From 11f06bf617d51e313eb0126b5255df576d2561bc Mon Sep 17 00:00:00 2001 From: Le Tan Date: Tue, 27 Jun 2017 22:03:41 +0800 Subject: [PATCH] vim-mode: bug fixes 1. Enable repeat in f/t/F/T movement; 2. Make cw/W behave like ce/E; --- src/utils/veditutils.cpp | 26 ++++++++++++++------------ src/utils/veditutils.h | 5 +++-- src/utils/vvim.cpp | 24 +++++++++++++++++++++--- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/utils/veditutils.cpp b/src/utils/veditutils.cpp index 9373be2e..55696753 100644 --- a/src/utils/veditutils.cpp +++ b/src/utils/veditutils.cpp @@ -215,26 +215,34 @@ bool VEditUtils::findTargetWithinBlock(QTextCursor &p_cursor, QTextCursor::MoveMode p_mode, QChar p_target, bool p_forward, - bool p_inclusive) + bool p_inclusive, + int p_repeat) { - qDebug() << "find target" << p_target << p_forward << p_inclusive; + if (p_repeat < 1) { + return false; + } + QTextBlock block = p_cursor.block(); QString text = block.text(); int pib = p_cursor.positionInBlock(); int delta = p_forward ? 1 : -1; - int idx = pib + delta; -repeat: + // The index to start searching. + int idx = pib + (p_inclusive ? delta : 2 * delta); + for (; idx < text.size() && idx >= 0; idx += delta) { if (text[idx] == p_target) { - break; + if (--p_repeat == 0) { + break; + } } } - if (idx < 0 || idx >= text.size()) { + if (idx < 0 || idx >= text.size() || p_repeat > 0) { return false; } + // text[idx] is the target character. if ((p_forward && p_inclusive && p_mode == QTextCursor::KeepAnchor) || (!p_forward && !p_inclusive)) { ++idx; @@ -242,12 +250,6 @@ repeat: --idx; } - if (idx == pib) { - // We need to skip current match. - idx = pib + delta * 2; - goto repeat; - } - p_cursor.setPosition(block.position() + idx, p_mode); return true; } diff --git a/src/utils/veditutils.h b/src/utils/veditutils.h index 691b6396..7e521bbd 100644 --- a/src/utils/veditutils.h +++ b/src/utils/veditutils.h @@ -65,13 +65,14 @@ public: static void unindentBlock(QTextCursor &p_cursor, const QString &p_indentationText); - // Find a char within a block. + // Find @p_repeat th occurence a char within a block. // Returns true if target is found. static bool findTargetWithinBlock(QTextCursor &p_cursor, QTextCursor::MoveMode p_mode, QChar p_target, bool p_forward, - bool p_inclusive); + bool p_inclusive, + int p_repeat); // Get the count of blocks selected. static int selectedBlockCount(const QTextCursor &p_cursor); diff --git a/src/utils/vvim.cpp b/src/utils/vvim.cpp index 53cf950b..db63064b 100644 --- a/src/utils/vvim.cpp +++ b/src/utils/vvim.cpp @@ -1206,7 +1206,17 @@ bool VVim::handleKeyPressEvent(int key, int modifiers, bool *p_autoIndented) mm = Movement::WORDForward; } - tryAddMoveAction(); + if (checkActionToken(Action::Change)) { + // In Change action, cw equals to ce. + if (shift) { + mm = Movement::ForwardEndOfWORD; + } else { + mm = Movement::ForwardEndOfWord; + } + } else { + tryAddMoveAction(); + } + addMovementToken(mm); processCommand(m_tokens); break; @@ -2322,11 +2332,19 @@ bool VVim::processMovement(QTextCursor &p_cursor, const QTextDocument *p_doc, case Movement::FindForward: { handle_target: + if (p_repeat == -1) { + p_repeat = 1; + } + const Key &key = p_token.m_key; QChar target = keyToChar(key.m_key, key.m_modifiers); if (!target.isNull()) { - hasMoved = VEditUtils::findTargetWithinBlock(p_cursor, p_moveMode, - target, forward, inclusive); + hasMoved = VEditUtils::findTargetWithinBlock(p_cursor, + p_moveMode, + target, + forward, + inclusive, + p_repeat); } break;