From b2235b5ca20e59e60f7065e571375d6d42246afd Mon Sep 17 00:00:00 2001 From: James Linse <jameslinse@gmail.com> Date: Wed, 16 Sep 2009 14:16:21 +0200 Subject: [PATCH] Fixed yanking and deleting using marks ma "ay'a Fixed yanking with e (ye) Fixed ce followed by . Initial implementation for mark updates (marks should stay on the same line after adding/deleting lines) Fixed yank with Y Added fakevim tests for yanking using marks and yanking using Y. Fixed yanking with marks when a mark was set to a blank line. Combined yy and Y to use the same yanking method. Merge-request: 1314 Reviewed-by: hjk <qtc-committer@nokia.com> --- src/plugins/fakevim/fakevimhandler.cpp | 105 ++++++++++++++++++------- tests/auto/fakevim/main.cpp | 20 +++++ 2 files changed, 96 insertions(+), 29 deletions(-) diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index ee3e3216e1a..49bf5df7932 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -249,6 +249,7 @@ public: bool wantsOverride(QKeyEvent *ev); void handleCommand(const QString &cmd); // sets m_tc + handleExCommand void handleExCommand(const QString &cmd); + void fixMarks(int positionAction, int positionChange); //Updates marks positions by the difference in positionChange void installEventFilter(); void setupWidget(); @@ -746,10 +747,12 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand) enterInsertMode(); m_submode = NoSubMode; } else if (m_submode == DeleteSubMode) { - if (m_movetype == MoveInclusive) - moveRight(); // correction - if (anchor() >= position()) - m_anchor++; + if (m_rangemode == RangeCharMode) { + if (m_movetype == MoveInclusive) + moveRight(); // correction + if (anchor() >= position()) + m_anchor++; + } if (!dotCommand.isEmpty()) setDotCommand("d" + dotCommand); yankSelectedText(); @@ -761,8 +764,13 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand) setTargetColumn(); } else if (m_submode == YankSubMode) { yankSelectedText(); - setPosition(m_savedYankPosition); m_submode = NoSubMode; + if (m_register != '"') { + setPosition(m_marks[m_register]); + moveToStartOfLine(); + } else { + setPosition(m_savedYankPosition); + } } else if (m_submode == ReplaceSubMode) { m_submode = NoSubMode; } else if (m_submode == IndentSubMode) { @@ -941,6 +949,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, } else if (m_submode == RegisterSubMode) { m_register = key; m_submode = NoSubMode; + m_rangemode = RangeLineMode; } else if (m_submode == ChangeSubMode && key == 'c') { // tested moveDown(count() - 1); moveToEndOfLine(); @@ -964,14 +973,6 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, moveToFirstNonBlankOnLine(); setTargetColumn(); finishMovement(); - } else if (m_submode == YankSubMode && key == 'y') { - m_movetype = MoveLineWise; - int endPos = firstPositionInLine(lineForPosition(position()) + count() - 1); - Range range(position(), endPos, RangeLineMode); - ///range.extendByLines(count() - 1); - yankText(range); - m_submode = NoSubMode; - finishMovement(); } else if (m_submode == ShiftLeftSubMode && key == '<') { setAnchor(); moveDown(count() - 1); @@ -1232,9 +1233,16 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, } else if (key == control('c')) { showBlackMessage("Type Alt-v,Alt-v to quit FakeVim mode"); } else if (key == 'd' && m_visualMode == NoVisualMode) { - if (atEndOfLine()) - moveLeft(); - setAnchor(); + if (m_rangemode == RangeLineMode) { + m_savedYankPosition = m_tc.position(); + moveToEndOfLine(); + setAnchor(); + setPosition(m_savedYankPosition); + } else { + if (atEndOfLine()) + moveLeft(); + setAnchor(); + } m_opcount = m_mvcount; m_mvcount.clear(); m_submode = DeleteSubMode; @@ -1271,7 +1279,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, } else if (key == 'e') { // tested m_movetype = MoveInclusive; moveToWordBoundary(false, true); - finishMovement(); + finishMovement("e"); } else if (key == 'E') { m_movetype = MoveInclusive; moveToWordBoundary(true, true); @@ -1512,13 +1520,30 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, removeSelectedText(); } finishMovement(); + } else if ((m_submode == YankSubMode && key == 'y') + || (key == 'Y' && m_visualMode == NoVisualMode)) { + const int line = cursorLineInDocument() + 1; + m_savedYankPosition = position(); + setAnchor(firstPositionInLine(line)); + setPosition(lastPositionInLine(line+count() - 1)); + if (count() > 1) + showBlackMessage(QString("%1 lines yanked").arg(count())); + m_rangemode = RangeLineMode; + m_movetype = MoveLineWise; + m_submode = YankSubMode; + finishMovement(); } else if (key == 'y' && m_visualMode == NoVisualMode) { - m_savedYankPosition = m_tc.position(); - if (atEndOfLine()) - moveLeft(); - setAnchor(); + if (m_rangemode == RangeLineMode) { + m_savedYankPosition = position(); + setAnchor(firstPositionInLine(cursorLineInDocument() + 1)); + } else { + m_savedYankPosition = position(); + if (atEndOfLine()) + moveLeft(); + setAnchor(); + m_rangemode = RangeCharMode; + } m_submode = YankSubMode; - m_rangemode = RangeCharMode; } else if (key == 'y' && m_visualMode == VisualCharMode) { Range range(position(), anchor(), RangeCharMode); range.endPos++; // MoveInclusive @@ -1526,13 +1551,6 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, setPosition(qMin(position(), anchor())); leaveVisualMode(); finishMovement(); - } else if (key == 'Y' && m_visualMode == NoVisualMode) { - const int line = cursorLineInDocument() + 1; - selectRange(line, line + count() - 1); - m_rangemode = RangeLineMode; - yankSelectedText(); - setPosition(qMin(position(), anchor())); - finishMovement(); } else if ((key == 'y' && m_visualMode == VisualLineMode) || (key == 'Y' && m_visualMode == VisualLineMode) || (key == 'Y' && m_visualMode == VisualCharMode)) { @@ -2476,6 +2494,12 @@ QString FakeVimHandler::Private::text(const Range &range) const tc.setPosition(range.endPos, KeepAnchor); return tc.selection().toPlainText(); } + if (range.rangemode == RangeLineMode) { + QTextCursor tc = m_tc; + tc.setPosition(firstPositionInLine(lineForPosition(range.beginPos)), MoveAnchor); + tc.setPosition(firstPositionInLine(lineForPosition(range.endPos)+1), KeepAnchor); + return tc.selection().toPlainText(); + } // FIXME: Performance? int beginLine = lineForPosition(range.beginPos); int endLine = lineForPosition(range.endPos); @@ -2536,6 +2560,7 @@ void FakeVimHandler::Private::removeText(const Range &range) case RangeCharMode: { tc.setPosition(range.beginPos, MoveAnchor); tc.setPosition(range.endPos, KeepAnchor); + fixMarks(range.beginPos, tc.selectionStart() - tc.selectionEnd()); tc.removeSelectedText(); return; } @@ -2545,6 +2570,7 @@ void FakeVimHandler::Private::removeText(const Range &range) tc.setPosition(range.endPos, KeepAnchor); tc.movePosition(EndOfLine, KeepAnchor); tc.movePosition(Right, KeepAnchor, 1); + fixMarks(range.beginPos, tc.selectionStart() - tc.selectionEnd()); tc.removeSelectedText(); return; } @@ -2564,6 +2590,7 @@ void FakeVimHandler::Private::removeText(const Range &range) int eCol = qMin(endColumn, block.length() - 1); tc.setPosition(block.position() + bCol, MoveAnchor); tc.setPosition(block.position() + eCol, KeepAnchor); + fixMarks(block.position() + bCol, tc.selectionStart() - tc.selectionEnd()); tc.removeSelectedText(); block = block.previous(); } @@ -2582,6 +2609,7 @@ void FakeVimHandler::Private::pasteText(bool afterCursor) for (int i = count(); --i >= 0; ) { if (afterCursor && rightDist() > 0) moveRight(); + fixMarks(position(), text.length()); m_tc.insertText(text); moveLeft(); } @@ -2593,6 +2621,7 @@ void FakeVimHandler::Private::pasteText(bool afterCursor) for (int i = count(); --i >= 0; ) { if (afterCursor) moveDown(); + fixMarks(position(), text.length()); m_tc.insertText(text); moveUp(lines.size() - 1); } @@ -2611,16 +2640,19 @@ void FakeVimHandler::Private::pasteText(bool afterCursor) tc.movePosition(StartOfLine, MoveAnchor); if (col >= block.length()) { tc.movePosition(EndOfLine, MoveAnchor); + fixMarks(position(), QString(col - line.size() + 1, QChar(' ')).length()); tc.insertText(QString(col - line.size() + 1, QChar(' '))); } else { tc.movePosition(Right, MoveAnchor, col); } qDebug() << "INSERT " << line << " AT " << tc.position() << "COL: " << col; + fixMarks(position(), line.length()); tc.insertText(line); tc.movePosition(StartOfLine, MoveAnchor); tc.movePosition(Down, MoveAnchor, 1); if (tc.position() >= lastPositionInDocument() - 1) { + fixMarks(position(), QString(QChar('\n')).length()); tc.insertText(QString(QChar('\n'))); tc.movePosition(Up, MoveAnchor, 1); } @@ -2632,6 +2664,21 @@ void FakeVimHandler::Private::pasteText(bool afterCursor) } } +//FIXME: This needs to called after undo/insert +void FakeVimHandler::Private::fixMarks(int positionAction, int positionChange) +{ + QHashIterator<int, int> i(m_marks); + while (i.hasNext()) { + i.next(); + if (i.value() >= positionAction) { + if (i.value() + positionChange > 0) + m_marks[i.key()] = i.value() + positionChange; + else + m_marks.remove(i.key()); + } + } +} + int FakeVimHandler::Private::firstPositionInLine(int line) const { return m_tc.document()->findBlockByNumber(line - 1).position(); diff --git a/tests/auto/fakevim/main.cpp b/tests/auto/fakevim/main.cpp index cf674adcbe7..d3e71f5032b 100644 --- a/tests/auto/fakevim/main.cpp +++ b/tests/auto/fakevim/main.cpp @@ -73,7 +73,9 @@ private slots: void command_up(); void command_w(); void command_yyp(); + void command_Yp(); void command_Gyyp(); + void command_ma_yank(); // special tests void test_i_cw_i(); @@ -485,6 +487,24 @@ void tst_FakeVim::command_yyp() check("yyp", lmid(0, 4) + "\n" + lmid(4, 1) + "\n@" + lmid(4)); } +void tst_FakeVim::command_Yp() +{ + setup(); + move("4j", "@int main"); + check("Yp", lmid(0, 4) + "\n" + lmid(4, 1) + "\n@" + lmid(4)); +} + +void tst_FakeVim::command_ma_yank() +{ + setup(); + check("ma", "@" + lmid(0)); + move("4j", "@int main"); + check("mb", lmid(0,4) + "\n@" + lmid(4)); + check("\"ay'a", "@" + lmid(0)); + check("'b", lmid(0,4) + "\n@" + lmid(4)); + check("\"ap", lmid(0,5) + "\n@" + lmid(0,4) +"\n" + lmid(4)); +} + void tst_FakeVim::command_Gyyp() { qWarning("FIXME"); -- GitLab