From a636a933d0a1f4dfd5a021c94c057f14d3a6bbf8 Mon Sep 17 00:00:00 2001 From: hluk <hluk@email.cz> Date: Sun, 15 Sep 2013 16:19:05 +0200 Subject: [PATCH] FakeVim: Fix searching in visual mode and with commands Search in visual mode should select text up to matched position. Using commands should work with search movement; e.g. 'd2/needle<CR>'. Commands should be also properly canceled if search movement fails. Change-Id: Ic695dccaf3f36ccae2f2b1a93f888d5ba9805a78 Reviewed-by: hjk <hjk121@nokiamail.com> --- src/plugins/fakevim/fakevim_test.cpp | 26 ++++++++ src/plugins/fakevim/fakevimhandler.cpp | 91 +++++++++++++++++--------- src/plugins/fakevim/fakevimplugin.cpp | 13 ---- 3 files changed, 87 insertions(+), 43 deletions(-) diff --git a/src/plugins/fakevim/fakevim_test.cpp b/src/plugins/fakevim/fakevim_test.cpp index 2e20323d987..6b9144da5d9 100644 --- a/src/plugins/fakevim/fakevim_test.cpp +++ b/src/plugins/fakevim/fakevim_test.cpp @@ -1472,6 +1472,32 @@ void FakeVimPlugin::test_vim_search() KEYS("N", "abc" N X "def" N "ghi"); KEYS("N", X "abc" N "def" N "ghi"); KEYS("2n2N", X "abc" N "def" N "ghi"); + + // delete to match + data.setText("abc" N "def" N "abc" N "ghi abc jkl" N "xyz"); + KEYS("2l" "d/ghi<CR>", "ab" X "ghi abc jkl" N "xyz"); + + data.setText("abc" N "def" N "abc" N "ghi abc jkl" N "xyz"); + KEYS("l" "d2/abc<CR>", "a" X "abc jkl" N "xyz"); + + data.setText("abc" N "def" N "abc" N "ghi abc jkl" N "xyz"); + KEYS("d/abc<CR>", X "abc" N "ghi abc jkl" N "xyz"); + KEYS(".", "abc jkl" N "xyz"); + + data.setText("abc" N "def" N "abc" N "ghi abc jkl" N "xyz"); + KEYS("/abc<CR>" "l" "dn", "abc" N "def" N "a" X "abc jkl" N "xyz"); + + data.setText("abc" N "def" N "abc" N "ghi abc jkl" N "xyz"); + KEYS("2/abc<CR>" "h" "dN", "abc" N "def" N X " abc jkl" N "xyz"); + KEYS("c/xxx<CR><ESC>" "h" "dN", "abc" N "def" N X " abc jkl" N "xyz"); + + data.setText("abc" N "def" N "abc" N "ghi abc jkl" N "xyz"); + KEYS("l" "v2/abc<CR>" "x", "abc jkl" N "xyz"); + + // don't leave visual mode after search failed or is cancelled + data.setText("abc" N "def" N "abc" N "ghi abc jkl" N "xyz"); + KEYS("vj" "/abc<ESC>" "x", X "ef" N "abc" N "ghi abc jkl" N "xyz"); + KEYS("vj" "/xxx<CR>" "x", X "bc" N "ghi abc jkl" N "xyz"); } void FakeVimPlugin::test_vim_indent() diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 0b49f6831f2..782333cc9f9 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -1524,12 +1524,13 @@ public: EventResult handleSearchSubSubMode(const Input &); bool handleCommandSubSubMode(const Input &); void fixSelection(); // Fix selection according to current range, move and command modes. + bool finishSearch(); void finishMovement(const QString &dotCommandMovement = QString()); void resetCommandMode(); void clearCommandMode(); QTextCursor search(const SearchData &sd, int startPos, int count, bool showMessages); void search(const SearchData &sd, bool showMessages = true); - void searchNext(bool forward = true); + bool searchNext(bool forward = true); void searchBalanced(bool forward, QChar needle, QChar other); void highlightMatches(const QString &needle); void stopIncrementalFind(); @@ -2096,15 +2097,32 @@ void FakeVimHandler::Private::init() void FakeVimHandler::Private::focus() { + if (g.inFakeVim) + return; + + enterFakeVim(); + stopIncrementalFind(); if (!isInsertMode()) { - leaveVisualMode(); + if (g.subsubmode == SearchSubSubMode) { + setPosition(m_searchStartPosition); + scrollToLine(m_searchFromScreenLine); + setTargetColumn(); + } else { + leaveVisualMode(); + } + + bool exitCommandLine = (g.subsubmode == SearchSubSubMode || g.mode == ExMode); resetCommandMode(); + if (exitCommandLine) + updateMiniBuffer(); } updateCursorShape(); - if (!g.inFakeVim || g.mode != CommandMode) + if (g.mode != CommandMode) updateMiniBuffer(); updateHighlights(); + + leaveFakeVim(); } void FakeVimHandler::Private::enterFakeVim() @@ -2726,14 +2744,16 @@ void FakeVimHandler::Private::updateFind(bool isComplete) g.currentMessage.clear(); const QString &needle = g.searchBuffer.contents(); + if (isComplete) { + setPosition(m_searchStartPosition); + if (!needle.isEmpty()) + recordJump(); + } + SearchData sd; sd.needle = needle; sd.forward = g.lastSearchForward; sd.highlightMatches = isComplete; - if (isComplete) { - setPosition(m_searchStartPosition); - recordJump(); - } search(sd, isComplete); } @@ -3018,6 +3038,17 @@ void FakeVimHandler::Private::fixSelection() } } +bool FakeVimHandler::Private::finishSearch() +{ + if (g.lastSearch.isEmpty() + || (!g.currentMessage.isEmpty() && g.currentMessageLevel == MessageError)) { + return false; + } + if (g.submode != NoSubMode) + setAnchorAndPosition(m_searchStartPosition, position()); + return true; +} + void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement) { //dump("FINISH MOVEMENT"); @@ -3488,7 +3519,7 @@ bool FakeVimHandler::Private::handleMovement(const Input &input) g.searchBuffer.historyPush(needle); g.lastSearch = needle; g.lastSearchForward = input.is('*'); - searchNext(); + handled = searchNext(); } else if (input.is('\'')) { g.subsubmode = TickSubSubMode; if (g.submode != NoSubMode) @@ -3655,7 +3686,7 @@ bool FakeVimHandler::Private::handleMovement(const Input &input) } setPosition(m_cursor.selectionStart()); } else { - searchNext(input.is('n')); + handled = searchNext(input.is('n')); } } else if (input.is('t')) { g.movetype = MoveInclusive; @@ -4378,6 +4409,7 @@ bool FakeVimHandler::Private::handleWindowSubMode(const Input &input) if (handleCount(input)) return true; + leaveVisualMode(); emit q->windowCommandRequested(input.toString(), count()); g.submode = NoSubMode; @@ -4811,7 +4843,6 @@ EventResult FakeVimHandler::Private::handleExMode(const Input &input) { if (input.isEscape()) { g.commandBuffer.clear(); - enterCommandMode(g.returnToMode); resetCommandMode(); m_ctrlVActive = false; } else if (m_ctrlVActive) { @@ -4822,7 +4853,7 @@ EventResult FakeVimHandler::Private::handleExMode(const Input &input) return EventHandled; } else if (input.isBackspace()) { if (g.commandBuffer.isEmpty()) { - enterCommandMode(g.returnToMode); + leaveVisualMode(); resetCommandMode(); } else if (g.commandBuffer.hasSelection()) { g.commandBuffer.deleteSelected(); @@ -4852,11 +4883,8 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input) if (input.isEscape()) { g.currentMessage.clear(); - g.searchBuffer.clear(); - setAnchorAndPosition(m_searchStartPosition, m_searchStartPosition); + setPosition(m_searchStartPosition); scrollToLine(m_searchFromScreenLine); - enterCommandMode(g.returnToMode); - resetCommandMode(); } else if (input.isBackspace()) { if (g.searchBuffer.isEmpty()) resetCommandMode(); @@ -4868,19 +4896,17 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input) g.lastSearch = needle; else g.searchBuffer.setContents(g.lastSearch); - if (!g.lastSearch.isEmpty()) { - updateFind(true); - finishMovement(g.searchBuffer.prompt() + g.lastSearch + QLatin1Char('\n')); + + updateFind(true); + + if (finishSearch()) { + if (g.submode != NoSubMode) + finishMovement(g.searchBuffer.prompt() + g.lastSearch + QLatin1Char('\n')); + if (g.currentMessage.isEmpty()) + showMessage(MessageCommand, g.searchBuffer.display()); } else { - finishMovement(); - } - if (g.currentMessage.isEmpty()) - showMessage(MessageCommand, g.searchBuffer.display()); - else if (g.currentMessageLevel == MessageError) handled = EventCancelled; // Not found so cancel mapping if any. - enterCommandMode(g.returnToMode); - resetCommandMode(); - g.searchBuffer.clear(); + } } else if (input.isKey(Key_Tab)) { g.searchBuffer.insertChar(QChar(9)); } else if (!g.searchBuffer.handleInput(input)) { @@ -4888,10 +4914,14 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input) return EventUnhandled; } - updateMiniBuffer(); - - if (!input.isReturn() && !input.isEscape()) + if (input.isReturn() || input.isEscape()) { + g.searchBuffer.clear(); + resetCommandMode(); + updateMiniBuffer(); + } else { + updateMiniBuffer(); updateFind(false); + } return handled; } @@ -5963,7 +5993,7 @@ void FakeVimHandler::Private::search(const SearchData &sd, bool showMessages) setTargetColumn(); } -void FakeVimHandler::Private::searchNext(bool forward) +bool FakeVimHandler::Private::searchNext(bool forward) { SearchData sd; sd.needle = g.lastSearch; @@ -5973,6 +6003,7 @@ void FakeVimHandler::Private::searchNext(bool forward) showMessage(MessageCommand, QLatin1Char(g.lastSearchForward ? '/' : '?') + sd.needle); recordJump(); search(sd); + return finishSearch(); } void FakeVimHandler::Private::highlightMatches(const QString &needle) diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index b43be12888a..e3836c178f1 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -122,7 +122,6 @@ class MiniBuffer : public QStackedWidget public: MiniBuffer() : m_label(new QLabel(this)), m_edit(new QLineEdit(this)), m_eventFilter(0) { - m_edit->installEventFilter(this); connect(m_edit, SIGNAL(textEdited(QString)), SLOT(changed())); connect(m_edit, SIGNAL(cursorPositionChanged(int,int)), SLOT(changed())); connect(m_edit, SIGNAL(selectionChanged()), SLOT(changed())); @@ -206,18 +205,6 @@ private slots: emit edited(m_edit->text(), cursorPos, anchorPos); } - bool eventFilter(QObject *ob, QEvent *ev) - { - // cancel editing on escape - if (m_eventFilter != 0 && ob == m_edit && ev->type() == QEvent::ShortcutOverride - && static_cast<QKeyEvent*>(ev)->key() == Qt::Key_Escape) { - emit edited(QString(), -1, -1); - ev->accept(); - return true; - } - return false; - } - private: QLabel *m_label; QLineEdit *m_edit; -- GitLab