forked from qt-creator/qt-creator
Fixes: Multi-file regexp replace didn't replace placeholders e.g. \1
This commit is contained in:
@@ -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 ®exp)
|
||||
{
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user