Commit f232cd4e authored by con's avatar con
Browse files

Fixes: Multi-file regexp replace didn't replace placeholders e.g. \1

parent 3b4b2c3e
......@@ -170,7 +170,8 @@ void runFileSearch(QFutureInterface<FileSearchResult> &future,
while (startOfLastLine[i] != '\n' && startOfLastLine[i] != '\r' && i < textLength && n++ < 256)
res.append(startOfLastLine[i++]);
future.reportResult(FileSearchResult(s, lineNr, QString(res),
regionPtr - startOfLastLine, sa.length()));
regionPtr - startOfLastLine, sa.length(),
QStringList()));
++numMatches;
}
}
......@@ -229,7 +230,8 @@ void runFileSearchRegExp(QFutureInterface<FileSearchResult> &future,
int pos = 0;
while ((pos = expression.indexIn(line, pos)) != -1) {
future.reportResult(FileSearchResult(s, lineNr, line,
pos, expression.matchedLength()));
pos, expression.matchedLength(),
expression.capturedTexts()));
pos += expression.matchedLength();
}
++lineNr;
......@@ -259,3 +261,36 @@ QFuture<FileSearchResult> Utils::findInFilesRegExp(const QString &searchTerm, co
return QtConcurrent::run<FileSearchResult, QString, QStringList, QTextDocument::FindFlags, QMap<QString, QString> >
(runFileSearchRegExp, searchTerm, files, flags, fileToContentsMap);
}
QString Utils::expandRegExpReplacement(const QString &replaceText, const QStringList &capturedTexts)
{
QString result;
int numCaptures = capturedTexts.size() - 1;
for (int i = 0; i < replaceText.length(); ++i) {
QChar c = replaceText.at(i);
if (c == QLatin1Char('\\') && i < replaceText.length() - 1) {
c = replaceText.at(++i);
if (c == QLatin1Char('\\')) {
result += QLatin1Char('\\');
} else if (c == QLatin1Char('&')) {
result += QLatin1Char('&');
} else if (c.isDigit()) {
int index = c.unicode()-'1';
if (index < numCaptures) {
result += capturedTexts.at(index+1);
} else {
result += QLatin1Char('\\');
result += c;
}
} else {
result += QLatin1Char('\\');
result += c;
}
} else if (c == QLatin1Char('&')) {
result += capturedTexts.at(0);
} else {
result += c;
}
}
return result;
}
......@@ -43,8 +43,15 @@ class QTCREATOR_UTILS_EXPORT FileSearchResult
{
public:
FileSearchResult() {}
FileSearchResult(QString fileName, int lineNumber, QString matchingLine, int matchStart, int matchLength)
: fileName(fileName), lineNumber(lineNumber), matchingLine(matchingLine), matchStart(matchStart), matchLength(matchLength)
FileSearchResult(QString fileName, int lineNumber, QString matchingLine,
int matchStart, int matchLength,
QStringList regexpCapturedTexts)
: fileName(fileName),
lineNumber(lineNumber),
matchingLine(matchingLine),
matchStart(matchStart),
matchLength(matchLength),
regexpCapturedTexts(regexpCapturedTexts)
{
}
QString fileName;
......@@ -52,6 +59,7 @@ public:
QString matchingLine;
int matchStart;
int matchLength;
QStringList regexpCapturedTexts;
};
QTCREATOR_UTILS_EXPORT QFuture<FileSearchResult> findInFiles(const QString &searchTerm, const QStringList &files,
......@@ -60,6 +68,8 @@ QTCREATOR_UTILS_EXPORT QFuture<FileSearchResult> findInFiles(const QString &sear
QTCREATOR_UTILS_EXPORT QFuture<FileSearchResult> findInFilesRegExp(const QString &searchTerm, const QStringList &files,
QTextDocument::FindFlags flags, QMap<QString, QString> fileToContentsMap = QMap<QString, QString>());
QTCREATOR_UTILS_EXPORT QString expandRegExpReplacement(const QString &replaceText, const QStringList &capturedTexts);
} // namespace Utils
#endif // FILESEARCH_H
......@@ -30,6 +30,7 @@
#include "basetextfind.h"
#include <utils/qtcassert.h>
#include <utils/filesearch.h>
#include <QtGui/QTextBlock>
#include <QtGui/QPlainTextEdit>
......@@ -152,40 +153,6 @@ IFindSupport::Result BaseTextFind::findStep(const QString &txt, IFindSupport::Fi
return found ? Found : NotFound;
}
namespace {
QString expandRegExpReplacement(const QString &replaceText, const QRegExp &regexp)
{
QString result;
for (int i = 0; i < replaceText.length(); ++i) {
QChar c = replaceText.at(i);
if (c == QLatin1Char('\\') && i < replaceText.length() - 1) {
c = replaceText.at(++i);
if (c == QLatin1Char('\\')) {
result += QLatin1Char('\\');
} else if (c == QLatin1Char('&')) {
result += QLatin1Char('&');
} else if (c.isDigit()) {
int index = c.unicode()-'1';
if (index < regexp.numCaptures()) {
result += regexp.cap(index+1);
} else {
result += QLatin1Char('\\');
result += c;
}
} else {
result += QLatin1Char('\\');
result += c;
}
} else if (c == QLatin1Char('&')) {
result += regexp.cap(0);
} else {
result += c;
}
}
return result;
}
}
bool BaseTextFind::replaceStep(const QString &before, const QString &after,
IFindSupport::FindFlags findFlags)
{
......@@ -196,7 +163,7 @@ bool BaseTextFind::replaceStep(const QString &before, const QString &after,
usesRegExp ? QRegExp::RegExp : QRegExp::FixedString);
if (regexp.exactMatch(cursor.selectedText())) {
QString realAfter = usesRegExp ? expandRegExpReplacement(after, regexp) : after;
QString realAfter = usesRegExp ? Utils::expandRegExpReplacement(after, regexp.capturedTexts()) : after;
int start = cursor.selectionStart();
cursor.insertText(realAfter);
if ((findFlags&IFindSupport::FindBackward) != 0)
......@@ -226,7 +193,7 @@ int BaseTextFind::replaceAll(const QString &before, const QString &after,
editCursor.setPosition(found.selectionStart());
editCursor.setPosition(found.selectionEnd(), QTextCursor::KeepAnchor);
regexp.exactMatch(found.selectedText());
QString realAfter = usesRegExp ? expandRegExpReplacement(after, regexp) : after;
QString realAfter = usesRegExp ? Utils::expandRegExpReplacement(after, regexp.capturedTexts()) : after;
editCursor.insertText(realAfter);
found = findOne(regexp, editCursor, IFindSupport::textDocumentFlagsForFindFlags(findFlags));
}
......
......@@ -150,7 +150,8 @@ void BaseFileFind::displayResult(int index) {
result.lineNumber,
result.matchingLine,
result.matchStart,
result.matchLength);
result.matchLength,
result.regexpCapturedTexts);
if (m_resultLabel)
m_resultLabel->setText(tr("%1 found").arg(m_resultWindow->numberOfResults()));
}
......@@ -280,7 +281,7 @@ void BaseFileFind::openEditor(const Find::SearchResultItem &item)
static void applyChanges(QTextDocument *doc, const QString &text, const QList<Find::SearchResultItem> &items)
{
QList<QTextCursor> cursors;
QList<QPair<QTextCursor, QString> > changes;
foreach (const Find::SearchResultItem &item, items) {
const int blockNumber = item.lineNumber - 1;
......@@ -289,24 +290,31 @@ static void applyChanges(QTextDocument *doc, const QString &text, const QList<Fi
const int cursorPosition = tc.position() + item.searchTermStart;
int cursorIndex = 0;
for (; cursorIndex < cursors.size(); ++cursorIndex) {
const QTextCursor &tc = cursors.at(cursorIndex);
for (; cursorIndex < changes.size(); ++cursorIndex) {
const QTextCursor &otherTc = changes.at(cursorIndex).first;
if (tc.position() == cursorPosition)
if (otherTc.position() == cursorPosition)
break;
}
if (cursorIndex != cursors.size())
if (cursorIndex != changes.size())
continue; // skip this change.
tc.setPosition(cursorPosition);
tc.setPosition(tc.position() + item.searchTermLength,
QTextCursor::KeepAnchor);
cursors.append(tc);
QString substitutionText;
if (item.userData.canConvert<QStringList>() && !item.userData.toStringList().isEmpty())
substitutionText = Utils::expandRegExpReplacement(text, item.userData.toStringList());
else
substitutionText = text;
changes.append(QPair<QTextCursor, QString>(tc, substitutionText));
}
foreach (QTextCursor tc, cursors)
tc.insertText(text);
for (int i = 0; i < changes.size(); ++i) {
QPair<QTextCursor, QString> &cursor = changes[i];
cursor.first.insertText(cursor.second);
}
}
QStringList BaseFileFind::replaceAll(const QString &text,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment