fakevim: Restore FakeVim state before any text processing

Restore selection and cursor position (may have been changed externally)
before any text processing.

Change-Id: I424523512f8f83c276e7d29760aad29bf7921dab
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Lukas Holecek
2012-12-07 18:46:30 +01:00
committed by hjk
parent f377264128
commit 3eedd06ce5
2 changed files with 94 additions and 46 deletions

View File

@@ -239,18 +239,34 @@ struct FakeVimPlugin::TestData
editor()->setTextCursor(tc); editor()->setTextCursor(tc);
} }
// Simulate external position change.
void jump(const char *textWithCursorPosition)
{
int pos = QString(_(textWithCursorPosition)).indexOf(_(X));
QTextCursor tc = editor()->textCursor();
tc.setPosition(pos);
editor()->setTextCursor(tc);
QCOMPARE(QByteArray(textWithCursorPosition), textWithCursor(text(), position()));
}
int lines() const int lines() const
{ {
QTextDocument *doc = editor()->document(); QTextDocument *doc = editor()->document();
Q_ASSERT(doc != 0); Q_ASSERT(doc != 0);
return doc->lineCount(); return doc->lineCount();
} }
// Enter command mode and go to start.
void reset()
{
handler->handleInput(_("<ESC><ESC>gg0"));
}
}; };
void FakeVimPlugin::setup(TestData *data) void FakeVimPlugin::setup(TestData *data)
{ {
setupTest(&data->title, &data->handler, &data->edit); setupTest(&data->title, &data->handler, &data->edit);
data->handler->handleInput(_("<ESC><ESC>gg")); data->reset();
} }
@@ -1333,6 +1349,15 @@ void FakeVimPlugin::test_vim_jumps()
KEYS("u", " aBc" N " d" X "ef" N " ghi"); KEYS("u", " aBc" N " d" X "ef" N " ghi");
KEYS("''", " aBc" N " " X "def" N " ghi"); KEYS("''", " aBc" N " " X "def" N " ghi");
KEYS("`'", " aBc" N " d" X "ef" N " ghi"); KEYS("`'", " aBc" N " d" X "ef" N " ghi");
// record external position changes
data.setText("abc" N "def" N "g" X "hi");
data.jump("abc" N "de" X "f" N "ghi");
KEYS("<C-O>", "abc" N "def" N "g" X "hi");
KEYS("<C-I>", "abc" N "de" X "f" N "ghi");
data.jump("ab" X "c" N "def" N "ghi");
KEYS("<C-O>", "abc" N "de" X "f" N "ghi");
KEYS("<C-O>", "abc" N "def" N "g" X "hi");
} }
void FakeVimPlugin::test_vim_copy_paste() void FakeVimPlugin::test_vim_copy_paste()

View File

