From 76d4084234b29df9708a5049a1c5f8e7a96755a2 Mon Sep 17 00:00:00 2001 From: hluk Date: Mon, 5 Aug 2013 19:14:18 +0200 Subject: [PATCH] FakeVim: Bracket movement commands Added commands ]], [[, [], ][ for movement. Task-number: QTCREATORBUG-9527 Change-Id: I0c363427505c9ef6274ed1cf735c9fbc43cb4bd9 Reviewed-by: hjk --- src/plugins/fakevim/fakevim_test.cpp | 128 +++++++++++++++++++++++++ src/plugins/fakevim/fakevimhandler.cpp | 54 +++++++++-- 2 files changed, 175 insertions(+), 7 deletions(-) diff --git a/src/plugins/fakevim/fakevim_test.cpp b/src/plugins/fakevim/fakevim_test.cpp index 2df0cb19903..3f5ec899ee6 100644 --- a/src/plugins/fakevim/fakevim_test.cpp +++ b/src/plugins/fakevim/fakevim_test.cpp @@ -454,6 +454,79 @@ void FakeVimPlugin::test_vim_movement() data.setText("abc def"); KEYS("}", "abc de" X "f"); KEYS("{", X "abc def"); + + // bracket movement commands + data.setText( + "void a()" N + "{" N + "}" N "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + ""); + + KEYS("]]", + "void a()" N + X "{" N + "}" N "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + ""); + + KEYS("]]", + "void a()" N + "{" N + "}" N "" N "int b()" N + X "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + ""); + + KEYS("2[[", + X "void a()" N + "{" N + "}" N "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + ""); + + KEYS("4]]", + "void a()" N + "{" N + "}" N "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + X ""); + + KEYS("2[]", + "void a()" N + "{" N + X "}" N "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + ""); + + KEYS("][", + "void a()" N + "{" N + "}" N "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + X "}" N + ""); + + KEYS("][", + "void a()" N + "{" N + "}" N "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + X ""); } void FakeVimPlugin::test_vim_insert() @@ -809,6 +882,61 @@ void FakeVimPlugin::test_vim_delete() data.setText("abc" N "def"); KEYS("2lvox", "a" X "b" N "def"); KEYS("vlox", "a" X "def"); + + // bracket movement command + data.setText( + "void a()" N + "{" N + "}" N "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + ""); + + KEYS("d]]", + X "{" N + "}" N "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + ""); + + KEYS("u", + X "void a()" N + "{" N + "}" N "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + ""); + + // When ]] is used after an operator, then also stops below a '}' in the first column. + KEYS("jd]]", + "void a()" N + X "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + ""); + + KEYS("u", + "void a()" N + X "{" N + "}" N "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + ""); + + // do nothing on failed movement + KEYS("Gd5[[", + "void a()" N + "{" N + "}" N "" N "int b()" N + "{ return 0; }" N "" N "int c()" N + "{ return 0;" N + "}" N + X ""); } void FakeVimPlugin::test_vim_delete_inner_word() diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 3b6936d091e..394974b74a5 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -584,6 +584,40 @@ static void searchBackward(QTextCursor *tc, QRegExp &needleExp, int *repeat) tc->setPosition(block.position() + i); } +// Commands [[, [] +static void bracketSearchBackward(QTextCursor *tc, const QString &needleExp, int repeat) +{ + QRegExp re(needleExp); + QTextCursor tc2 = *tc; + tc2.setPosition(tc2.position() - 1); + searchBackward(&tc2, re, &repeat); + if (repeat <= 1) + tc->setPosition(tc2.isNull() ? 0 : tc2.position(), KeepAnchor); +} + +// Commands ][, ]] +// When ]] is used after an operator, then also stops below a '}' in the first column. +static void bracketSearchForward(QTextCursor *tc, const QString &needleExp, int repeat, + bool searchWithCommand) +{ + QRegExp re(searchWithCommand ? QString(_("^\\}|^\\{")) : needleExp); + QTextCursor tc2 = *tc; + tc2.setPosition(tc2.position() + 1); + searchForward(&tc2, re, &repeat); + if (repeat <= 1) { + if (tc2.isNull()) { + tc->setPosition(tc->document()->characterCount() - 1, KeepAnchor); + } else { + tc->setPosition(tc2.position() - 1, KeepAnchor); + if (searchWithCommand && tc->document()->characterAt(tc->position()).unicode() == '}') { + QTextBlock block = tc->block().next(); + if (block.isValid()) + tc->setPosition(block.position(), KeepAnchor); + } + } + } +} + static bool substituteText(QString *text, QRegExp &pattern, const QString &replacement, bool global) { @@ -2897,7 +2931,7 @@ void FakeVimHandler::Private::fixSelection() } } - if (g.movetype == MoveExclusive) { + if (g.movetype == MoveExclusive && g.subsubmode == NoSubSubMode) { if (anchor() < position() && atBlockStart()) { // Exlusive motion ending at the beginning of line // becomes inclusive and end is moved to end of previous line. @@ -3321,14 +3355,22 @@ bool FakeVimHandler::Private::handleCommandSubSubMode(const Input &input) } } else if (g.subsubmode == OpenSquareSubSubMode || CloseSquareSubSubMode) { int pos = position(); - if ((input.is('{') && g.subsubmode == OpenSquareSubSubMode)) + if (input.is('{') && g.subsubmode == OpenSquareSubSubMode) searchBalanced(false, QLatin1Char('{'), QLatin1Char('}')); - else if ((input.is('}') && g.subsubmode == CloseSquareSubSubMode)) + else if (input.is('}') && g.subsubmode == CloseSquareSubSubMode) searchBalanced(true, QLatin1Char('}'), QLatin1Char('{')); - else if ((input.is('(') && g.subsubmode == OpenSquareSubSubMode)) + else if (input.is('(') && g.subsubmode == OpenSquareSubSubMode) searchBalanced(false, QLatin1Char('('), QLatin1Char(')')); - else if ((input.is(')') && g.subsubmode == CloseSquareSubSubMode)) + else if (input.is(')') && g.subsubmode == CloseSquareSubSubMode) searchBalanced(true, QLatin1Char(')'), QLatin1Char('(')); + else if (input.is('[') && g.subsubmode == OpenSquareSubSubMode) + bracketSearchBackward(&m_cursor, _("^\\{"), count()); + else if (input.is('[') && g.subsubmode == CloseSquareSubSubMode) + bracketSearchForward(&m_cursor, _("^\\}"), count(), false); + else if (input.is(']') && g.subsubmode == OpenSquareSubSubMode) + bracketSearchBackward(&m_cursor, _("^\\}"), count()); + else if (input.is(']') && g.subsubmode == CloseSquareSubSubMode) + bracketSearchForward(&m_cursor, _("^\\{"), count(), g.submode != NoSubMode); else if (input.is('z')) emit q->foldGoTo(g.subsubmode == OpenSquareSubSubMode ? -count() : count(), true); handled = pos != position(); @@ -3629,8 +3671,6 @@ bool FakeVimHandler::Private::handleMovement(const Input &input) movePageUp(count); handleStartOfLine(); movement = _("b"); - } else if (input.isKey(Key_BracketLeft) || input.isKey(Key_BracketRight)) { - } else { handled = false; }