find&replace: support \n for back reference in replace text

This commit is contained in:
Le Tan 2018-03-07 21:04:34 +08:00
parent d3f9ec48eb
commit 469f4b43cc
2 changed files with 79 additions and 4 deletions

View File

@ -41,7 +41,7 @@ void VFindReplaceDialog::setupUI()
// Replace // Replace
QLabel *replaceLabel = new QLabel(tr("&Replace with:")); QLabel *replaceLabel = new QLabel(tr("&Replace with:"));
m_replaceEdit = new VLineEdit(); m_replaceEdit = new VLineEdit();
m_replaceEdit->setPlaceholderText(tr("Enter text to replace with")); m_replaceEdit->setPlaceholderText(tr("\\1, \\2 for back reference in regular expression"));
replaceLabel->setBuddy(m_replaceEdit); replaceLabel->setBuddy(m_replaceEdit);
m_replaceBtn = new QPushButton(tr("Replace")); m_replaceBtn = new QPushButton(tr("Replace"));
m_replaceBtn->setProperty("FlatBtn", true); m_replaceBtn->setProperty("FlatBtn", true);

View File

@ -695,6 +695,47 @@ void VEditor::highlightSearchedWordUnderCursor(const QTextCursor &p_cursor)
highlightExtraSelections(true); highlightExtraSelections(true);
} }
static void fillReplaceTextWithBackReference(QString &p_replaceText,
const QString &p_text,
const QRegExp &p_exp)
{
int idx = p_exp.indexIn(p_text);
if (idx != 0) {
return;
}
QStringList caps = p_exp.capturedTexts();
if (caps.size() < 2) {
return;
}
QChar sla('\\');
int pos = 0;
while (pos < p_replaceText.size()) {
int idx = p_replaceText.indexOf(sla, pos);
if (idx == -1 || idx == p_replaceText.size() - 1) {
break;
}
QChar ne(p_replaceText[idx + 1]);
if (ne == sla) {
// \\ to \.
p_replaceText.remove(idx, 1);
} else if (ne.isDigit()) {
// TODO: for now, we only support 1 - 9.
int num = ne.digitValue();
if (num > 0 && num < caps.size()) {
// Replace it.
p_replaceText.replace(idx, 2, caps[num]);
pos = idx + caps[num].size() - 2;
continue;
}
}
pos = idx + 1;
}
}
void VEditor::replaceText(const QString &p_text, void VEditor::replaceText(const QString &p_text,
uint p_options, uint p_options,
const QString &p_replaceText, const QString &p_replaceText,
@ -703,16 +744,32 @@ void VEditor::replaceText(const QString &p_text,
QTextCursor cursor = textCursorW(); QTextCursor cursor = textCursorW();
bool wrapped = false; bool wrapped = false;
QTextCursor retCursor; QTextCursor retCursor;
QString newText(p_replaceText);
bool useRegExp = p_options & FindOption::RegularExpression;
QRegExp exp;
if (useRegExp) {
exp = QRegExp(p_text,
p_options & FindOption::CaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
}
bool found = findTextHelper(p_text, bool found = findTextHelper(p_text,
p_options, true, p_options,
true,
cursor.position(), cursor.position(),
wrapped, wrapped,
retCursor); retCursor);
if (found) { if (found) {
if (retCursor.selectionStart() == cursor.position()) { if (retCursor.selectionStart() == cursor.position()) {
// Matched. // Matched.
if (useRegExp) {
// Handle \1, \2 in replace text.
fillReplaceTextWithBackReference(newText,
VEditUtils::selectedText(retCursor),
exp);
}
retCursor.beginEditBlock(); retCursor.beginEditBlock();
retCursor.insertText(p_replaceText); retCursor.insertText(newText);
retCursor.endEditBlock(); retCursor.endEditBlock();
setTextCursorW(retCursor); setTextCursorW(retCursor);
} }
@ -734,6 +791,17 @@ void VEditor::replaceTextAll(const QString &p_text,
tmpCursor.setPosition(0); tmpCursor.setPosition(0);
setTextCursorW(tmpCursor); setTextCursorW(tmpCursor);
int start = tmpCursor.position(); int start = tmpCursor.position();
QString newText;
bool useRegExp = p_options & FindOption::RegularExpression;
QRegExp exp;
if (useRegExp) {
exp = QRegExp(p_text,
p_options & FindOption::CaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
} else {
newText = p_replaceText;
}
while (true) { while (true) {
bool wrapped = false; bool wrapped = false;
QTextCursor retCursor; QTextCursor retCursor;
@ -751,9 +819,16 @@ void VEditor::replaceTextAll(const QString &p_text,
break; break;
} }
if (useRegExp) {
newText = p_replaceText;
fillReplaceTextWithBackReference(newText,
VEditUtils::selectedText(retCursor),
exp);
}
nrReplaces++; nrReplaces++;
retCursor.beginEditBlock(); retCursor.beginEditBlock();
retCursor.insertText(p_replaceText); retCursor.insertText(newText);
retCursor.endEditBlock(); retCursor.endEditBlock();
setTextCursorW(retCursor); setTextCursorW(retCursor);
start = retCursor.position(); start = retCursor.position();