@@ -1351,6 +1351,9 @@ public:
void init(); void init();
void focus(); void focus();
void enterFakeVim(); // Call before any FakeVim processing (import cursor position from editor)
void leaveFakeVim(); // Call after any FakeVim processing (export cursor position to editor)
EventResult handleKey(const Input &input); EventResult handleKey(const Input &input);
EventResult handleDefaultKey(const Input &input); EventResult handleDefaultKey(const Input &input);
void handleMappedKeys(); void handleMappedKeys();
@@ -1597,7 +1600,6 @@ public:
FakeVimHandler *q; FakeVimHandler *q;
Mode m_mode; Mode m_mode;
bool m_passing; // let the core see the next event bool m_passing; // let the core see the next event
bool m_firstKeyPending;
SubMode m_submode; SubMode m_submode;
SubSubMode m_subsubmode; SubSubMode m_subsubmode;
Input m_subsubdata; Input m_subsubdata;
@@ -1729,7 +1731,7 @@ public:
RangeMode registerRangeMode(int reg) const; RangeMode registerRangeMode(int reg) const;
void getRegisterType(int reg, bool *isClipboard, bool *isSelection) const; void getRegisterType(int reg, bool *isClipboard, bool *isSelection) const;
void recordJump(); void recordJump(int position = -1);
void jump(int distance); void jump(int distance);
QStack<CursorPosition> m_jumpListUndo; QStack<CursorPosition> m_jumpListUndo;
QStack<CursorPosition> m_jumpListRedo; QStack<CursorPosition> m_jumpListRedo;
@@ -1842,7 +1844,6 @@ void FakeVimHandler::Private::init()
m_submode = NoSubMode; m_submode = NoSubMode;
m_subsubmode = NoSubSubMode; m_subsubmode = NoSubSubMode;
m_passing = false; m_passing = false;
m_firstKeyPending = false;
g.findPending = false; g.findPending = false;
m_findStartPosition = -1; m_findStartPosition = -1;
m_visualBlockInsert = false; m_visualBlockInsert = false;
@@ -1885,6 +1886,51 @@ void FakeVimHandler::Private::focus()
} }
} }
void FakeVimHandler::Private::enterFakeVim()
{
importSelection();
QTextCursor tc = cursor();
// Position changed externally, e.g. by code completion.
if (tc.position() != m_oldPosition) {
// record external jump to different line
if (m_oldPosition != -1 && lineForPosition(m_oldPosition) != lineForPosition(tc.position()))
recordJump(m_oldPosition);
setTargetColumn();
if (atEndOfLine() && !isVisualMode() && m_mode != InsertMode && m_mode != ReplaceMode)
moveLeft();
}
tc.setVisualNavigation(true);
setCursor(tc);
if (m_fakeEnd)
moveRight();
}
void FakeVimHandler::Private::leaveFakeVim()
{
// The command might have destroyed the editor.
if (m_textedit || m_plaintextedit) {
// We fake vi-style end-of-line behaviour
m_fakeEnd = atEndOfLine() && m_mode == CommandMode && !isVisualBlockMode();
//QTC_ASSERT(m_mode == InsertMode || m_mode == ReplaceMode
// || !atBlockEnd() || block().length() <= 1,
// qDebug() << "Cursor at EOL after key handler");
if (m_fakeEnd)
moveLeft();
m_oldPosition = position();
if (hasConfig(ConfigShowMarks))
updateSelection();
exportSelection();
updateCursorShape();
}
}
bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev) bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev)
{ {
const int key = ev->key(); const int key = ev->key();
@@ -1967,26 +2013,6 @@ EventResult FakeVimHandler::Private::handleEvent(QKeyEvent *ev)
//if (0 && hasBlock) { //if (0 && hasBlock) {
// (pos > anc) ? --pos : --anc; // (pos > anc) ? --pos : --anc;
importSelection();
// Position changed externally, e.g. by code completion.
if (position() != m_oldPosition) {
setTargetColumn();
if (atEndOfLine() && !isVisualMode() && m_mode != InsertMode && m_mode != ReplaceMode)
moveLeft();
}
QTextCursor tc = cursor();
tc.setVisualNavigation(true);
if (m_firstKeyPending) {
m_firstKeyPending = false;
recordJump();
}
setCursor(tc);
if (m_fakeEnd)
moveRight();
//if ((mods & RealControlModifier) != 0) { //if ((mods & RealControlModifier) != 0) {
// if (key >= Key_A && key <= Key_Z) // if (key >= Key_A && key <= Key_Z)
// key = shift(key); // make it lower case // key = shift(key); // make it lower case
@@ -1999,26 +2025,9 @@ EventResult FakeVimHandler::Private::handleEvent(QKeyEvent *ev)
// || !atBlockEnd() || block().length() <= 1, // || !atBlockEnd() || block().length() <= 1,
// qDebug() << "Cursor at EOL before key handler"); // qDebug() << "Cursor at EOL before key handler");
enterFakeVim();
EventResult result = handleKey(Input(key, mods, ev->text())); EventResult result = handleKey(Input(key, mods, ev->text()));
leaveFakeVim();
// The command might have destroyed the editor.
if (m_textedit || m_plaintextedit) {
// We fake vi-style end-of-line behaviour
m_fakeEnd = atEndOfLine() && m_mode == CommandMode && !isVisualBlockMode();
//QTC_ASSERT(m_mode == InsertMode || m_mode == ReplaceMode
// || !atBlockEnd() || block().length() <= 1,
// qDebug() << "Cursor at EOL after key handler");
if (m_fakeEnd)
moveLeft();
m_oldPosition = position();
if (hasConfig(ConfigShowMarks))
updateSelection();
exportSelection();
updateCursorShape();
}
return result; return result;
} }
@@ -2039,12 +2048,16 @@ void FakeVimHandler::Private::setupWidget()
m_plaintextedit->setLineWrapMode(QPlainTextEdit::NoWrap); m_plaintextedit->setLineWrapMode(QPlainTextEdit::NoWrap);
} }
m_wasReadOnly = EDITOR(isReadOnly()); m_wasReadOnly = EDITOR(isReadOnly());
m_firstKeyPending = true;
updateEditor(); updateEditor();
importSelection(); importSelection();
updateMiniBuffer(); updateMiniBuffer();
updateCursorShape(); updateCursorShape();
recordJump();
setTargetColumn();
if (atEndOfLine() && !isVisualMode() && m_mode != InsertMode && m_mode != ReplaceMode)
moveLeft();
} }
void FakeVimHandler::Private::exportSelection() void FakeVimHandler::Private::exportSelection()
@@ -2357,7 +2370,10 @@ void FakeVimHandler::Private::timerEvent(QTimerEvent *ev)
if (ev->timerId() == g.inputTimer) { if (ev->timerId() == g.inputTimer) {
if (g.currentMap.isComplete()) if (g.currentMap.isComplete())
handleMappedKeys(); handleMappedKeys();
enterFakeVim();
handleKey(Input()); handleKey(Input());
leaveFakeVim();
} }
} }
@@ -6675,9 +6691,10 @@ void FakeVimHandler::Private::enterExMode(const QString &contents)
m_subsubmode = NoSubSubMode; m_subsubmode = NoSubSubMode;
} }
void FakeVimHandler::Private::recordJump() void FakeVimHandler::Private::recordJump(int position)
{ {
CursorPosition pos(cursor()); CursorPosition pos = position >= 0 ? CursorPosition(document(), position)
: CursorPosition(cursor());
setMark(QLatin1Char('\''), pos); setMark(QLatin1Char('\''), pos);
if (m_jumpListUndo.isEmpty() || m_jumpListUndo.top() != pos) if (m_jumpListUndo.isEmpty() || m_jumpListUndo.top() != pos)
m_jumpListUndo.push(pos); m_jumpListUndo.push(pos);
@@ -7327,19 +7344,25 @@ void FakeVimHandler::restoreWidget(int tabSize)
void FakeVimHandler::handleCommand(const QString &cmd) void FakeVimHandler::handleCommand(const QString &cmd)
{ {
d->enterFakeVim();
d->handleCommand(cmd); d->handleCommand(cmd);
d->leaveFakeVim();
} }
void FakeVimHandler::handleReplay(const QString &keys) void FakeVimHandler::handleReplay(const QString &keys)
{ {
d->enterFakeVim();
d->replay(keys); d->replay(keys);
d->leaveFakeVim();
} }
void FakeVimHandler::handleInput(const QString &keys) void FakeVimHandler::handleInput(const QString &keys)
{ {
Inputs inputs(keys); Inputs inputs(keys);
d->enterFakeVim();
foreach (const Input &input, inputs) foreach (const Input &input, inputs)
d->handleKey(input); d->handleKey(input);
d->leaveFakeVim();
} }
void FakeVimHandler::setCurrentFileName(const QString &fileName) void FakeVimHandler::setCurrentFileName(const QString &fileName)