fakevim: Fix insert modes

Change-Id: I8efb89e6931be2c37cfaf82f0aa053317c6b8d93
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Lukas Holecek
2012-10-19 19:47:18 +02:00
committed by hjk
parent ba86ddcc44
commit 5a809353d9
3 changed files with 128 additions and 46 deletions

View File

@@ -114,7 +114,9 @@ static const QString helpFormat =
} while (false) } while (false)
// Test undo, redo and repeat of last single command. This doesn't test cursor position. // Test undo, redo and repeat of last single command. This doesn't test cursor position.
#define INTEGRITY() \ // Set afterEnd to true if cursor position after undo and redo differs at the end of line
// (e.g. undoing 'A' operation moves cursor at the end of line and redo moves it one char right).
#define INTEGRITY(afterEnd) \
do { \ do { \
data.doKeys("<ESC>"); \ data.doKeys("<ESC>"); \
const int newPosition = data.position(); \ const int newPosition = data.position(); \
@@ -123,7 +125,8 @@ static const QString helpFormat =
KEYS("u", data.oldText); \ KEYS("u", data.oldText); \
const QTextCursor tc = data.cursor(); \ const QTextCursor tc = data.cursor(); \
const int pos = tc.position(); \ const int pos = tc.position(); \
const int col = tc.positionInBlock(); \ const int col = tc.positionInBlock() \
+ ((afterEnd && tc.positionInBlock() + 2 == tc.block().length()) ? 1 : 0); \
const int line = tc.block().blockNumber(); \ const int line = tc.block().blockNumber(); \
const QTextDocument *doc = data.editor()->document(); \ const QTextDocument *doc = data.editor()->document(); \
KEYS("<c-r>", textWithCursor(redo, doc->findBlockByNumber(line), col)); \ KEYS("<c-r>", textWithCursor(redo, doc->findBlockByNumber(line), col)); \
@@ -278,6 +281,62 @@ void FakeVimPlugin::test_vim_movement()
KEYS("$a", "abc def" X N "ghi"); KEYS("$a", "abc def" X N "ghi");
} }
void FakeVimPlugin::test_vim_insert()
{
TestData data;
setup(&data);
// basic insert text
data.setText("ab" X "c" N "def");
KEYS("i 123", "ab 123" X "c" N "def");
INTEGRITY(false);
data.setText("ab" X "c" N "def");
KEYS("a 123", "abc 123" X N "def");
INTEGRITY(true);
data.setText("ab" X "c" N "def");
KEYS("I 123", " 123" X "abc" N "def");
INTEGRITY(false);
data.setText("abc" N "def");
KEYS("A 123", "abc 123" X N "def");
INTEGRITY(true);
data.setText("abc" N "def");
KEYS("o 123", "abc" N " 123" X N "def");
INTEGRITY(false);
data.setText("abc" N "def");
KEYS("O 123", " 123" X N "abc" N "def");
INTEGRITY(false);
// insert text [count] times
data.setText("ab" X "c" N "def");
KEYS("3i 123<esc>", "ab 123 123 12" X "3c" N "def");
INTEGRITY(false);
data.setText("ab" X "c" N "def");
KEYS("3a 123<esc>", "abc 123 123 12" X "3" N "def");
INTEGRITY(true);
data.setText("ab" X "c" N "def");
KEYS("3I 123<esc>", " 123 123 12" X "3abc" N "def");
INTEGRITY(false);
data.setText("abc" N "def");
KEYS("3A 123<esc>", "abc 123 123 12" X "3" N "def");
INTEGRITY(true);
data.setText("abc" N "def");
KEYS("3o 123<esc>", "abc" N " 123" N " 123" N " 12" X "3" N "def");
INTEGRITY(false);
data.setText("abc" N "def");
KEYS("3O 123<esc>", " 123" N " 123" N " 12" X "3" N "abc" N "def");
INTEGRITY(false);
}
void FakeVimPlugin::test_vim_fFtT() void FakeVimPlugin::test_vim_fFtT()
{ {
TestData data; TestData data;
@@ -306,18 +365,18 @@ void FakeVimPlugin::test_vim_transform_numbers()
data.setText("8"); data.setText("8");
KEYS("<c-a>", X "9"); KEYS("<c-a>", X "9");
INTEGRITY(); INTEGRITY(false);
KEYS("<c-x>", X "8"); KEYS("<c-x>", X "8");
INTEGRITY(); INTEGRITY(false);
KEYS("<c-a>", X "9"); KEYS("<c-a>", X "9");
KEYS("<c-a>", "1" X "0"); KEYS("<c-a>", "1" X "0");
KEYS("<c-a>", "1" X "1"); KEYS("<c-a>", "1" X "1");
KEYS("5<c-a>", "1" X "6"); KEYS("5<c-a>", "1" X "6");
INTEGRITY(); INTEGRITY(false);
KEYS("10<c-a>", "2" X "6"); KEYS("10<c-a>", "2" X "6");
KEYS("h100<c-a>", "12" X "6"); KEYS("h100<c-a>", "12" X "6");
KEYS("100<c-x>", "2" X "6"); KEYS("100<c-x>", "2" X "6");
INTEGRITY(); INTEGRITY(false);
KEYS("10<c-x>", "1" X "6"); KEYS("10<c-x>", "1" X "6");
KEYS("5<c-x>", "1" X "1"); KEYS("5<c-x>", "1" X "1");
KEYS("5<c-x>", X "6"); KEYS("5<c-x>", X "6");
@@ -356,33 +415,33 @@ void FakeVimPlugin::test_vim_delete()
data.setText("123" N "456"); data.setText("123" N "456");
KEYS("x", "23" N "456"); KEYS("x", "23" N "456");
INTEGRITY(); INTEGRITY(false);
KEYS("dd", "456"); KEYS("dd", "456");
INTEGRITY(); INTEGRITY(false);
KEYS("2x", "6"); KEYS("2x", "6");
INTEGRITY(); INTEGRITY(false);
KEYS("dd", ""); KEYS("dd", "");
INTEGRITY(); INTEGRITY(false);
data.setText("void main()"); data.setText("void main()");
KEYS("dt(", "()"); KEYS("dt(", "()");
INTEGRITY(); INTEGRITY(false);
data.setText("void main()"); data.setText("void main()");
KEYS("df(", ")"); KEYS("df(", ")");
INTEGRITY(); INTEGRITY(false);
data.setText("void " X "main()"); data.setText("void " X "main()");
KEYS("D", "void "); KEYS("D", "void ");
INTEGRITY(); INTEGRITY(false);
KEYS("ggd$", ""); KEYS("ggd$", "");
data.setText("abc def ghi"); data.setText("abc def ghi");
KEYS("2dw", X "ghi"); KEYS("2dw", X "ghi");
INTEGRITY(); INTEGRITY(false);
data.setText("abc def ghi"); data.setText("abc def ghi");
KEYS("d2w", X "ghi"); KEYS("d2w", X "ghi");
INTEGRITY(); INTEGRITY(false);
data.setText("abc " N " def" N " ghi" N "jkl"); data.setText("abc " N " def" N " ghi" N "jkl");
KEYS("3dw", X "jkl"); KEYS("3dw", X "jkl");
@@ -396,7 +455,7 @@ void FakeVimPlugin::test_vim_delete()
// delete on an empty line // delete on an empty line
data.setText("a" N X "" N " b"); data.setText("a" N X "" N " b");
KEYS("d$", "a" N X "" N " b"); KEYS("d$", "a" N X "" N " b");
INTEGRITY(); INTEGRITY(false);
// delete in empty document // delete in empty document
data.setText(""); data.setText("");
@@ -413,11 +472,11 @@ void FakeVimPlugin::test_vim_delete_inner_word()
data.setText("abc def ghi jkl"); data.setText("abc def ghi jkl");
KEYS("3diw", X " ghi jkl"); KEYS("3diw", X " ghi jkl");
INTEGRITY(); INTEGRITY(false);
data.setText("abc " X " def"); data.setText("abc " X " def");
KEYS("diw", "abc" X "def"); KEYS("diw", "abc" X "def");
INTEGRITY(); INTEGRITY(false);
KEYS("diw", ""); KEYS("diw", "");
data.setText("abc " N " def"); data.setText("abc " N " def");
@@ -460,9 +519,9 @@ void FakeVimPlugin::test_vim_delete_a_word()
data.setText("abc" X " def ghi"); data.setText("abc" X " def ghi");
KEYS("daw", "abc" X " ghi"); KEYS("daw", "abc" X " ghi");
INTEGRITY(); INTEGRITY(false);
KEYS("daw", "ab" X "c"); KEYS("daw", "ab" X "c");
INTEGRITY(); INTEGRITY(false);
KEYS("daw", ""); KEYS("daw", "");
data.setText(X " ghi jkl"); data.setText(X " ghi jkl");
@@ -471,7 +530,7 @@ void FakeVimPlugin::test_vim_delete_a_word()
data.setText("abc def ghi jkl"); data.setText("abc def ghi jkl");
KEYS("3daw", X "jkl"); KEYS("3daw", X "jkl");
INTEGRITY(); INTEGRITY(false);
// remove trailing spaces // remove trailing spaces
data.setText("abc " N " def" N " ghi" N "jkl"); data.setText("abc " N " def" N " ghi" N "jkl");
@@ -500,7 +559,7 @@ void FakeVimPlugin::test_vim_change_a_word()
data.setText("abc " X "def ghi"); data.setText("abc " X "def ghi");
KEYS("caw#", "abc #" X "ghi"); KEYS("caw#", "abc #" X "ghi");
INTEGRITY(); INTEGRITY(false);
data.setText("abc d" X "ef ghi"); data.setText("abc d" X "ef ghi");
KEYS("caw#", "abc #" X "ghi"); KEYS("caw#", "abc #" X "ghi");
data.setText("abc de" X "f ghi"); data.setText("abc de" X "f ghi");
@@ -508,7 +567,7 @@ void FakeVimPlugin::test_vim_change_a_word()
data.setText("abc de" X "f ghi jkl"); data.setText("abc de" X "f ghi jkl");
KEYS("2caw#", "abc #" X "jkl"); KEYS("2caw#", "abc #" X "jkl");
INTEGRITY(); INTEGRITY(false);
data.setText("abc" X " def ghi jkl"); data.setText("abc" X " def ghi jkl");
KEYS("2caw#", "abc#" X " jkl"); KEYS("2caw#", "abc#" X " jkl");
@@ -532,12 +591,12 @@ void FakeVimPlugin::test_vim_change_replace()
// change empty line // change empty line
data.setText("a" N X "" N " b"); data.setText("a" N X "" N " b");
KEYS("ccABC", "a" N "ABC" X N " b"); KEYS("ccABC", "a" N "ABC" X N " b");
INTEGRITY(); INTEGRITY(false);
// change on empty line // change on empty line
data.setText("a" N X "" N " b"); data.setText("a" N X "" N " b");
KEYS("c$ABC<esc>", "a" N "AB" X "C" N " b"); KEYS("c$ABC<esc>", "a" N "AB" X "C" N " b");
INTEGRITY(); INTEGRITY(false);
KEYS("u", "a" N X "" N " b"); KEYS("u", "a" N X "" N " b");
KEYS("rA", "a" N X "" N " b"); KEYS("rA", "a" N X "" N " b");
@@ -566,7 +625,7 @@ void FakeVimPlugin::test_vim_change_replace()
" int i = 0;" X N " int i = 0;" X N
"}" N "}" N
""); "");
INTEGRITY(); INTEGRITY(false);
KEYS("uS" "int i = 0;" N "int j = 1;", KEYS("uS" "int i = 0;" N "int j = 1;",
"int main()" N "int main()" N
@@ -585,12 +644,12 @@ void FakeVimPlugin::test_vim_block_selection()
data.setText("int main(int /* (unused) */, char *argv[]);"); data.setText("int main(int /* (unused) */, char *argv[]);");
KEYS("f(", "int main" X "(int /* (unused) */, char *argv[]);"); KEYS("f(", "int main" X "(int /* (unused) */, char *argv[]);");
KEYS("da(", "int main" X ";"); KEYS("da(", "int main" X ";");
INTEGRITY(); INTEGRITY(false);
data.setText("int main(int /* (unused) */, char *argv[]);"); data.setText("int main(int /* (unused) */, char *argv[]);");
KEYS("f(", "int main" X "(int /* (unused) */, char *argv[]);"); KEYS("f(", "int main" X "(int /* (unused) */, char *argv[]);");
KEYS("di(", "int main(" X ");"); KEYS("di(", "int main(" X ");");
INTEGRITY(); INTEGRITY(false);
data.setText("int main(int /* (unused) */, char *argv[]);"); data.setText("int main(int /* (unused) */, char *argv[]);");
KEYS("2f)", "int main(int /* (unused) */, char *argv[]" X ");"); KEYS("2f)", "int main(int /* (unused) */, char *argv[]" X ");");
@@ -604,12 +663,12 @@ void FakeVimPlugin::test_vim_block_selection()
KEYS("2f{l", "{ { {" X " } } }"); KEYS("2f{l", "{ { {" X " } } }");
KEYS("da{", "{ { " X " } }"); KEYS("da{", "{ { " X " } }");
KEYS("da{", "{ " X " }"); KEYS("da{", "{ " X " }");
INTEGRITY(); INTEGRITY(false);
data.setText("{ { { } } }"); data.setText("{ { { } } }");
KEYS("2f{l", "{ { {" X " } } }"); KEYS("2f{l", "{ { {" X " } } }");
KEYS("2da{", "{ " X " }"); KEYS("2da{", "{ " X " }");
INTEGRITY(); INTEGRITY(false);
data.setText("{" N " { " N " } " N "}"); data.setText("{" N " { " N " } " N "}");
KEYS("di{", "{" N "}"); KEYS("di{", "{" N "}");
@@ -629,7 +688,7 @@ void FakeVimPlugin::test_vim_repeat()
data.setText("abc" N "def" N "ghi"); data.setText("abc" N "def" N "ghi");
KEYS("dd", X "def" N "ghi"); KEYS("dd", X "def" N "ghi");
KEYS(".", X "ghi"); KEYS(".", X "ghi");
INTEGRITY(); INTEGRITY(false);
// delete to next word // delete to next word
data.setText("abc def ghi jkl"); data.setText("abc def ghi jkl");
@@ -787,7 +846,7 @@ void FakeVimPlugin::test_vim_indent()
" " X "ghi" N " " X "ghi" N
" jkl" N " jkl" N
"mno"); "mno");
INTEGRITY(); INTEGRITY(false);
KEYS("k3<<", KEYS("k3<<",
"abc" N "abc" N
X "def" N X "def" N
@@ -810,7 +869,7 @@ void FakeVimPlugin::test_vim_indent()
data.setText("abc"); data.setText("abc");
KEYS(">>", " " X "abc"); KEYS(">>", " " X "abc");
INTEGRITY(); INTEGRITY(false);
data.setText("abc"); data.setText("abc");
data.doCommand("set shiftwidth=2"); data.doCommand("set shiftwidth=2");
@@ -828,7 +887,7 @@ void FakeVimPlugin::test_vim_indent()
data.doCommand("set shiftwidth=7"); data.doCommand("set shiftwidth=7");
data.setText("abc"); data.setText("abc");
KEYS(">>", "\t\t abc"); KEYS(">>", "\t\t abc");
INTEGRITY(); INTEGRITY(false);
} }
void FakeVimPlugin::test_vim_marks() void FakeVimPlugin::test_vim_marks()
@@ -869,7 +928,7 @@ void FakeVimPlugin::test_vim_copy_paste()
data.setText("123" N "456"); data.setText("123" N "456");
KEYS("yyp", "123" N X "123" N "456"); KEYS("yyp", "123" N X "123" N "456");
KEYS("2p", "123" N "123" N X "123" N "123" N "456"); KEYS("2p", "123" N "123" N X "123" N "123" N "456");
INTEGRITY(); INTEGRITY(false);
data.setText("123 456"); data.setText("123 456");
KEYS("yw2P", "123 123" X " 123 456"); KEYS("yw2P", "123 123" X " 123 456");
@@ -1022,7 +1081,7 @@ void FakeVimPlugin::test_vim_code_autoindent()
" return 0;" X N " return 0;" X N
"}" N "}" N
""); "");
INTEGRITY(); INTEGRITY(false);
KEYS("O" "int i = 0;", KEYS("O" "int i = 0;",
"int main()" N "int main()" N
"{" N "{" N
@@ -1030,7 +1089,7 @@ void FakeVimPlugin::test_vim_code_autoindent()
" return 0;" N " return 0;" N
"}" N "}" N
""); "");
INTEGRITY(); INTEGRITY(false);
KEYS("ddO" "int i = 0;" N "int j = 0;", KEYS("ddO" "int i = 0;" N "int j = 0;",
"int main()" N "int main()" N
"{" N "{" N
@@ -1068,7 +1127,18 @@ void FakeVimPlugin::test_vim_code_autoindent()
"{" N "{" N
X "}" N X "}" N
""); "");
INTEGRITY(); INTEGRITY(false);
// autoindent
data.doCommand("set nosmartindent");
data.setText("abc" N "def");
KEYS("3o 123<esc>", "abc" N " 123" N " 123" N " 12" X "3" N "def");
INTEGRITY(false);
data.setText("abc" N "def");
KEYS("3O 123<esc>", " 123" N " 123" N " 12" X "3" N "abc" N "def");
INTEGRITY(false);
data.doCommand("set smartindent");
} }
void FakeVimPlugin::test_vim_code_folding() void FakeVimPlugin::test_vim_code_folding()

