diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp index 997faf2452285ce93ba2b1b10db89ef498047be1..677a678959d3e26be858a73055b65b833614c908 100644 --- a/src/libs/utils/filesearch.cpp +++ b/src/libs/utils/filesearch.cpp @@ -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; +} diff --git a/src/libs/utils/filesearch.h b/src/libs/utils/filesearch.h index e7f91a6719c50de779c3771cd8f33ae8973186f3..f2860e34e0147c4bb6990326ca53ef1da539f360 100644 --- a/src/libs/utils/filesearch.h +++ b/src/libs/utils/filesearch.h @@ -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 diff --git a/src/plugins/find/basetextfind.cpp b/src/plugins/find/basetextfind.cpp index d2ddfc0441856d79ad392f65804de325ac84c5b2..86dd69e33c666b81a218ffdfe58b3efd805403d2 100644 --- a/src/plugins/find/basetextfind.cpp +++ b/src/plugins/find/basetextfind.cpp @@ -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)); } diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp index 2bacef7cb36796a7cad84cef4b34aa9d18ad580f..650c13b0206a2170afb331feb59e5118e01ff653 100644 --- a/src/plugins/texteditor/basefilefind.cpp +++ b/src/plugins/texteditor/basefilefind.cpp @@ -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,