diff --git a/src/plugins/fakevim/fakevim_test.cpp b/src/plugins/fakevim/fakevim_test.cpp index 47cb3c5d4c9..2f9a56b8ca7 100644 --- a/src/plugins/fakevim/fakevim_test.cpp +++ b/src/plugins/fakevim/fakevim_test.cpp @@ -192,8 +192,12 @@ struct FakeVimPlugin::TestData QString text() const { return editor()->toPlainText(); } + void doCommand(const QString &cmd) { handler->handleCommand(cmd); } + void doKeys(const QString &keys) { handler->handleInput(keys); } + void setText(const QString &text) { + doKeys(""); QString str = text; int i = str.indexOf(cursorString); if (!cursorString.isEmpty() && i != -1) @@ -202,9 +206,6 @@ struct FakeVimPlugin::TestData setPosition(i); } - void doCommand(const QString &cmd) { handler->handleCommand(cmd); } - void doKeys(const QString &keys) { handler->handleInput(keys); } - int lines() const { QTextDocument *doc = editor()->document(); @@ -550,6 +551,27 @@ void FakeVimPlugin::test_vim_delete() // delete in empty document data.setText(""); KEYS("dd", X); + + // delete to start of line + data.setText(" abc" N " de" X "f" N " ghi"); + KEYS("d0", " abc" N X "f" N " ghi"); + INTEGRITY(false); + data.setText(" abc" N " de" X "f" N " ghi"); + KEYS("d^", " abc" N " " X "f" N " ghi"); + INTEGRITY(false); + + // delete to mark + data.setText("abc " X "def ghi"); + KEYS("ma" "3l" "d`a", "abc " X " ghi"); + KEYS("u" "gg" "d`a", X "def ghi"); + + // delete lines + data.setText(" abc" N " de" X "f" N " ghi" N " jkl"); + KEYS("dj", " abc" N " " X "jkl"); + INTEGRITY(false); + data.setText(" abc" N " def" N " gh" X "i" N " jkl"); + KEYS("dk", " abc" N " " X "jkl"); + INTEGRITY(false); } void FakeVimPlugin::test_vim_delete_inner_word() @@ -724,6 +746,27 @@ void FakeVimPlugin::test_vim_change_replace() " int j = 1;" X N "}" N ""); + + // change to start of line + data.setText(" abc" N " de" X "f" N " ghi"); + KEYS("c0123", " abc" N "12" X "3f" N " ghi"); + INTEGRITY(false); + data.setText(" abc" N " de" X "f" N " ghi"); + KEYS("c^123", " abc" N " 12" X "3f" N " ghi"); + INTEGRITY(false); + + // change to mark + data.setText("abc " X "def ghi"); + KEYS("ma" "3l" "c`a123", "abc 12" X "3 ghi"); + KEYS("u" "gg" "c`a123", "12" X "3def ghi"); + + // change lines + data.setText(" abc" N " de" X "f" N " ghi" N " jkl"); + KEYS("cj123", " abc" N " 12" X "3" N " jkl"); + INTEGRITY(false); + data.setText(" abc" N " def" N " gh" X "i" N " jkl"); + KEYS("ck123", " abc" N " 12" X "3" N " jkl"); + INTEGRITY(false); } void FakeVimPlugin::test_vim_block_selection() diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 4ddd471511e..a7a9669c6d9 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -2286,7 +2286,7 @@ void FakeVimHandler::Private::moveToStartOfLine() void FakeVimHandler::Private::fixSelection() { if (m_movetype == MoveExclusive) { - if (anchor() != position() && atBlockStart()) { + if (anchor() < position() && atBlockStart()) { // Exlusive motion ending at the beginning of line // becomes inclusive and end is moved to end of previous line. m_movetype = MoveInclusive; @@ -2391,8 +2391,8 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement) QString dotCommand; if (m_submode == ChangeSubMode) { - if (m_rangemode == RangeLineMode) - m_rangemode = RangeLineModeExclusive; + if (m_rangemode != RangeLineModeExclusive) + setUndoPosition(); removeText(currentRange()); dotCommand = QString('c'); if (m_movetype == MoveLineWise) @@ -2401,8 +2401,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement) enterInsertMode(); } else if (m_submode == DeleteSubMode) { setUndoPosition(); - Range range = currentRange(); - removeText(range); + removeText(currentRange()); dotCommand = QString('d'); if (m_movetype == MoveLineWise) handleStartOfLine(); @@ -2904,8 +2903,6 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input) } } else if (input.is('`')) { m_subsubmode = BackTickSubSubMode; - if (m_submode != NoSubMode) - m_movetype = MoveLineWise; } else if (input.is('#') || input.is('*')) { // FIXME: That's not proper vim behaviour QString needle; @@ -3047,12 +3044,12 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input) moveToNextWordStart(count(), true, false); setTargetColumn(); finishMovement(); - } else if (input.is('c') && isNoVisualMode()) { - setUndoPosition(); - if (atEndOfLine()) - moveLeft(); + } else if ((input.is('c') || input.is('d')) && isNoVisualMode()) { setAnchor(); - m_submode = ChangeSubMode; + m_opcount = m_mvcount; + m_mvcount.clear(); + m_movetype = MoveExclusive; + m_submode = input.is('c') ? ChangeSubMode : DeleteSubMode; } else if ((input.is('c') || input.is('C') || input.is('s') || input.is('R')) && (isVisualCharMode() || isVisualLineMode())) { setDotCommand(visualDotCommand() + input.asChar()); @@ -3078,18 +3075,6 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input) showMessage(MessageInfo, "Type Alt-v,Alt-v to quit FakeVim mode"); else leaveVisualMode(); - } else if (input.is('d') && isNoVisualMode()) { - if (m_rangemode == RangeLineMode) { - int pos = position(); - moveToEndOfLine(); - setAnchor(); - setPosition(pos); - } else { - setAnchor(); - } - m_opcount = m_mvcount; - m_mvcount.clear(); - m_submode = DeleteSubMode; } else if ((input.is('d') || input.is('x') || input.isKey(Key_Delete)) && isVisualMode()) { setUndoPosition(); @@ -3501,6 +3486,7 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input) finishMovement(); } else if (input.is('y') && isNoVisualMode()) { setAnchor(); + m_movetype = MoveExclusive; m_submode = YankSubMode; } else if (input.is('y') && isVisualCharMode()) { Range range(position(), anchor(), RangeCharMode); @@ -6569,7 +6555,8 @@ bool FakeVimHandler::Private::jumpToMark(QChar mark, bool backTickMode) setCursorPosition(m.position); if (!backTickMode) moveToFirstNonBlankOnLine(); - setAnchor(); + if (m_submode == NoSubMode) + setAnchor(); setTargetColumn(); return true;