View File

@@ -2954,13 +2954,13 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
finishMovement(); finishMovement();
} else if ((!isVisualMode() && input.is('a')) || (isVisualMode() && input.is('A'))) { } else if ((!isVisualMode() && input.is('a')) || (isVisualMode() && input.is('A'))) {
leaveVisualMode(); leaveVisualMode();
setUndoPosition();
breakEditBlock(); breakEditBlock();
enterInsertMode(); enterInsertMode();
setDotCommand(QString(QLatin1Char('a'))); setDotCommand("%1a", count());
m_lastInsertion.clear(); m_lastInsertion.clear();
if (!atEndOfLine()) if (!atEndOfLine())
moveRight(); moveRight();
setUndoPosition();
updateMiniBuffer(); updateMiniBuffer();
} else if (input.is('A')) { } else if (input.is('A')) {
breakEditBlock(); breakEditBlock();
@@ -2969,6 +2969,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
setAnchor(); setAnchor();
enterInsertMode(); enterInsertMode();
setDotCommand(QString(QLatin1Char('A'))); setDotCommand(QString(QLatin1Char('A')));
setDotCommand("%1A", count());
m_lastInsertion.clear(); m_lastInsertion.clear();
updateMiniBuffer(); updateMiniBuffer();
} else if (input.isControl('a')) { } else if (input.isControl('a')) {
@@ -3151,7 +3152,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
handleStartOfLine(); handleStartOfLine();
finishMovement(); finishMovement();
} else if (!isVisualMode() && (input.is('i') || input.isKey(Key_Insert))) { } else if (!isVisualMode() && (input.is('i') || input.isKey(Key_Insert))) {
setDotCommand(QString(QLatin1Char('i'))); // setDotCommand("%1i", count()); setDotCommand("%1i", count());
breakEditBlock(); breakEditBlock();
enterInsertMode(); enterInsertMode();
updateMiniBuffer(); updateMiniBuffer();
@@ -3169,7 +3170,7 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
if (input.is('I')) { if (input.is('I')) {
setUndoPosition(); setUndoPosition();
setDotCommand(QString(QLatin1Char('I'))); // setDotCommand("%1I", count()); setDotCommand("%1I", count());
if (isVisualMode()) { if (isVisualMode()) {
int beginLine = lineForPosition(anchor()); int beginLine = lineForPosition(anchor());
int endLine = lineForPosition(position()); int endLine = lineForPosition(position());
@@ -3288,6 +3289,7 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
} }
beginEditBlock(); beginEditBlock();
insertText(QString("\n")); insertText(QString("\n"));
m_lastInsertion += '\n';
if (!appendLine) if (!appendLine)
moveUp(); moveUp();
insertAutomaticIndentation(insertAfter); insertAutomaticIndentation(insertAfter);
@@ -3638,15 +3640,24 @@ EventResult FakeVimHandler::Private::handleInsertMode(const Input &input)
} else { } else {
// Normal insertion. Start with '1', as one instance was // Normal insertion. Start with '1', as one instance was
// already physically inserted while typing. // already physically inserted while typing.
QString data; const int repeat = count();
for (int i = 1; i < count(); ++i) if (repeat > 1) {
data += m_lastInsertion; const QString text = m_lastInsertion;
insertText(data); for (int i = 1; i < repeat; ++i) {
m_lastInsertion.truncate(0);
foreach (const QChar &c, text)
handleInsertMode(Input(c));
}
m_lastInsertion = text;
}
moveLeft(qMin(1, leftDist())); moveLeft(qMin(1, leftDist()));
setTargetColumn(); setTargetColumn();
leaveVisualMode(); leaveVisualMode();
breakEditBlock(); breakEditBlock();
} }
// If command is 'o' or 'O' don't include the first line feed in dot command.
if (g.dotCommand.endsWith(QChar('o'), Qt::CaseInsensitive))
m_lastInsertion.remove(0, 1);
g.dotCommand += m_lastInsertion; g.dotCommand += m_lastInsertion;
g.dotCommand += QChar(27); g.dotCommand += QChar(27);
enterCommandMode(); enterCommandMode();

View File

@@ -61,6 +61,7 @@ private:
private slots: private slots:
void cleanup(); void cleanup();
void test_vim_movement(); void test_vim_movement();
void test_vim_insert();
void test_vim_fFtT(); void test_vim_fFtT();
void test_vim_transform_numbers(); void test_vim_transform_numbers();
void test_vim_delete(); void test_vim_delete();