In a regex autoreplace, it's impossible to output a literal percent sign followed by a number. If I have a regex "foo-(\S*)" and replacement "bar%23%1", "foo-x" will output "bar3x", because the %2 is interpreted as a capturing subpattern, even though the regex only has one subpattern. The current code is: // replace %0 - %9 in regex groups for (int capture=0;capture<captures.count();capture++) { replacement.replace(QString("%%1").arg(capture),captures[capture]); } replacement.remove(QRegExp("%[0-9]")); Removing the last line would allow the previous example to work. However, it still doesn't solve the problem if I *do* have a second subpattern (or if I want to output %1). What we really need is a way to escape the percent sign. Instead of using replace(), I propose looping over the characters in the string. Pseudocode: foreach (char in string) { if (char == %) { look at the following character; if (char == %) output += '%'; //this lets you escape a % by doubling it if (char is digit) output += capture[digit]; else output += '%' + char; } else { output += char; } } I may implement this myself later.
commit a54b8543fa24de3bf6fe6993724b588a9e48a1b4 Author: Travis McHenry <wordsizzle@gmail.com> Date: Tue Dec 15 00:44:23 2009 -0700 Fix an autoreplace bug and enable escaping Make it so we can do multiple replaces in a single line again by not replacing the content of the 'global' replace variable BUG:211632 Make it so we can support %# in replacements without it getting lost in regex land by allowing escaping (with %%#).If you're so inclined please review the big comment explaining why we can't just not remove the leftover %# to make sure I'm not shooting hot air. BUG:218332 diff --git a/src/application.cpp b/src/application.cpp index cf61af5..79c7730 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -1007,18 +1007,27 @@ QString Application::doAutoreplace(const QString& text,bool output) { // remember captured patterns QStringList captures = needleReg.capturedTexts(); + QString replaceWith = replacement; - // replace %0 - %9 in regex groups + replaceWith.replace("%%","%\x01"); // escape double % + // replace %0-9 in regex groups for (int capture=0;capture<captures.count();capture++) { - replacement.replace(QString("%%1").arg(capture),captures[capture]); + QString search = QString("%%1").arg(capture); + replaceWith.replace(search, captures[capture]); } - replacement.remove(QRegExp("%[0-9]")); + //Explanation why this is important so we don't forget: + //If somebody has a regex that say has a replacement of url.com/%1/%2 and the + //regex can either match one or two patterns, if the 2nd pattern match is left, + //the url is invalid (url.com/match/%2). This is expected regex behavior I'd assume. + replaceWith.remove(QRegExp("%[0-9]")); + + replaceWith.replace("%\x01","%"); // return escaped % to normal // allow for var expansion in autoreplace - replacement = Konversation::doVarExpansion(replacement); + replaceWith = Konversation::doVarExpansion(replaceWith); // replace input with replacement - line.replace(index, captures[0].length(), replacement); - index += replacement.length(); + line.replace(index, captures[0].length(), replaceWith); + index += replaceWith.length(); } } while (index >= 0 && index < (int)line.length()); }