diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index b6df6ec7e48eba22746ec66478a4ad0c2b53fe68..d51904a625ea98f52c01f9802b8e3689a2314473 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -135,8 +135,6 @@ enum Mode InsertMode, CommandMode, ExMode, - SearchForwardMode, - SearchBackwardMode, }; enum SubMode @@ -171,6 +169,8 @@ enum SubSubMode UpCaseSubSubMode, // used for gU ReplaceSubSubMode, // used for r after visual mode TextObjectSubSubMode, // used for thing like iw, aW, as etc. + SearchForwardSubSubMode, + SearchBackwardSubSubMode, }; enum VisualMode @@ -260,11 +260,14 @@ QString quoteUnprintable(const QString &ba) { QString res; for (int i = 0, n = ba.size(); i != n; ++i) { - QChar c = ba.at(i); + const QChar c = ba.at(i); + const int cc = c.unicode(); if (c.isPrint()) res += c; + else if (cc == '\n') + res += QLatin1String("<CR>"); else - res += QString("\\x%1").arg(c.unicode(), 2, 16); + res += QString("\\x%1").arg(c.unicode(), 2, 16, QLatin1Char('0')); } return res; } @@ -589,7 +592,10 @@ public: bool m_positionPastEnd; // '$' & 'l' in visual mode can move past eol bool isSearchMode() const - { return m_mode == SearchForwardMode || m_mode == SearchBackwardMode; } + { + return m_subsubmode == SearchForwardSubSubMode + || m_subsubmode == SearchBackwardSubSubMode; + } int m_gflag; // whether current command started with 'g' QString m_commandBuffer; @@ -774,6 +780,8 @@ bool FakeVimHandler::Private::wantsOverride(QKeyEvent *ev) KEY_DEBUG("SHORTCUT OVERRIDE" << key << " PASSING: " << m_passing); if (key == Key_Escape) { + if (isSearchMode()) + return true; // Not sure this feels good. People often hit Esc several times if (isNoVisualMode() && m_mode == CommandMode) return false; @@ -958,6 +966,8 @@ void FakeVimHandler::Private::restoreWidget(int tabSize) EventResult FakeVimHandler::Private::handleKey(const Input &input) { + if (m_mode == ExMode || isSearchMode()) + return handleMiniBufferModes(input); if (m_mode == InsertMode || m_mode == CommandMode) { m_pendingInput.append(input); const char code = m_mode == InsertMode ? 'i' : 'n'; @@ -968,9 +978,6 @@ EventResult FakeVimHandler::Private::handleKey(const Input &input) m_inputTimer = startTimer(1000); return EventHandled; } - if (m_mode == ExMode || m_mode == SearchForwardMode - || m_mode == SearchBackwardMode) - return handleMiniBufferModes(input); return EventUnhandled; } @@ -1210,20 +1217,19 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand) indentSelectedText(); endEditBlock(); m_submode = NoSubMode; - updateMiniBuffer(); } else if (m_submode == ShiftRightSubMode) { recordJump(); shiftRegionRight(1); m_submode = NoSubMode; - updateMiniBuffer(); } else if (m_submode == ShiftLeftSubMode) { recordJump(); shiftRegionLeft(1); m_submode = NoSubMode; - updateMiniBuffer(); } resetCommandMode(); + updateSelection(); + updateMiniBuffer(); updateCursor(); } @@ -1236,9 +1242,6 @@ void FakeVimHandler::Private::resetCommandMode() m_register = '"'; m_tc.clearSelection(); m_rangemode = RangeCharMode; - - updateSelection(); - updateMiniBuffer(); } void FakeVimHandler::Private::updateSelection() @@ -1324,9 +1327,9 @@ void FakeVimHandler::Private::updateMiniBuffer() else msg = "-- INSERT --"; } else { - if (m_mode == SearchForwardMode) + if (m_subsubmode == SearchForwardSubSubMode) msg += '/'; - else if (m_mode == SearchBackwardMode) + else if (m_subsubmode == SearchBackwardSubSubMode) msg += '?'; else if (m_mode == ExMode) msg += ':'; @@ -1475,6 +1478,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input) finishMovement(); } else { resetCommandMode(); + updateSelection(); + updateMiniBuffer(); } } else if (m_subsubmode != NoSubSubMode) { handleCommandSubSubMode(input); @@ -1630,12 +1635,13 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input) } else { // FIXME: make core find dialog sufficiently flexible to // produce the "default vi" behaviour too. For now, roll our own. - enterExMode(); // to get the cursor disabled m_currentMessage.clear(); - m_mode = (input.is('/')) ? SearchForwardMode : SearchBackwardMode; + m_subsubmode = (input.is('/')) + ? SearchForwardSubSubMode : SearchBackwardSubSubMode; m_commandBuffer.clear(); m_searchHistory.append(QString()); m_searchHistoryIndex = m_searchHistory.size() - 1; + updateCursor(); updateMiniBuffer(); } } else if (input.is('`')) { @@ -1703,7 +1709,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(const Input &input) } else if (input.is(',')) { passShortcuts(true); } else if (input.is('.')) { - //qDebug() << "REPEATING" << quoteUnprintable(m_dotCommand) << count(); + //qDebug() << "REPEATING" << quoteUnprintable(m_dotCommand) << count() + // << input; QString savedCommand = m_dotCommand; m_dotCommand.clear(); replay(savedCommand, count()); @@ -2452,26 +2459,29 @@ EventResult FakeVimHandler::Private::handleMiniBufferModes(const Input &input) if (!m_commandBuffer.isEmpty()) m_commandBuffer.chop(1); updateMiniBuffer(); - } else if (input.isKey(Key_Return) && m_mode == ExMode) { - if (!m_commandBuffer.isEmpty()) { - m_commandHistory.takeLast(); - m_commandHistory.append(m_commandBuffer); - handleExCommand(m_commandBuffer); - if (m_textedit || m_plaintextedit) { - leaveVisualMode(); - } - } } else if (input.isKey(Key_Return) && isSearchMode() && !hasConfig(ConfigIncSearch)) { if (!m_commandBuffer.isEmpty()) { m_searchHistory.takeLast(); m_searchHistory.append(m_commandBuffer); - m_lastSearchForward = (m_mode == SearchForwardMode); + m_lastSearchForward = (m_subsubmode == SearchForwardSubSubMode); search(lastSearchString(), m_lastSearchForward); recordJump(); } + QString needle = m_commandBuffer.mid(1); // FIXME: why + finishMovement("/" + needle + "\n"); enterCommandMode(); + highlightMatches(needle); updateMiniBuffer(); + } else if (input.isKey(Key_Return) && m_mode == ExMode) { + if (!m_commandBuffer.isEmpty()) { + m_commandHistory.takeLast(); + m_commandHistory.append(m_commandBuffer); + handleExCommand(m_commandBuffer); + if (m_textedit || m_plaintextedit) { + leaveVisualMode(); + } + } } else if ((input.isKey(Key_Up) || input.isKey(Key_PageUp)) && isSearchMode()) { // FIXME: This and the three cases below are wrong as vim // takes only matching entries in the history into account. @@ -2854,7 +2864,7 @@ bool FakeVimHandler::Private::handleExNormalCommand(const QString &cmd) // :norm static QRegExp reNormal("^norm(al)?( (.*))?$"); if (reNormal.indexIn(cmd) == -1) return false; - //qDebug() << "REPLAY: " << reNormal.cap(3); + //qDebug() << "REPLAY NORMAL: " << quoteUnprintable(reNormal.cap(3)); replay(reNormal.cap(3), 1); return true; } @@ -3319,7 +3329,7 @@ void FakeVimHandler::Private::shiftRegionLeft(int repeat) int targetPos = anchor(); if (beginLine > endLine) { qSwap(beginLine, endLine); - targetPos = position(); + targetPos = position(); } const int shift = config(ConfigShiftWidth).toInt() * repeat; const int tab = config(ConfigTabStop).toInt(); @@ -4068,6 +4078,8 @@ void FakeVimHandler::Private::enterInsertMode() { //leaveVisualMode(); m_mode = InsertMode; + m_submode = NoSubMode; + m_subsubmode = NoSubSubMode; m_lastInsertion.clear(); m_beginEditBlock = true; updateCursor(); @@ -4078,12 +4090,16 @@ void FakeVimHandler::Private::enterCommandMode() if (atEndOfLine()) moveLeft(); m_mode = CommandMode; + m_submode = NoSubMode; + m_subsubmode = NoSubSubMode; updateCursor(); } void FakeVimHandler::Private::enterExMode() { m_mode = ExMode; + m_submode = NoSubMode; + m_subsubmode = NoSubSubMode; updateCursor(); } @@ -4170,7 +4186,7 @@ void FakeVimHandler::Private::handleStartOfLine() void FakeVimHandler::Private::replay(const QString &command, int n) { - //qDebug() << "REPLAY: " << command; + //qDebug() << "REPLAY: " << quoteUnprintable(command); m_inReplay = true; for (int i = n; --i >= 0; ) { foreach (QChar c, command) {