diff options
Diffstat (limited to 'src/plugins/fakevim/fakevimhandler.cpp')
-rw-r--r-- | src/plugins/fakevim/fakevimhandler.cpp | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index fe3f2262e51..5c393a714c4 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -168,6 +168,7 @@ enum SubMode NoSubMode, ChangeSubMode, // Used for c DeleteSubMode, // Used for d + ExchangeSubMode, // Used for cx FilterSubMode, // Used for ! IndentSubMode, // Used for = RegisterSubMode, // Used for " @@ -1346,6 +1347,8 @@ QString dotCommandFromSubMode(SubMode submode) return QLatin1String("d"); if (submode == CommentSubMode) return QLatin1String("gc"); + if (submode == ExchangeSubMode) + return QLatin1String("cx"); if (submode == ReplaceWithRegisterSubMode) return QLatin1String("gr"); if (submode == InvertCaseSubMode) @@ -1830,6 +1833,7 @@ public: bool handleReplaceSubMode(const Input &); bool handleCommentSubMode(const Input &); bool handleReplaceWithRegisterSubMode(const Input &); + bool handleExchangeSubMode(const Input &); bool handleFilterSubMode(const Input &); bool handleRegisterSubMode(const Input &); bool handleShiftSubMode(const Input &); @@ -2092,6 +2096,7 @@ public: bool isOperatorPending() const { return g.submode == ChangeSubMode || g.submode == DeleteSubMode + || g.submode == ExchangeSubMode || g.submode == CommentSubMode || g.submode == ReplaceWithRegisterSubMode || g.submode == FilterSubMode @@ -2171,6 +2176,8 @@ public: void toggleComment(const Range &range); + void exchangeRange(const Range &range); + void replaceWithRegister(const Range &range); void upCase(const Range &range); @@ -2409,6 +2416,10 @@ public: QString recorded; int currentRegister = 0; int lastExecutedRegister = 0; + + // If empty, cx{motion} will store the range defined by {motion} here. + // If non-empty, cx{motion} replaces the {motion} with selectText(*exchangeData) + std::optional<Range> exchangeRange; } g; }; @@ -3597,6 +3608,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement) if (g.submode == ChangeSubMode || g.submode == DeleteSubMode || g.submode == CommentSubMode + || g.submode == ExchangeSubMode || g.submode == ReplaceWithRegisterSubMode || g.submode == YankSubMode || g.submode == InvertCaseSubMode @@ -3629,6 +3641,8 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement) beginEditBlock(); toggleComment(currentRange()); endEditBlock(); + } else if (g.submode == ExchangeSubMode) { + exchangeRange(currentRange()); } else if (g.submode == ReplaceWithRegisterSubMode && hasConfig(ConfigEmulateReplaceWithRegister)) { pushUndoState(false); @@ -4281,6 +4295,12 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input) handled = handleCommandSubSubMode(input); } else if (g.submode == NoSubMode) { handled = handleNoSubMode(input); + } else if (g.submode == ExchangeSubMode) { + handled = handleExchangeSubMode(input); + } else if (g.submode == ChangeSubMode && input.is('x') && hasConfig(ConfigEmulateExchange)) { + // Exchange submode is "cx", so we need to switch over from ChangeSubMode here + g.submode = ExchangeSubMode; + handled = true; } else if (g.submode == ChangeSubMode || g.submode == DeleteSubMode || g.submode == YankSubMode) { @@ -4842,6 +4862,30 @@ bool FakeVimHandler::Private::handleReplaceWithRegisterSubMode(const Input &inpu return true; } +bool FakeVimHandler::Private::handleExchangeSubMode(const Input &input) +{ + if (input.is('c')) { // cxc + g.exchangeRange.reset(); + g.submode = NoSubMode; + return true; + } + + if (input.is('x')) { // cxx + setAnchorAndPosition(firstPositionInLine(cursorLine() + 1), + lastPositionInLine(cursorLine() + 1) + 1); + + setDotCommand("cxx"); + + finishMovement(); + + g.submode = NoSubMode; + + return true; + } + + return false; +} + bool FakeVimHandler::Private::handleFilterSubMode(const Input &) { return false; @@ -7484,6 +7528,32 @@ void FakeVimHandler::Private::toggleComment(const Range &range) }); } +void FakeVimHandler::Private::exchangeRange(const Range &range) +{ + if (g.exchangeRange) { + pushUndoState(false); + beginEditBlock(); + + Range leftRange = *g.exchangeRange; + Range rightRange = range; + if (leftRange.beginPos > rightRange.beginPos) + std::swap(leftRange, rightRange); + + // First replace the right range, then left one + // If we did it the other way around, we would invalidate the positions + // of the right range + const QString rightText = selectText(rightRange); + replaceText(rightRange, selectText(leftRange)); + replaceText(leftRange, rightText); + + g.exchangeRange.reset(); + + endEditBlock(); + } else { + g.exchangeRange = range; + } +} + void FakeVimHandler::Private::replaceWithRegister(const Range &range) { replaceText(range, registerContents(m_register)); |