forked from qt-creator/qt-creator
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 <hjk@qt.io>
This commit is contained in:
@@ -3006,6 +3006,18 @@ void FakeVimPlugin::test_vim_substitute()
|
|||||||
COMMAND("undo | s/[bcef]//g", "a d");
|
COMMAND("undo | s/[bcef]//g", "a d");
|
||||||
COMMAND("undo | s/\\w//g", " ");
|
COMMAND("undo | s/\\w//g", " ");
|
||||||
COMMAND("undo | s/f\\|$/-/g", "abc de-");
|
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()
|
void FakeVimPlugin::test_vim_ex_commandbuffer_paste()
|
||||||
|
@@ -700,6 +700,47 @@ static char backslashed(char t)
|
|||||||
return 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,
|
static bool substituteText(QString *text,
|
||||||
const QRegularExpression &pattern,
|
const QRegularExpression &pattern,
|
||||||
const QString &replacement,
|
const QString &replacement,
|
||||||
@@ -729,14 +770,31 @@ static bool substituteText(QString *text,
|
|||||||
QString matched = text->mid(pos, match.captured(0).size());
|
QString matched = text->mid(pos, match.captured(0).size());
|
||||||
QString repl;
|
QString repl;
|
||||||
bool escape = false;
|
bool escape = false;
|
||||||
|
Modifier toggledModifier = Modifier::NONE;
|
||||||
|
Modifier nextCharacterModifier = Modifier::NONE;
|
||||||
// insert captured texts
|
// insert captured texts
|
||||||
for (int i = 0; i < replacement.size(); ++i) {
|
for (int i = 0; i < replacement.size(); ++i) {
|
||||||
const QChar &c = replacement[i];
|
const QChar &c = replacement[i];
|
||||||
if (escape) {
|
if (escape) {
|
||||||
escape = false;
|
escape = false;
|
||||||
if (c.isDigit()) {
|
if (c.isDigit()) {
|
||||||
if (c.digitValue() <= match.lastCapturedIndex())
|
if (c.digitValue() <= match.lastCapturedIndex()) {
|
||||||
repl += match.captured(c.digitValue());
|
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 {
|
} else {
|
||||||
repl += backslashed(c.unicode());
|
repl += backslashed(c.unicode());
|
||||||
}
|
}
|
||||||
@@ -744,9 +802,11 @@ static bool substituteText(QString *text,
|
|||||||
if (c == '\\')
|
if (c == '\\')
|
||||||
escape = true;
|
escape = true;
|
||||||
else if (c == '&')
|
else if (c == '&')
|
||||||
repl += match.captured(0);
|
repl += applyReplacementLetterCases(match.captured(0),
|
||||||
|
toggledModifier,
|
||||||
|
nextCharacterModifier);
|
||||||
else
|
else
|
||||||
repl += c;
|
repl += applyReplacementLetterCases(c, toggledModifier, nextCharacterModifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
text->replace(pos, matched.size(), repl);
|
text->replace(pos, matched.size(), repl);
|
||||||
|
Reference in New Issue
Block a user