From 70adf53fbdc01f00c31261e532aad70507859246 Mon Sep 17 00:00:00 2001 From: hluk Date: Sat, 16 Mar 2013 13:32:32 +0100 Subject: [PATCH] FakeVim: Option 'passnewline' (not in Vim) Option 'passnewline' ('pnl') passes new line in insert mode and on 'o' and 'O' commands to editor widget. This way the editor widget can handle the indentation or insert characters (e.g. asterisk if in C block comment). Change-Id: I06afab6b20b49e1b4d31447826c847d36d32806f Reviewed-by: hjk --- src/plugins/fakevim/fakevim_test.cpp | 1 + src/plugins/fakevim/fakevimactions.cpp | 1 + src/plugins/fakevim/fakevimactions.h | 1 + src/plugins/fakevim/fakevimhandler.cpp | 76 ++++++++++++++++++++------ 4 files changed, 63 insertions(+), 16 deletions(-) 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();