diff --git a/src/libs/utils/fuzzymatcher.cpp b/src/libs/utils/fuzzymatcher.cpp index 819c723f6d3..6a3e0e50151 100644 --- a/src/libs/utils/fuzzymatcher.cpp +++ b/src/libs/utils/fuzzymatcher.cpp @@ -122,6 +122,21 @@ QRegularExpression FuzzyMatcher::createRegExp( return QRegularExpression('(' + plainRegExp + ")|" + keyRegExp); } +/** + \overload + This overload eases the construction of a fuzzy regexp from a given + Qt::CaseSensitivity. + */ +QRegularExpression FuzzyMatcher::createRegExp(const QString &pattern, + Qt::CaseSensitivity caseSensitivity) +{ + const CaseSensitivity sensitivity = (caseSensitivity == Qt::CaseSensitive) + ? CaseSensitivity::CaseSensitive + : CaseSensitivity::CaseInsensitive; + + return createRegExp(pattern, sensitivity); +} + /*! * \brief Returns a list of matched character positions and their matched lengths for the * given regular expression \a match. diff --git a/src/libs/utils/fuzzymatcher.h b/src/libs/utils/fuzzymatcher.h index 753742ac227..8e90ebe7968 100644 --- a/src/libs/utils/fuzzymatcher.h +++ b/src/libs/utils/fuzzymatcher.h @@ -54,5 +54,7 @@ public: static QRegularExpression createRegExp(const QString &pattern, CaseSensitivity caseSensitivity = CaseSensitivity::CaseInsensitive); + static QRegularExpression createRegExp(const QString &pattern, + Qt::CaseSensitivity caseSensitivity); static HighlightingPositions highlightingPositions(const QRegularExpressionMatch &match); }; diff --git a/src/plugins/coreplugin/locator/filesystemfilter.cpp b/src/plugins/coreplugin/locator/filesystemfilter.cpp index beab841fe7b..1266b008e74 100644 --- a/src/plugins/coreplugin/locator/filesystemfilter.cpp +++ b/src/plugins/coreplugin/locator/filesystemfilter.cpp @@ -35,30 +35,34 @@ #include #include +#include using namespace Core; using namespace Core::Internal; -namespace { +enum class MatchLevel { + Best = 0, + Better, + Good, + Normal, + Number +}; -QList *categorize(const QString &entry, const QString &candidate, - Qt::CaseSensitivity caseSensitivity, - QList *betterEntries, QList *goodEntries, - int *index) +static MatchLevel matchLevelFor(const QRegularExpressionMatch &match, const QString &matchText) { - const int position = candidate.indexOf(entry, 0, caseSensitivity); - if (index) - *index = position; - - if (entry.isEmpty() || position == 0) - return betterEntries; - if (position >= 0) - return goodEntries; - return nullptr; + const int consecutivePos = match.capturedStart(1); + if (consecutivePos == 0) + return MatchLevel::Best; + if (consecutivePos > 0) { + const QChar prevChar = matchText.at(consecutivePos - 1); + if (prevChar == '_' || prevChar == '.') + return MatchLevel::Better; + } + if (match.capturedStart() == 0) + return MatchLevel::Good; + return MatchLevel::Normal; } -} // anynoumous namespace - FileSystemFilter::FileSystemFilter() { setId("Files in file system"); @@ -76,8 +80,7 @@ void FileSystemFilter::prepareSearch(const QString &entry) QList FileSystemFilter::matchesFor(QFutureInterface &future, const QString &entry) { - QList goodEntries; - QList betterEntries; + QList entries[int(MatchLevel::Number)]; const QFileInfo entryInfo(entry); const QString entryFileName = entryInfo.fileName(); QString directory = entryInfo.path(); @@ -101,19 +104,24 @@ QList FileSystemFilter::matchesFor(QFutureInterface *category = categorize(entryFileName, dir, caseSensitivity_, - &betterEntries, &goodEntries, &index)) { + + const QRegularExpressionMatch match = regExp.match(dir); + if (match.hasMatch()) { + const MatchLevel level = matchLevelFor(match, dir); const QString fullPath = dirInfo.filePath(dir); LocatorFilterEntry filterEntry(this, dir, QVariant()); filterEntry.fileName = fullPath; - if (index >= 0) - filterEntry.highlightInfo = {index, entryFileName.length()}; + filterEntry.highlightInfo = highlightInfo(match); - category->append(filterEntry); + entries[int(level)].append(filterEntry); } } // file names can match with +linenumber or :linenumber @@ -122,29 +130,29 @@ QList FileSystemFilter::matchesFor(QFutureInterface *category = categorize(fileName, file, caseSensitivity_, - &betterEntries, &goodEntries, &index)) { + + const QRegularExpressionMatch match = regExp.match(file); + if (match.hasMatch()) { + const MatchLevel level = matchLevelFor(match, file); const QString fullPath = dirInfo.filePath(file); LocatorFilterEntry filterEntry(this, file, QString(fullPath + fp.postfix)); filterEntry.fileName = fullPath; - if (index >= 0) - filterEntry.highlightInfo = {index, fileName.length()}; + filterEntry.highlightInfo = highlightInfo(match); - category->append(filterEntry); + entries[int(level)].append(filterEntry); } } - betterEntries.append(goodEntries); // "create and open" functionality const QString fullFilePath = dirInfo.filePath(fileName); - if (!QFileInfo::exists(fullFilePath) && dirInfo.exists()) { + const bool containsWildcard = entry.contains('?') || entry.contains('*'); + if (!containsWildcard && !QFileInfo::exists(fullFilePath) && dirInfo.exists()) { LocatorFilterEntry createAndOpen(this, tr("Create and Open \"%1\"").arg(entry), fullFilePath); createAndOpen.extraInfo = Utils::FilePath::fromString(dirInfo.absolutePath()).shortNativePath(); - betterEntries.append(createAndOpen); + entries[int(MatchLevel::Normal)].append(createAndOpen); } - return betterEntries; + return std::accumulate(std::begin(entries), std::end(entries), QList()); } void FileSystemFilter::accept(LocatorFilterEntry selection, diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.cpp b/src/plugins/coreplugin/locator/ilocatorfilter.cpp index 79aee8f6373..222ba82c4f8 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.cpp +++ b/src/plugins/coreplugin/locator/ilocatorfilter.cpp @@ -207,9 +207,9 @@ Qt::CaseSensitivity ILocatorFilter::caseSensitivity(const QString &str) return str == str.toLower() ? Qt::CaseInsensitive : Qt::CaseSensitive; } -QRegularExpression ILocatorFilter::createRegExp(const QString &text) +QRegularExpression ILocatorFilter::createRegExp(const QString &text, Qt::CaseSensitivity caseSensitivity) { - return FuzzyMatcher::createRegExp(text); + return FuzzyMatcher::createRegExp(text, caseSensitivity); } LocatorFilterEntry::HighlightInfo ILocatorFilter::highlightInfo( diff --git a/src/plugins/coreplugin/locator/ilocatorfilter.h b/src/plugins/coreplugin/locator/ilocatorfilter.h index ecb47eaae20..92b00be8120 100644 --- a/src/plugins/coreplugin/locator/ilocatorfilter.h +++ b/src/plugins/coreplugin/locator/ilocatorfilter.h @@ -145,7 +145,8 @@ public: bool isEnabled() const; static Qt::CaseSensitivity caseSensitivity(const QString &str); - static QRegularExpression createRegExp(const QString &text); + static QRegularExpression createRegExp(const QString &text, + Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive); LocatorFilterEntry::HighlightInfo highlightInfo(const QRegularExpressionMatch &match, LocatorFilterEntry::HighlightInfo::DataType dataType = LocatorFilterEntry::HighlightInfo::DisplayName);