From ceaedb088314ddbbcc416748f8cc0319ebf21aa8 Mon Sep 17 00:00:00 2001 From: Lukas Holecek <hluk@email.cz> Date: Sat, 29 Sep 2012 19:09:08 +0200 Subject: [PATCH] fakevim: Correct Undo/Redo position for large editing operations Change-Id: Ie5d354a0e7f59c61646d14da79bf7059821c12e5 Reviewed-by: hjk <qthjk@ovi.com> --- src/plugins/fakevim/fakevim_test.cpp | 25 +++++++-- src/plugins/fakevim/fakevimhandler.cpp | 78 ++++++++++++++++++-------- 2 files changed, 74 insertions(+), 29 deletions(-) diff --git a/src/plugins/fakevim/fakevim_test.cpp b/src/plugins/fakevim/fakevim_test.cpp index f75e65a7554..92c3fe80987 100644 --- a/src/plugins/fakevim/fakevim_test.cpp +++ b/src/plugins/fakevim/fakevim_test.cpp @@ -714,20 +714,19 @@ void FakeVimPlugin::test_vim_undo_redo() void FakeVimPlugin::test_advanced_commands() { - // TODO: Fix undo/redo position for substitute command. TestData data; setup(&data); // subcommands - data.setText("abc" N " xxx" N "def"); - COMMAND("%s/xxx/ZZZ/g|%s/ZZZ/OOO/g", "abc" N " OOO" N "def"); + data.setText("abc" N " xxx" N " xxx" N "def"); + COMMAND("%s/xxx/ZZZ/g|%s/ZZZ/OOO/g", "abc" N " OOO" N " " X "OOO" N "def"); // undo/redo all subcommands - COMMAND(":undo", "abc" N " xxx" N "def"); - COMMAND(":redo", "abc" N " OOO" N "def"); + COMMAND(":undo", "abc" N X " xxx" N " xxx" N "def"); + COMMAND(":redo", "abc" N X " OOO" N " OOO" N "def"); // redundant characters - COMMAND("::: %s/\\S\\S\\S/ZZZ/g | :::: %s/ZZZ/XXX/g ", "XXX" N " XXX" N "XXX"); + COMMAND("::: %s/\\S\\S\\S/ZZZ/g | :::: %s/ZZZ/XXX/g ", "XXX" N " XXX" N " XXX" N X "XXX"); } void FakeVimPlugin::test_map() @@ -840,6 +839,20 @@ void FakeVimPlugin::test_map() KEYS("<C-r>", X "def xyz ghi"); data.doCommand("unmap X"); + data.setText("abc" N " def" N " ghi"); + data.doCommand("map X jdd"); + KEYS("X", "abc" N " " X "ghi"); + KEYS("u", "abc" N X " def" N " ghi"); + KEYS("<c-r>", "abc" N X " ghi"); + data.doCommand("unmap X"); + + data.setText("abc" N "def" N "ghi"); + data.doCommand("map X jAxxx<cr>yyy<esc>"); + KEYS("X", "abc" N "defxxx" N "yy" X "y" N "ghi"); + KEYS("u", "abc" N "de" X "f" N "ghi"); + KEYS("<c-r>", "abc" N "def" X "xxx" N "yyy" N "ghi"); + data.doCommand("unmap X"); + NOT_IMPLEMENTED // <C-o> data.setText("abc def"); diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 3fccc3697dd..f3b0b3cc690 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -1315,21 +1315,11 @@ public: QTextDocument *document() const { return EDITOR(document()); } QChar characterAtCursor() const { return document()->characterAt(position()); } - void joinPreviousEditBlock() { - UNDO_DEBUG("JOIN"); - if (m_breakEditBlock) - beginEditBlock(); - else - cursor().joinPreviousEditBlock(); - } - void beginEditBlock() { - UNDO_DEBUG("BEGIN EDIT BLOCK"); - cursor().beginEditBlock(); - setUndoPosition(false); - m_breakEditBlock = false; - } - void endEditBlock() - { UNDO_DEBUG("END EDIT BLOCK"); cursor().endEditBlock(); } + + void joinPreviousEditBlock(); + void beginEditBlock(bool rememberPosition = true); + void beginLargeEditBlock() { beginEditBlock(false); } + void endEditBlock(); void breakEditBlock() { m_breakEditBlock = true; } bool isVisualMode() const { return m_visualMode != NoVisualMode; } @@ -2005,7 +1995,7 @@ void FakeVimHandler::Private::handleMappedKeys() g.pendingInput << inputs << Input() << rest; g.mapStates << MappingState(maxMapDepth, inputs.noremap(), inputs.silent()); g.commandBuffer.setHistoryAutoSave(false); - beginEditBlock(); + beginLargeEditBlock(); } g.currentMap.reset(); } @@ -4001,8 +3991,6 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd) replacement = line.mid(pos1 + 1, pos2 - pos1 - 1); flags = line.mid(pos2 + 1); - needle.replace('$', '\n'); - needle.replace("\\\n", "\\$"); pattern = vimPatternToQtPattern(needle, hasConfig(ConfigSmartCase)); m_lastSubstituteFlags = flags; @@ -4016,7 +4004,8 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd) if (flags.contains('i')) pattern.setCaseSensitivity(Qt::CaseInsensitive); - beginEditBlock(); + int lastLine = -1; + int firstLine = -1; const bool global = flags.contains('g'); for (int a = 0; a != count; ++a) { const Range range = cmd.range.endPos == 0 ? rangeFromCurrentLine() : cmd.range; @@ -4046,6 +4035,13 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd) repl.replace("\\&", "&"); text = text.left(pos) + repl + text.mid(pos + matched.size()); pos += repl.size(); + + firstLine = line; + if (lastLine == -1) { + lastLine = line; + beginEditBlock(); + } + if (!global) break; } @@ -4053,9 +4049,21 @@ bool FakeVimHandler::Private::handleExSubstituteCommand(const ExCommand &cmd) setLineContents(line, text); } } - moveToStartOfLine(); - setTargetColumn(); - endEditBlock(); + + if (lastLine != -1) { + State &state = m_undo.top(); + state.line = firstLine; + state.position = firstPositionInLine(firstLine); + + QTextCursor tc = cursor(); + tc.setPosition(firstPositionInLine(lastLine)); + setCursor(tc); + moveToFirstNonBlankOnLine(); + setTargetColumn(); + + endEditBlock(); + } + return true; } @@ -4530,7 +4538,7 @@ void FakeVimHandler::Private::handleExCommand(const QString &line0) cmd.setContentsFromLine(line); //qDebug() << "CMD: " << cmd; - beginEditBlock(); + beginLargeEditBlock(); while (cmd.nextSubcommand()) { if (!handleExCommandHelper(cmd)) { showMessage(MessageError, @@ -5668,6 +5676,30 @@ QWidget *FakeVimHandler::Private::editor() const : static_cast<QWidget *>(m_plaintextedit); } +void FakeVimHandler::Private::joinPreviousEditBlock() +{ + UNDO_DEBUG("JOIN"); + if (m_breakEditBlock) + beginEditBlock(); + else + cursor().joinPreviousEditBlock(); +} + +void FakeVimHandler::Private::beginEditBlock(bool rememberPosition) +{ + UNDO_DEBUG("BEGIN EDIT BLOCK"); + cursor().beginEditBlock(); + if (rememberPosition) + setUndoPosition(false); + m_breakEditBlock = false; +} + +void FakeVimHandler::Private::endEditBlock() +{ + UNDO_DEBUG("END EDIT BLOCK"); + cursor().endEditBlock(); +} + char FakeVimHandler::Private::currentModeCode() const { if (m_mode == ExMode) -- GitLab