Commit a636a933 authored by hluk's avatar hluk Committed by hjk
Browse files

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: default avatarhjk <hjk121@nokiamail.com>
parent 8c7a9a51
......@@ -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()
......
......@@ -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)
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment