aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/silversearcher
diff options
context:
space:
mode:
authorJarek Kobus <jaroslaw.kobus@qt.io>2023-06-01 03:20:12 +0200
committerJarek Kobus <jaroslaw.kobus@qt.io>2023-06-01 11:49:07 +0000
commitd81d1bc14c08645749b0d5fda1675dd20a369ad2 (patch)
tree644f2495911eb8f7f2c90d3a90222d6959f82f3b /src/plugins/silversearcher
parent1afa720f2cfee575096fc7f6afc5a0760496675b (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.cpp50
-rw-r--r--src/plugins/silversearcher/silversearcherparser.cpp36
-rw-r--r--src/plugins/silversearcher/silversearcherparser.h16
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 &parameters)
+{
+ 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 &parameters)
{
@@ -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> &regExp)
+void parse(QPromise<SearchResultItems> &promise, const QString &input,
+ ParserState *parserState, const std::optional<QRegularExpression> &regExp)
{
+ 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> &regExp)
+{
+ 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> &regExp = {});
+
+Utils::SearchResultItems parse(const QString &input,
const std::optional<QRegularExpression> &regExp = {});
} // namespace SilverSearcher