From 002db1fa4288b8e88bb1740c0eb84f06d601e462 Mon Sep 17 00:00:00 2001 From: Timon Riedelbauch Date: Mon, 1 Feb 2021 02:46:07 +0100 Subject: [PATCH] add special characters \u \U \l \L to fakevim substitute command vim substitute (:s/) hast the option to use special characters \u \U \l \L in the replacement part to change the case of the following letters. This was not present in fakevim. Change-Id: I13785db24018283c242d94fd7892765657570176 Reviewed-by: hjk --- src/plugins/fakevim/fakevim_test.cpp | 12 +++++ src/plugins/fakevim/fakevimhandler.cpp | 68 ++++++++++++++++++++++++-- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/plugins/fakevim/fakevim_test.cpp b/src/plugins/fakevim/fakevim_test.cpp index 88973a5200e..81eee1973f0 100644 --- a/src/plugins/fakevim/fakevim_test.cpp +++ b/src/plugins/fakevim/fakevim_test.cpp @@ -3006,6 +3006,18 @@ void FakeVimPlugin::test_vim_substitute() COMMAND("undo | s/[bcef]//g", "a d"); COMMAND("undo | s/\\w//g", " "); COMMAND("undo | s/f\\|$/-/g", "abc de-"); + + // modifiers + data.setText("abC dEfGh"); + COMMAND("s/b...E/\\u&", "aBC dEfGh"); + COMMAND("undo | s/b...E/\\U&/g", "aBC DEfGh"); + COMMAND("undo | s/C..E/\\l&/g", "abc dEfGh"); + COMMAND("undo | s/b...E/\\L&/g", "abc defGh"); + + COMMAND("undo | s/\\(b...E\\)/\\u\\1/g", "aBC dEfGh"); + COMMAND("undo | s/\\(b...E\\)/\\U\\1/g", "aBC DEfGh"); + COMMAND("undo | s/\\(C..E\\)/\\l\\1/g", "abc dEfGh"); + COMMAND("undo | s/\\(b...E\\)/\\L\\1/g", "abc defGh"); } void FakeVimPlugin::test_vim_ex_commandbuffer_paste() diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index ea0be66d54a..e4147e55806 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -700,6 +700,47 @@ static char backslashed(char t) return t; } +enum class Modifier {NONE,UPPERCASE,LOWERCASE}; + +static QString applyReplacementLetterCases(QString repl, + Modifier &toggledModifier, + Modifier &nextCharacterModifier) +{ + if (toggledModifier == Modifier::UPPERCASE) + repl = repl.toUpper(); + else if (toggledModifier == Modifier::LOWERCASE) + repl = repl.toLower(); + + if (nextCharacterModifier == Modifier::UPPERCASE) { + repl.replace(0, 1, repl.at(0).toUpper()); + nextCharacterModifier = Modifier::NONE; + } else if (nextCharacterModifier == Modifier::LOWERCASE) { + repl.replace(0, 1, repl.at(0).toLower()); + nextCharacterModifier = Modifier::NONE; + } + return repl; +} + +static QChar applyReplacementLetterCases(QChar repl, + Modifier &toggledModifier, + Modifier &nextCharacterModifier) +{ + if (nextCharacterModifier == Modifier::UPPERCASE){ + nextCharacterModifier = Modifier::NONE; + return repl.toUpper(); + } + else if (nextCharacterModifier == Modifier::LOWERCASE) { + nextCharacterModifier = Modifier::NONE; + return repl.toLower(); + } + else if (toggledModifier == Modifier::UPPERCASE) + return repl.toUpper(); + else if (toggledModifier == Modifier::LOWERCASE) + return repl.toLower(); + else + return repl; +} + static bool substituteText(QString *text, const QRegularExpression &pattern, const QString &replacement, @@ -729,14 +770,31 @@ static bool substituteText(QString *text, QString matched = text->mid(pos, match.captured(0).size()); QString repl; bool escape = false; + Modifier toggledModifier = Modifier::NONE; + Modifier nextCharacterModifier = Modifier::NONE; // insert captured texts for (int i = 0; i < replacement.size(); ++i) { const QChar &c = replacement[i]; if (escape) { escape = false; if (c.isDigit()) { - if (c.digitValue() <= match.lastCapturedIndex()) - repl += match.captured(c.digitValue()); + if (c.digitValue() <= match.lastCapturedIndex()) { + repl += applyReplacementLetterCases(match.captured(c.digitValue()), + toggledModifier, + nextCharacterModifier); + + } + } else if (c == 'u') { + nextCharacterModifier = Modifier::UPPERCASE; + } else if (c == 'l') { + nextCharacterModifier = Modifier::LOWERCASE; + } else if (c == 'U') { + toggledModifier = Modifier::UPPERCASE; + } else if (c == 'L') { + toggledModifier = Modifier::LOWERCASE; + } else if (c == 'e' || c == 'E') { + nextCharacterModifier = Modifier::NONE; + toggledModifier = Modifier::NONE; } else { repl += backslashed(c.unicode()); } @@ -744,9 +802,11 @@ static bool substituteText(QString *text, if (c == '\\') escape = true; else if (c == '&') - repl += match.captured(0); + repl += applyReplacementLetterCases(match.captured(0), + toggledModifier, + nextCharacterModifier); else - repl += c; + repl += applyReplacementLetterCases(c, toggledModifier, nextCharacterModifier); } } text->replace(pos, matched.size(), repl);