diff --git a/src/plugins/fakevim/fakevim_test.cpp b/src/plugins/fakevim/fakevim_test.cpp index 66677ad219e..6a5298ee1f2 100644 --- a/src/plugins/fakevim/fakevim_test.cpp +++ b/src/plugins/fakevim/fakevim_test.cpp @@ -1646,6 +1646,7 @@ void FakeVimPlugin::test_vim_code_autoindent() TestData data; setup(&data); + data.doCommand("set nopassnewline"); data.doCommand("set expandtab"); data.doCommand("set shiftwidth=3"); diff --git a/src/plugins/fakevim/fakevimactions.cpp b/src/plugins/fakevim/fakevimactions.cpp index 4432e8d1b80..9672b6af231 100644 --- a/src/plugins/fakevim/fakevimactions.cpp +++ b/src/plugins/fakevim/fakevimactions.cpp @@ -180,6 +180,7 @@ FakeVimSettings *theFakeVimSettings() #endif createAction(s, ConfigShowMarks, false, _("ShowMarks"), _("sm")); createAction(s, ConfigPassControlKey, false, _("PassControlKey"), _("pck")); + createAction(s, ConfigPassNewLine, false, _("PassNewLine"), _("pnl")); // Emulated Vim setting createAction(s, ConfigStartOfLine, true, _("StartOfLine"), _("sol")); diff --git a/src/plugins/fakevim/fakevimactions.h b/src/plugins/fakevim/fakevimactions.h index 50471014fb6..ce20850c52d 100644 --- a/src/plugins/fakevim/fakevimactions.h +++ b/src/plugins/fakevim/fakevimactions.h @@ -93,6 +93,7 @@ enum FakeVimSettingsCode // other actions ConfigShowMarks, ConfigPassControlKey, + ConfigPassNewLine, ConfigClipboard, ConfigShowCmd, ConfigScrollOff diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index dd251c9243c..73ca096be67 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -1396,6 +1396,7 @@ public: void handleExCommand(const QString &cmd); void installEventFilter(); + void removeEventFilter(); void passShortcuts(bool enable); void setupWidget(); void restoreWidget(int tabSize); @@ -1728,6 +1729,8 @@ public: void joinLines(int count, bool preserveSpace = false); + void insertNewLine(); + // undo handling int revision() const { return document()->availableUndoSteps(); } void undoRedo(bool undo); @@ -2098,6 +2101,12 @@ void FakeVimHandler::Private::installEventFilter() EDITOR(installEventFilter(q)); } +void FakeVimHandler::Private::removeEventFilter() +{ + EDITOR(viewport()->removeEventFilter(q)); + EDITOR(removeEventFilter(q)); +} + void FakeVimHandler::Private::setupWidget() { m_mode = CommandMode; @@ -3661,26 +3670,38 @@ bool FakeVimHandler::Private::handleNoSubMode(const Input &input) bool insertAfter = input.is('o'); setDotCommand(_(insertAfter ? "%1o" : "%1O"), count()); setUndoPosition(); - enterInsertMode(); - // Insert new line so that command can be repeated [count] times inserting new line - // each time without unfolding any lines. - QTextBlock block = cursor().block(); - bool appendLine = false; - if (insertAfter) { - const int line = lineNumber(block); - appendLine = line >= document()->lineCount(); - setPosition(appendLine ? lastPositionInLine(line) : firstPositionInLine(line + 1)); - } else { - setPosition(block.position()); + + // Prepend line only if on the first line and command is 'O'. + bool appendLine = true; + if (!insertAfter) { + if (block().blockNumber() == 0) + appendLine = false; + else + moveUp(); } + const int line = lineNumber(block()); + + enterInsertMode(); beginEditBlock(); - insertText(QString::fromLatin1("\n")); - if (!appendLine) + if (appendLine) { + setPosition(lastPositionInLine(line)); + insertNewLine(); + } else { + setPosition(firstPositionInLine(line)); + insertNewLine(); moveUp(); - insertAutomaticIndentation(insertAfter); + } recordInsertion(QString::fromLatin1("\n")); setTargetColumn(); endEditBlock(); + + // Close accidentally opened block. + if (block().blockNumber() > 0) { + moveUp(); + if (line != lineNumber(block())) + emit q->fold(1, true); + moveDown(); + } } else if (input.isControl('o')) { jump(-count()); } else if (input.is('p') || input.is('P') || input.isShift(Qt::Key_Insert)) { @@ -4266,9 +4287,8 @@ EventResult FakeVimHandler::Private::handleInsertMode(const Input &input) } else if (input.isReturn() || input.isControl('j') || input.isControl('m')) { joinPreviousEditBlock(); m_submode = NoSubMode; - insertText(QString::fromLatin1("\n")); + insertNewLine(); insert = _("\n"); - insertAutomaticIndentation(true); endEditBlock(); } else if (input.isBackspace()) { joinPreviousEditBlock(); @@ -6456,6 +6476,30 @@ void FakeVimHandler::Private::joinLines(int count, bool preserveSpace) setPosition(pos); } +void FakeVimHandler::Private::insertNewLine() +{ + if ( hasConfig(ConfigPassNewLine) ) { + QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, QLatin1String("\n")); + + removeEventFilter(); + + QTextCursor tc = m_cursor; + tc.setPosition(tc.position()); + EDITOR(setTextCursor(tc)); + bool accepted = QApplication::sendEvent(editor(), &event); + + installEventFilter(); + + if (accepted) { + setPosition(EDITOR(textCursor()).position()); + return; + } + } + + insertText(QString::fromLatin1("\n")); + insertAutomaticIndentation(true); +} + QString FakeVimHandler::Private::lineContents(int line) const { return document()->findBlockByLineNumber(line - 1).text();