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>
This commit is contained in:
hluk
2013-09-15 16:19:05 +02:00
committed by hjk
parent 8c7a9a51ec
commit a636a933d0
3 changed files with 87 additions and 43 deletions

View File

@@ -1472,6 +1472,32 @@ void FakeVimPlugin::test_vim_search()
KEYS("N", "abc" N X "def" N "ghi"); KEYS("N", "abc" N X "def" N "ghi");
KEYS("N", X "abc" N "def" N "ghi"); KEYS("N", X "abc" N "def" N "ghi");
KEYS("2n2N", 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() void FakeVimPlugin::test_vim_indent()

View File

@@ -1524,12 +1524,13 @@ public:
EventResult handleSearchSubSubMode(const Input &); EventResult handleSearchSubSubMode(const Input &);
bool handleCommandSubSubMode(const Input &); bool handleCommandSubSubMode(const Input &);
void fixSelection(); // Fix selection according to current range, move and command modes. void fixSelection(); // Fix selection according to current range, move and command modes.
bool finishSearch();
void finishMovement(const QString &dotCommandMovement = QString()); void finishMovement(const QString &dotCommandMovement = QString());
void resetCommandMode(); void resetCommandMode();
void clearCommandMode(); void clearCommandMode();
QTextCursor search(const SearchData &sd, int startPos, int count, bool showMessages); QTextCursor search(const SearchData &sd, int startPos, int count, bool showMessages);
void search(const SearchData &sd, bool showMessages = true); 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 searchBalanced(bool forward, QChar needle, QChar other);
void highlightMatches(const QString &needle); void highlightMatches(const QString &needle);
void stopIncrementalFind(); void stopIncrementalFind();
@@ -2096,15 +2097,32 @@ void FakeVimHandler::Private::init()
void FakeVimHandler::Private::focus() void FakeVimHandler::Private::focus()
{ {
if (g.inFakeVim)
return;
enterFakeVim();
stopIncrementalFind(); stopIncrementalFind();
if (!isInsertMode()) { if (!isInsertMode()) {
if (g.subsubmode == SearchSubSubMode) {
setPosition(m_searchStartPosition);
scrollToLine(m_searchFromScreenLine);
setTargetColumn();
} else {
leaveVisualMode(); leaveVisualMode();
}
bool exitCommandLine = (g.subsubmode == SearchSubSubMode || g.mode == ExMode);
resetCommandMode(); resetCommandMode();
if (exitCommandLine)
updateMiniBuffer();
} }
updateCursorShape(); updateCursorShape();
if (!g.inFakeVim || g.mode != CommandMode) if (g.mode != CommandMode)
updateMiniBuffer(); updateMiniBuffer();
updateHighlights(); updateHighlights();
leaveFakeVim();
} }
void FakeVimHandler::Private::enterFakeVim() void FakeVimHandler::Private::enterFakeVim()
@@ -2726,14 +2744,16 @@ void FakeVimHandler::Private::updateFind(bool isComplete)
g.currentMessage.clear(); g.currentMessage.clear();
const QString &needle = g.searchBuffer.contents(); const QString &needle = g.searchBuffer.contents();
if (isComplete) {
setPosition(m_searchStartPosition);
if (!needle.isEmpty())
recordJump();
}
SearchData sd; SearchData sd;
sd.needle = needle; sd.needle = needle;
sd.forward = g.lastSearchForward; sd.forward = g.lastSearchForward;
sd.highlightMatches = isComplete; sd.highlightMatches = isComplete;
if (isComplete) {
setPosition(m_searchStartPosition);
recordJump();
}
search(sd, isComplete); 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) void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement)
{ {
//dump("FINISH MOVEMENT"); //dump("FINISH MOVEMENT");
@@ -3488,7 +3519,7 @@ bool FakeVimHandler::Private::handleMovement(const Input &input)
g.searchBuffer.historyPush(needle); g.searchBuffer.historyPush(needle);
g.lastSearch = needle; g.lastSearch = needle;
g.lastSearchForward = input.is('*'); g.lastSearchForward = input.is('*');
searchNext(); handled = searchNext();
} else if (input.is('\'')) { } else if (input.is('\'')) {
g.subsubmode = TickSubSubMode; g.subsubmode = TickSubSubMode;
if (g.submode != NoSubMode) if (g.submode != NoSubMode)
@@ -3655,7 +3686,7 @@ bool FakeVimHandler::Private::handleMovement(const Input &input)
} }
setPosition(m_cursor.selectionStart()); setPosition(m_cursor.selectionStart());
} else { } else {
searchNext(input.is('n')); handled = searchNext(input.is('n'));
} }
} else if (input.is('t')) { } else if (input.is('t')) {
g.movetype = MoveInclusive; g.movetype = MoveInclusive;
@@ -4378,6 +4409,7 @@ bool FakeVimHandler::Private::handleWindowSubMode(const Input &input)
if (handleCount(input)) if (handleCount(input))
return true; return true;
leaveVisualMode();
emit q->windowCommandRequested(input.toString(), count()); emit q->windowCommandRequested(input.toString(), count());
g.submode = NoSubMode; g.submode = NoSubMode;
@@ -4811,7 +4843,6 @@ EventResult FakeVimHandler::Private::handleExMode(const Input &input)
{ {
if (input.isEscape()) { if (input.isEscape()) {
g.commandBuffer.clear(); g.commandBuffer.clear();
enterCommandMode(g.returnToMode);
resetCommandMode(); resetCommandMode();
m_ctrlVActive = false; m_ctrlVActive = false;
} else if (m_ctrlVActive) { } else if (m_ctrlVActive) {
@@ -4822,7 +4853,7 @@ EventResult FakeVimHandler::Private::handleExMode(const Input &input)
return EventHandled; return EventHandled;
} else if (input.isBackspace()) { } else if (input.isBackspace()) {
if (g.commandBuffer.isEmpty()) { if (g.commandBuffer.isEmpty()) {
enterCommandMode(g.returnToMode); leaveVisualMode();
resetCommandMode(); resetCommandMode();
} else if (g.commandBuffer.hasSelection()) { } else if (g.commandBuffer.hasSelection()) {
g.commandBuffer.deleteSelected(); g.commandBuffer.deleteSelected();
@@ -4852,11 +4883,8 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input)
if (input.isEscape()) { if (input.isEscape()) {
g.currentMessage.clear(); g.currentMessage.clear();
g.searchBuffer.clear(); setPosition(m_searchStartPosition);
setAnchorAndPosition(m_searchStartPosition, m_searchStartPosition);
scrollToLine(m_searchFromScreenLine); scrollToLine(m_searchFromScreenLine);
enterCommandMode(g.returnToMode);
resetCommandMode();
} else if (input.isBackspace()) { } else if (input.isBackspace()) {
if (g.searchBuffer.isEmpty()) if (g.searchBuffer.isEmpty())
resetCommandMode(); resetCommandMode();
@@ -4868,19 +4896,17 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input)
g.lastSearch = needle; g.lastSearch = needle;
else else
g.searchBuffer.setContents(g.lastSearch); g.searchBuffer.setContents(g.lastSearch);
if (!g.lastSearch.isEmpty()) {
updateFind(true); updateFind(true);
if (finishSearch()) {
if (g.submode != NoSubMode)
finishMovement(g.searchBuffer.prompt() + g.lastSearch + QLatin1Char('\n')); finishMovement(g.searchBuffer.prompt() + g.lastSearch + QLatin1Char('\n'));
} else {
finishMovement();
}
if (g.currentMessage.isEmpty()) if (g.currentMessage.isEmpty())
showMessage(MessageCommand, g.searchBuffer.display()); showMessage(MessageCommand, g.searchBuffer.display());
else if (g.currentMessageLevel == MessageError) } else {
handled = EventCancelled; // Not found so cancel mapping if any. handled = EventCancelled; // Not found so cancel mapping if any.
enterCommandMode(g.returnToMode); }
resetCommandMode();
g.searchBuffer.clear();
} else if (input.isKey(Key_Tab)) { } else if (input.isKey(Key_Tab)) {
g.searchBuffer.insertChar(QChar(9)); g.searchBuffer.insertChar(QChar(9));
} else if (!g.searchBuffer.handleInput(input)) { } else if (!g.searchBuffer.handleInput(input)) {
@@ -4888,10 +4914,14 @@ EventResult FakeVimHandler::Private::handleSearchSubSubMode(const Input &input)
return EventUnhandled; return EventUnhandled;
} }
if (input.isReturn() || input.isEscape()) {
g.searchBuffer.clear();
resetCommandMode();
updateMiniBuffer();
} else {
updateMiniBuffer(); updateMiniBuffer();
if (!input.isReturn() && !input.isEscape())
updateFind(false); updateFind(false);
}
return handled; return handled;
} }
@@ -5963,7 +5993,7 @@ void FakeVimHandler::Private::search(const SearchData &sd, bool showMessages)
setTargetColumn(); setTargetColumn();
} }
void FakeVimHandler::Private::searchNext(bool forward) bool FakeVimHandler::Private::searchNext(bool forward)
{ {
SearchData sd; SearchData sd;
sd.needle = g.lastSearch; sd.needle = g.lastSearch;
@@ -5973,6 +6003,7 @@ void FakeVimHandler::Private::searchNext(bool forward)
showMessage(MessageCommand, QLatin1Char(g.lastSearchForward ? '/' : '?') + sd.needle); showMessage(MessageCommand, QLatin1Char(g.lastSearchForward ? '/' : '?') + sd.needle);
recordJump(); recordJump();
search(sd); search(sd);
return finishSearch();
} }
void FakeVimHandler::Private::highlightMatches(const QString &needle) void FakeVimHandler::Private::highlightMatches(const QString &needle)

View File

@@ -122,7 +122,6 @@ class MiniBuffer : public QStackedWidget
public: public:
MiniBuffer() : m_label(new QLabel(this)), m_edit(new QLineEdit(this)), m_eventFilter(0) 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(textEdited(QString)), SLOT(changed()));
connect(m_edit, SIGNAL(cursorPositionChanged(int,int)), SLOT(changed())); connect(m_edit, SIGNAL(cursorPositionChanged(int,int)), SLOT(changed()));
connect(m_edit, SIGNAL(selectionChanged()), SLOT(changed())); connect(m_edit, SIGNAL(selectionChanged()), SLOT(changed()));
@@ -206,18 +205,6 @@ private slots:
emit edited(m_edit->text(), cursorPos, anchorPos); 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: private:
QLabel *m_label; QLabel *m_label;
QLineEdit *m_edit; QLineEdit *m_edit;