forked from qt-creator/qt-creator
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:
@@ -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()
|
||||||
|
|||||||
@@ -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()) {
|
||||||
leaveVisualMode();
|
if (g.subsubmode == SearchSubSubMode) {
|
||||||
|
setPosition(m_searchStartPosition);
|
||||||
|
scrollToLine(m_searchFromScreenLine);
|
||||||
|
setTargetColumn();
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
finishMovement(g.searchBuffer.prompt() + g.lastSearch + QLatin1Char('\n'));
|
|
||||||
|
if (finishSearch()) {
|
||||||
|
if (g.submode != NoSubMode)
|
||||||
|
finishMovement(g.searchBuffer.prompt() + g.lastSearch + QLatin1Char('\n'));
|
||||||
|
if (g.currentMessage.isEmpty())
|
||||||
|
showMessage(MessageCommand, g.searchBuffer.display());
|
||||||
} else {
|
} 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.
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMiniBuffer();
|
if (input.isReturn() || input.isEscape()) {
|
||||||
|
g.searchBuffer.clear();
|
||||||
if (!input.isReturn() && !input.isEscape())
|
resetCommandMode();
|
||||||
|
updateMiniBuffer();
|
||||||
|
} else {
|
||||||
|
updateMiniBuffer();
|
||||||
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)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user