diff options
author | Jarek Kobus <jaroslaw.kobus@qt.io> | 2023-06-01 03:20:12 +0200 |
---|---|---|
committer | Jarek Kobus <jaroslaw.kobus@qt.io> | 2023-06-01 11:49:07 +0000 |
commit | d81d1bc14c08645749b0d5fda1675dd20a369ad2 (patch) | |
tree | 644f2495911eb8f7f2c90d3a90222d6959f82f3b /src/plugins/silversearcher | |
parent | 1afa720f2cfee575096fc7f6afc5a0760496675b (diff) |
SilverSearcher: Make the search cancellable
Especially when there are lot of files, and not too much results.
Change-Id: Id9e89c5d0d681e11dd8a9fb5c2373164dbeef3fd
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
Diffstat (limited to 'src/plugins/silversearcher')
-rw-r--r-- | src/plugins/silversearcher/findinfilessilversearcher.cpp | 50 | ||||
-rw-r--r-- | src/plugins/silversearcher/silversearcherparser.cpp | 36 | ||||
-rw-r--r-- | src/plugins/silversearcher/silversearcherparser.h | 16 |
3 files changed, 76 insertions, 26 deletions
diff --git a/src/plugins/silversearcher/findinfilessilversearcher.cpp b/src/plugins/silversearcher/findinfilessilversearcher.cpp index 43397a03f6d..b7e26d071b1 100644 --- a/src/plugins/silversearcher/findinfilessilversearcher.cpp +++ b/src/plugins/silversearcher/findinfilessilversearcher.cpp @@ -16,6 +16,7 @@ #include <QSettings> using namespace Core; +using namespace SilverSearcher; using namespace TextEditor; using namespace Utils; @@ -58,6 +59,21 @@ static bool isSilverSearcherAvailable() && silverSearcherProcess.cleanedStdOut().contains("ag version"); } +static std::optional<QRegularExpression> regExpFromParameters(const FileFindParameters ¶meters) +{ + if (!(parameters.flags & FindRegularExpression)) + return {}; + + const QRegularExpression::PatternOptions patternOptions + = (parameters.flags & FindCaseSensitively) + ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption; + QRegularExpression regExp; + regExp.setPattern(parameters.text); + regExp.setPatternOptions(patternOptions); + return regExp; +} + static void runSilverSeacher(QPromise<SearchResultItems> &promise, const FileFindParameters ¶meters) { @@ -92,26 +108,26 @@ static void runSilverSeacher(QPromise<SearchResultItems> &promise, arguments << "--" << parameters.text << directory.normalizedPathName().toString(); + QEventLoop loop; + Process process; process.setCommand({"ag", arguments}); + ParserState parserState; + const std::optional<QRegularExpression> regExp = regExpFromParameters(parameters); + process.setStdOutCallback([&promise, &parserState, regExp](const QString &output) { + SilverSearcher::parse(promise, output, &parserState, regExp); + }); + QObject::connect(&process, &Process::done, &loop, &QEventLoop::quit); + process.start(); - if (process.waitForFinished()) { - std::optional<QRegularExpression> regExp; - if (parameters.flags & FindRegularExpression) { - regExp = QRegularExpression(); - const QRegularExpression::PatternOptions patternOptions - = (parameters.flags & FindCaseSensitively) - ? QRegularExpression::NoPatternOption - : QRegularExpression::CaseInsensitiveOption; - regExp->setPattern(parameters.text); - regExp->setPatternOptions(patternOptions); - } - const SearchResultItems items = SilverSearcher::parse(process.cleanedStdOut(), regExp); - if (!items.isEmpty()) - promise.addResult(items); - } else { - promise.future().cancel(); - } + if (process.state() == QProcess::NotRunning) + return; + + QFutureWatcher<void> watcher; + QFuture<void> future(promise.future()); + QObject::connect(&watcher, &QFutureWatcherBase::canceled, &loop, &QEventLoop::quit); + watcher.setFuture(future); + loop.exec(QEventLoop::ExcludeUserInputEvents); } } // namespace diff --git a/src/plugins/silversearcher/silversearcherparser.cpp b/src/plugins/silversearcher/silversearcherparser.cpp index be4e9096c4c..9cdf5211a67 100644 --- a/src/plugins/silversearcher/silversearcherparser.cpp +++ b/src/plugins/silversearcher/silversearcherparser.cpp @@ -3,6 +3,8 @@ #include "silversearcherparser.h" +#include <QFuture> + using namespace Utils; namespace SilverSearcher { @@ -94,23 +96,28 @@ static bool parseLineHits(QStringView *remainingInput, QList<QPair<int, int>> *h return true; } -SearchResultItems parse(const QString &input, const std::optional<QRegularExpression> ®Exp) +void parse(QPromise<SearchResultItems> &promise, const QString &input, + ParserState *parserState, const std::optional<QRegularExpression> ®Exp) { + QTC_ASSERT(parserState, return); SearchResultItems items; QStringView remainingInput(input); while (true) { + if (promise.isCanceled()) + return; + if (remainingInput.isEmpty()) break; const QStringView filePathLine = nextLine(&remainingInput); - if (filePathLine.isEmpty()) - continue; - - if (!filePathLine.startsWith(':')) + if (filePathLine.isEmpty()) { + parserState->m_lastFilePath = {}; // Clear the parser state continue; + } - const FilePath filePath = FilePath::fromPathPart(filePathLine.mid(1)); + if (filePathLine.startsWith(':')) + parserState->m_lastFilePath = FilePath::fromPathPart(filePathLine.mid(1)); while (true) { QStringView hitLine = nextLine(&remainingInput); @@ -126,7 +133,7 @@ SearchResultItems parse(const QString &input, const std::optional<QRegularExpres break; SearchResultItem item; - item.setFilePath(filePath); + item.setFilePath(parserState->m_lastFilePath); item.setDisplayText(hitLine.toString()); item.setUseTextEditorFont(true); for (const QPair<int, int> &hit : hits) { @@ -138,7 +145,20 @@ SearchResultItems parse(const QString &input, const std::optional<QRegularExpres } } } - return items; + if (!items.isEmpty()) + promise.addResult(items); + + parserState->m_reportedResultsCount += items.count(); +} + +SearchResultItems parse(const QString &input, const std::optional<QRegularExpression> ®Exp) +{ + QPromise<SearchResultItems> promise; + promise.start(); + ParserState dummy; + SilverSearcher::parse(promise, input, &dummy, regExp); + promise.finish(); + return promise.future().resultCount() ? promise.future().result() : SearchResultItems(); } } // namespace SilverSearcher diff --git a/src/plugins/silversearcher/silversearcherparser.h b/src/plugins/silversearcher/silversearcherparser.h index f9d8502759a..1cc5ccb773c 100644 --- a/src/plugins/silversearcher/silversearcherparser.h +++ b/src/plugins/silversearcher/silversearcherparser.h @@ -5,11 +5,25 @@ #include <utils/searchresultitem.h> +#include <QPromise> #include <QRegularExpression> +namespace Utils { class FilePath; } + namespace SilverSearcher { -Utils::SearchResultItems parse(const QString &output, +class ParserState +{ +public: + Utils::FilePath m_lastFilePath; + int m_reportedResultsCount = 0; +}; + +void parse(QPromise<Utils::SearchResultItems> &promise, const QString &input, + ParserState *parserState = nullptr, + const std::optional<QRegularExpression> ®Exp = {}); + +Utils::SearchResultItems parse(const QString &input, const std::optional<QRegularExpression> ®Exp = {}); } // namespace SilverSearcher |