summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/fakevim/fakevim_test.cpp47
-rw-r--r--src/plugins/fakevim/fakevimhandler.cpp98
-rw-r--r--src/plugins/fakevim/fakevimhandler.h3
3 files changed, 110 insertions, 38 deletions
diff --git a/src/plugins/fakevim/fakevim_test.cpp b/src/plugins/fakevim/fakevim_test.cpp
index 92c3fe8098..1bb564abe4 100644
--- a/src/plugins/fakevim/fakevim_test.cpp
+++ b/src/plugins/fakevim/fakevim_test.cpp
@@ -122,14 +122,12 @@ struct TestData
void setText(const QString &text)
{
- QTextCursor tc = cursor();
QString str = text;
int i = str.indexOf(cursorString);
if (!cursorString.isEmpty() && i != -1)
str.remove(i, 1);
edit->document()->setPlainText(str);
- tc.setPosition(qMax(0, i));
- edit->setTextCursor(tc);
+ handler->setTextCursorPosition(i);
}
void doCommand(const QString &cmd) { handler->handleCommand(cmd); }
@@ -404,19 +402,50 @@ void FakeVimPlugin::test_vim_block_selection()
void FakeVimPlugin::test_vim_repeat()
{
- NOT_IMPLEMENTED
-
TestData data;
setup(&data);
- data.setText("test text");
- KEYS("ciwWORD", "WOR" X "D text");
+ // delete line
+ data.setText("abc" N "def" N "ghi");
+ KEYS("dd", X "def" N "ghi");
+ KEYS(".", X "ghi");
+
+ // delete to next word
+ data.setText("abc def ghi jkl");
+ KEYS("dw", X "def ghi jkl");
+ KEYS("w.", "def " X "jkl");
+ KEYS("gg.", X "jkl");
+
+ // change in word
+ data.setText("WORD text");
+ KEYS("ciwWORD<esc>", "WOR" X "D text");
KEYS("w.", "WORD WOR" X "D");
/* QTCREATORBUG-7248 */
data.setText("test tex" X "t");
- KEYS("vbcWORD", "test " "WOR" X "D");
- KEYS("bb.", X "WORD WORD");
+ KEYS("vbcWORD<esc>", "test " "WOR" X "D");
+ KEYS("bb.", "WOR" X "D WORD");
+
+ // delete selected range
+ data.setText("abc def ghi jkl");
+ KEYS("viwd", X " def ghi jkl");
+ KEYS(".", X "f ghi jkl");
+ KEYS(".", X "hi jkl");
+
+ // delete two lines
+ data.setText("abc" N "def" N "ghi" N "jkl" N "mno");
+ KEYS("Vjx", X "ghi" N "jkl" N "mno");
+ KEYS(".", X "mno");
+
+ // delete three lines
+ data.setText("abc" N "def" N "ghi" N "jkl" N "mno" N "pqr" N "stu");
+ KEYS("d2j", X "jkl" N "mno" N "pqr" N "stu");
+ KEYS(".", X "stu");
+
+ // replace block selection
+ data.setText("abcd" N "d" X "efg" N "ghij" N "jklm");
+ KEYS("<c-v>jlrX", "abcd" N "d" X "XXg" N "gXXj" N "jklm");
+ KEYS("gg.", "XXcd" N "XXXg" N "gXXj" N "jklm");
}
void FakeVimPlugin::test_vim_search()
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index f3b0b3cc69..852a07e7e4 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -1157,8 +1157,8 @@ public:
EventResult handleCloseSquareSubMode(const Input &);
EventResult handleSearchSubSubMode(const Input &);
EventResult handleCommandSubSubMode(const Input &);
- void finishMovement(const QString &dotCommand = QString());
- void finishMovement(const QString &dotCommand, int count);
+ void finishMovement(const QString &dotCommandMovement = QString());
+ void finishMovement(const QString &dotCommandMovement, int count);
void resetCommandMode();
void search(const SearchData &sd, bool showMessages = true);
void searchNext(bool forward = true);
@@ -1438,6 +1438,7 @@ public:
void replay(const QString &text, int count);
void setDotCommand(const QString &cmd) { g.dotCommand = cmd; }
void setDotCommand(const QString &cmd, int n) { g.dotCommand = cmd.arg(n); }
+ QString visualDotCommand() const;
// extra data for ';'
QString m_semicolonCount;
@@ -2156,12 +2157,12 @@ void FakeVimHandler::Private::moveToStartOfLine()
#endif
}
-void FakeVimHandler::Private::finishMovement(const QString &dotCommand, int count)
+void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement, int count)
{
- finishMovement(dotCommand.arg(count));
+ finishMovement(dotCommandMovement.arg(count));
}
-void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
+void FakeVimHandler::Private::finishMovement(const QString &dotCommandMovement)
{
//dump("FINISH MOVEMENT");
if (m_submode == FilterSubMode) {
@@ -2250,8 +2251,8 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
if (m_rangemode == RangeLineMode)
m_rangemode = RangeLineModeExclusive;
removeText(currentRange());
- if (!dotCommand.isEmpty())
- setDotCommand(QLatin1Char('c') + dotCommand);
+ if (!dotCommandMovement.isEmpty())
+ setDotCommand(QLatin1Char('c') + dotCommandMovement);
if (m_movetype == MoveLineWise)
insertAutomaticIndentation(true);
endEditBlock();
@@ -2261,8 +2262,8 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
setUndoPosition();
Range range = currentRange();
removeText(range);
- if (!dotCommand.isEmpty())
- setDotCommand(QLatin1Char('d') + dotCommand);
+ if (!dotCommandMovement.isEmpty())
+ setDotCommand(QLatin1Char('d') + dotCommandMovement);
if (m_movetype == MoveLineWise)
handleStartOfLine();
m_submode = NoSubMode;
@@ -2287,16 +2288,16 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
} else if (m_submode == TransformSubMode) {
if (m_subsubmode == InvertCaseSubSubMode) {
invertCase(currentRange());
- if (!dotCommand.isEmpty())
- setDotCommand(QLatin1Char('~') + dotCommand);
+ if (!dotCommandMovement.isEmpty())
+ setDotCommand(QLatin1Char('~') + dotCommandMovement);
} else if (m_subsubmode == UpCaseSubSubMode) {
upCase(currentRange());
- if (!dotCommand.isEmpty())
- setDotCommand("gU" + dotCommand);
+ if (!dotCommandMovement.isEmpty())
+ setDotCommand("gU" + dotCommandMovement);
} else if (m_subsubmode == DownCaseSubSubMode) {
downCase(currentRange());
- if (!dotCommand.isEmpty())
- setDotCommand("gu" + dotCommand);
+ if (!dotCommandMovement.isEmpty())
+ setDotCommand("gu" + dotCommandMovement);
}
m_submode = NoSubMode;
m_subsubmode = NoSubSubMode;
@@ -2309,22 +2310,22 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
setUndoPosition();
indentSelectedText();
m_submode = NoSubMode;
- if (!dotCommand.isEmpty())
- setDotCommand('=' + dotCommand);
+ if (!dotCommandMovement.isEmpty())
+ setDotCommand('=' + dotCommandMovement);
} else if (m_submode == ShiftRightSubMode) {
recordJump();
setUndoPosition();
shiftRegionRight(1);
m_submode = NoSubMode;
- if (!dotCommand.isEmpty())
- setDotCommand('>' + dotCommand);
+ if (!dotCommandMovement.isEmpty())
+ setDotCommand('>' + dotCommandMovement);
} else if (m_submode == ShiftLeftSubMode) {
recordJump();
setUndoPosition();
shiftRegionLeft(1);
m_submode = NoSubMode;
- if (!dotCommand.isEmpty())
- setDotCommand('<' + dotCommand);
+ if (!dotCommandMovement.isEmpty())
+ setDotCommand('<' + dotCommandMovement);
}
resetCommandMode();
@@ -2589,6 +2590,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input)
m_submode = NoSubMode;
m_rangemode = RangeLineMode;
} else if (m_submode == ReplaceSubMode) {
+ setDotCommand(visualDotCommand() + 'r' + input.asChar());
if (isVisualMode()) {
setUndoPosition();
if (isVisualLineMode())
@@ -2837,7 +2839,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
// << input;
QString savedCommand = g.dotCommand;
g.dotCommand.clear();
- replay(savedCommand, count());
+ replay(savedCommand, 1);
enterCommandMode();
g.dotCommand = savedCommand;
} else if (input.is('<')) {
@@ -2872,6 +2874,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
setUndoPosition();
breakEditBlock();
enterInsertMode();
+ setDotCommand(QString(QLatin1Char('a')));
m_lastInsertion.clear();
if (!atEndOfLine())
moveRight();
@@ -2887,6 +2890,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
updateMiniBuffer();
} else if (input.isControl('a')) {
changeNumberTextObject(true);
+ setDotCommand("%1<c-a>", count());
} else if (input.is('b') || input.isShift(Key_Left)) {
m_movetype = MoveExclusive;
moveToNextWordStart(count(), false, false);
@@ -2905,6 +2909,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
m_submode = ChangeSubMode;
} else if ((input.is('c') || input.is('C') || input.is('s') || input.is('R'))
&& (isVisualCharMode() || isVisualLineMode())) {
+ setDotCommand(visualDotCommand() + input.asChar());
if ((input.is('c')|| input.is('s')) && isVisualCharMode()) {
leaveVisualMode();
m_rangemode = RangeCharMode;
@@ -2942,6 +2947,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
} else if ((input.is('d') || input.is('x') || input.isKey(Key_Delete))
&& isVisualMode()) {
setUndoPosition();
+ setDotCommand(visualDotCommand() + 'x');
if (isVisualCharMode()) {
leaveVisualMode();
m_submode = DeleteSubMode;
@@ -2972,6 +2978,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
finishMovement();
} else if ((input.is('D') || input.is('X')) &&
(isVisualCharMode() || isVisualLineMode())) {
+ setDotCommand(visualDotCommand() + 'X');
leaveVisualMode();
m_rangemode = RangeLineMode;
m_submode = NoSubMode;
@@ -2979,6 +2986,7 @@ EventResult FakeVimHandler::Private::handleCommandMode1(const Input &input)
removeText(currentRange());
moveToFirstNonBlankOnLine();
} else if ((input.is('D') || input.is('X')) && isVisualBlockMode()) {
+ setDotCommand(visualDotCommand() + 'X');
leaveVisualMode();
m_rangemode = RangeBlockAndTailMode;
yankText(currentRange(), m_register);
@@ -3102,7 +3110,6 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
moveDown(count());
finishMovement("%1j", count());
} else if (input.is('J')) {
- setDotCommand("%1J", count());
beginEditBlock();
if (m_submode == NoSubMode) {
for (int i = qMax(count(), 2) - 1; --i >= 0; ) {
@@ -3123,7 +3130,7 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
moveLeft();
}
endEditBlock();
- finishMovement();
+ finishMovement("%1J");
} else if (input.is('k') || input.isKey(Key_Up) || input.isControl('p')) {
m_movetype = MoveLineWise;
moveUp(count());
@@ -3142,6 +3149,7 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
moveUp(qMax(count(), 1));
handleStartOfLine();
finishMovement();
+ finishMovement("%1L");
} else if (input.isControl('l')) {
// screen redraw. should not be needed
} else if (input.is('m')) {
@@ -3335,6 +3343,7 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
finishMovement();
} else if (input.isControl('x')) {
changeNumberTextObject(false);
+ setDotCommand("%1<c-a>", count());
} else if (input.is('X')) {
if (leftDist() > 0) {
setAnchor();
@@ -3447,12 +3456,12 @@ EventResult FakeVimHandler::Private::handleCommandMode2(const Input &input)
moveDown(count() * (linesOnScreen() - 2) - cursorLineOnScreen());
scrollToLine(cursorLine());
handleStartOfLine();
- finishMovement();
+ finishMovement("%1f", count());
} else if (input.isKey(Key_PageUp) || input.isControl('b')) {
moveUp(count() * (linesOnScreen() - 2) + cursorLineOnScreen());
scrollToLine(cursorLine() + linesOnScreen() - 2);
handleStartOfLine();
- finishMovement();
+ finishMovement("%1b", count());
} else if (input.isKey(Key_Delete)) {
setAnchor();
moveRight(qMin(1, rightDist()));
@@ -5923,14 +5932,35 @@ void FakeVimHandler::Private::handleStartOfLine()
void FakeVimHandler::Private::replay(const QString &command, int n)
{
//qDebug() << "REPLAY: " << quoteUnprintable(command);
+ Inputs inputs(command);
for (int i = n; --i >= 0; ) {
- foreach (QChar c, command) {
- //qDebug() << " REPLAY: " << c.unicode();
- handleDefaultKey(Input(c));
+ foreach (Input in, inputs) {
+ handleDefaultKey(in);
}
}
}
+QString FakeVimHandler::Private::visualDotCommand() const
+{
+ QTextCursor start(cursor());
+ QTextCursor end(start);
+ end.setPosition(end.anchor());
+
+ if (isVisualCharMode())
+ return QString("v%1l").arg(qAbs(start.position() - end.position()));
+
+ if (isVisualLineMode())
+ return QString("V%1j").arg(qAbs(start.blockNumber() - end.blockNumber()));
+
+ if (isVisualBlockMode()) {
+ return QString("<c-v>%1l%2j")
+ .arg(qAbs(start.positionInBlock() - end.positionInBlock()))
+ .arg(qAbs(start.blockNumber() - end.blockNumber()));
+ }
+
+ return QString();
+}
+
void FakeVimHandler::Private::selectTextObject(bool simple, bool inner)
{
bool setupAnchor = (position() == anchor());
@@ -6401,6 +6431,16 @@ void FakeVimHandler::miniBufferTextEdited(const QString &text, int cursorPos)
d->miniBufferTextEdited(text, cursorPos);
}
+void FakeVimHandler::setTextCursorPosition(int position)
+{
+ int pos = qMax(0, qMin(position, d->lastPositionInDocument()));
+ if (d->isVisualMode())
+ d->setPosition(pos);
+ else
+ d->setAnchorAndPosition(pos, pos);
+ d->setTargetColumn();
+}
+
} // namespace Internal
} // namespace FakeVim
diff --git a/src/plugins/fakevim/fakevimhandler.h b/src/plugins/fakevim/fakevimhandler.h
index 7c72e755b9..940e6acd17 100644
--- a/src/plugins/fakevim/fakevimhandler.h
+++ b/src/plugins/fakevim/fakevimhandler.h
@@ -131,6 +131,9 @@ public slots:
void miniBufferTextEdited(const QString &text, int cursorPos);
+ // Set text cursor position. Keeps anchor if in visual mode.
+ void setTextCursorPosition(int position);
+
signals:
void commandBufferChanged(const QString &msg, int pos, int messageLevel, QObject *eventFilter);
void statusDataChanged(const QString &msg);