Merge pull request #4 from Flow-Launcher/acronym_scoring

Acronym Scoring Change
This commit is contained in:
taooceros 2021-02-02 15:09:58 +08:00 committed by GitHub
commit 95325a8f0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 173 additions and 109 deletions

View file

@ -66,13 +66,13 @@ namespace Flow.Launcher.Infrastructure
var currentAcronymQueryIndex = 0; var currentAcronymQueryIndex = 0;
var acronymMatchData = new List<int>(); var acronymMatchData = new List<int>();
// preset acronymScore int acronymsTotalCount = 0;
int acronymScore = 100; int acronymsMatched = 0;
var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare; var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
var queryWithoutCase = opt.IgnoreCase ? query.ToLower() : query; var queryWithoutCase = opt.IgnoreCase ? query.ToLower() : query;
var querySubstrings = queryWithoutCase.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); var querySubstrings = queryWithoutCase.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
int currentQuerySubstringIndex = 0; int currentQuerySubstringIndex = 0;
var currentQuerySubstring = querySubstrings[currentQuerySubstringIndex]; var currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
var currentQuerySubstringCharacterIndex = 0; var currentQuerySubstringCharacterIndex = 0;
@ -87,12 +87,18 @@ namespace Flow.Launcher.Infrastructure
var indexList = new List<int>(); var indexList = new List<int>();
List<int> spaceIndices = new List<int>(); List<int> spaceIndices = new List<int>();
bool spaceMet = false;
for (var compareStringIndex = 0; compareStringIndex < fullStringToCompareWithoutCase.Length; compareStringIndex++) for (var compareStringIndex = 0; compareStringIndex < fullStringToCompareWithoutCase.Length; compareStringIndex++)
{ {
if (currentAcronymQueryIndex >= queryWithoutCase.Length // If acronyms matching successfully finished, this gets the remaining not matched acronyms for score calculation
|| allQuerySubstringsMatched && acronymScore < (int) UserSettingSearchPrecision) if (currentAcronymQueryIndex >= query.Length && acronymsMatched == query.Length)
{
if (IsAcronymCount(stringToCompare, compareStringIndex))
acronymsTotalCount++;
continue;
}
if (currentAcronymQueryIndex >= query.Length ||
currentAcronymQueryIndex >= query.Length && allQuerySubstringsMatched)
break; break;
// To maintain a list of indices which correspond to spaces in the string to compare // To maintain a list of indices which correspond to spaces in the string to compare
@ -101,42 +107,21 @@ namespace Flow.Launcher.Infrastructure
spaceIndices.Add(compareStringIndex); spaceIndices.Add(compareStringIndex);
// Acronym check // Acronym check
if (char.IsUpper(stringToCompare[compareStringIndex]) || if (IsAcronym(stringToCompare, compareStringIndex))
char.IsNumber(stringToCompare[compareStringIndex]) ||
char.IsWhiteSpace(stringToCompare[compareStringIndex]) ||
spaceMet)
{ {
if (fullStringToCompareWithoutCase[compareStringIndex] == if (fullStringToCompareWithoutCase[compareStringIndex] ==
queryWithoutCase[currentAcronymQueryIndex]) queryWithoutCase[currentAcronymQueryIndex])
{ {
if (!spaceMet) acronymMatchData.Add(compareStringIndex);
{ acronymsMatched++;
char currentCompareChar = stringToCompare[compareStringIndex];
spaceMet = char.IsWhiteSpace(currentCompareChar);
// if is space, no need to check whether upper or digit, though insignificant
if (!spaceMet && compareStringIndex == 0 || char.IsUpper(currentCompareChar) ||
char.IsDigit(currentCompareChar))
{
acronymMatchData.Add(compareStringIndex);
}
}
else if (!(spaceMet = char.IsWhiteSpace(stringToCompare[compareStringIndex])))
{
acronymMatchData.Add(compareStringIndex);
}
currentAcronymQueryIndex++; currentAcronymQueryIndex++;
} }
else
{
spaceMet = char.IsWhiteSpace(stringToCompare[compareStringIndex]);
// Acronym Penalty
if (!spaceMet)
{
acronymScore -= 10;
}
}
} }
if (IsAcronymCount(stringToCompare, compareStringIndex))
acronymsTotalCount++;
// Acronym end // Acronym end
if (allQuerySubstringsMatched || fullStringToCompareWithoutCase[compareStringIndex] != if (allQuerySubstringsMatched || fullStringToCompareWithoutCase[compareStringIndex] !=
@ -204,11 +189,16 @@ namespace Flow.Launcher.Infrastructure
} }
} }
// return acronym Match if possible // return acronym match if all query char matched
if (acronymMatchData.Count == query.Length && acronymScore >= (int) UserSettingSearchPrecision) if (acronymsMatched > 0 && acronymsMatched == query.Length)
{ {
acronymMatchData = acronymMatchData.Select(x => translationMapping?.MapToOriginalIndex(x) ?? x).Distinct().ToList(); int acronymScore = acronymsMatched * 100 / acronymsTotalCount;
return new MatchResult(true, UserSettingSearchPrecision, acronymMatchData, acronymScore);
if (acronymScore >= (int)UserSettingSearchPrecision)
{
acronymMatchData = acronymMatchData.Select(x => translationMapping?.MapToOriginalIndex(x) ?? x).Distinct().ToList();
return new MatchResult(true, UserSettingSearchPrecision, acronymMatchData, acronymScore);
}
} }
// proceed to calculate score if every char or substring without whitespaces matched // proceed to calculate score if every char or substring without whitespaces matched
@ -225,20 +215,49 @@ namespace Flow.Launcher.Infrastructure
return new MatchResult(false, UserSettingSearchPrecision); return new MatchResult(false, UserSettingSearchPrecision);
} }
private bool IsAcronym(string stringToCompare, int compareStringIndex)
{
if (IsAcronymChar(stringToCompare, compareStringIndex) || IsAcronymNumber(stringToCompare, compareStringIndex))
return true;
return false;
}
// When counting acronyms, treat a set of numbers as one acronym ie. Visual 2019 as 2 acronyms instead of 5
private bool IsAcronymCount(string stringToCompare, int compareStringIndex)
{
if (IsAcronymChar(stringToCompare, compareStringIndex))
return true;
if (IsAcronymNumber(stringToCompare, compareStringIndex))
return compareStringIndex == 0 || char.IsWhiteSpace(stringToCompare[compareStringIndex - 1]);
return false;
}
private bool IsAcronymChar(string stringToCompare, int compareStringIndex)
=> char.IsUpper(stringToCompare[compareStringIndex]) ||
compareStringIndex == 0 || // 0 index means char is the start of the compare string, which is an acronym
char.IsWhiteSpace(stringToCompare[compareStringIndex - 1]);
private bool IsAcronymNumber(string stringToCompare, int compareStringIndex) => stringToCompare[compareStringIndex] >= 0 && stringToCompare[compareStringIndex] <= 9;
// To get the index of the closest space which preceeds the first matching index // To get the index of the closest space which preceeds the first matching index
private int CalculateClosestSpaceIndex(List<int> spaceIndices, int firstMatchIndex) private int CalculateClosestSpaceIndex(List<int> spaceIndices, int firstMatchIndex)
{ {
if (spaceIndices.Count == 0) var closestSpaceIndex = -1;
// spaceIndices should be ordered asc
foreach (var index in spaceIndices)
{ {
return -1; if (index < firstMatchIndex)
} closestSpaceIndex = index;
else else
{ break;
int? ind = spaceIndices.OrderBy(item => (firstMatchIndex - item))
.FirstOrDefault(item => firstMatchIndex > item);
int closestSpaceIndex = ind ?? -1;
return closestSpaceIndex;
} }
return closestSpaceIndex;
} }
private static bool AllPreviousCharsMatched(int startIndexToVerify, int currentQuerySubstringCharacterIndex, private static bool AllPreviousCharsMatched(int startIndexToVerify, int currentQuerySubstringCharacterIndex,

View file

@ -131,16 +131,17 @@ namespace Flow.Launcher.Test
[TestCase(Chrome, Chrome, 157)] [TestCase(Chrome, Chrome, 157)]
[TestCase(Chrome, LastIsChrome, 147)] [TestCase(Chrome, LastIsChrome, 147)]
[TestCase(Chrome, HelpCureHopeRaiseOnMindEntityChrome, 90)] [TestCase("chro", HelpCureHopeRaiseOnMindEntityChrome, 50)]
[TestCase("chr", HelpCureHopeRaiseOnMindEntityChrome, 30)]
[TestCase(Chrome, UninstallOrChangeProgramsOnYourComputer, 21)] [TestCase(Chrome, UninstallOrChangeProgramsOnYourComputer, 21)]
[TestCase(Chrome, CandyCrushSagaFromKing, 0)] [TestCase(Chrome, CandyCrushSagaFromKing, 0)]
[TestCase("sql", MicrosoftSqlServerManagementStudio, 90)] [TestCase("sql", MicrosoftSqlServerManagementStudio, 110)]
[TestCase("sql manag", MicrosoftSqlServerManagementStudio, 121)] //double spacing intended [TestCase("sql manag", MicrosoftSqlServerManagementStudio, 121)] //double spacing intended
public void WhenGivenQueryString_ThenShouldReturn_TheDesiredScoring( public void WhenGivenQueryString_ThenShouldReturn_TheDesiredScoring(
string queryString, string compareString, int expectedScore) string queryString, string compareString, int expectedScore)
{ {
// When, Given // When, Given
var matcher = new StringMatcher(); var matcher = new StringMatcher {UserSettingSearchPrecision = SearchPrecisionScore.Regular};
var rawScore = matcher.FuzzyMatch(queryString, compareString).RawScore; var rawScore = matcher.FuzzyMatch(queryString, compareString).RawScore;
// Should // Should
@ -151,13 +152,22 @@ namespace Flow.Launcher.Test
[TestCase("goo", "Google Chrome", SearchPrecisionScore.Regular, true)] [TestCase("goo", "Google Chrome", SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Google Chrome", SearchPrecisionScore.Low, true)] [TestCase("chr", "Google Chrome", SearchPrecisionScore.Low, true)]
[TestCase("chr", "Chrome", SearchPrecisionScore.Regular, true)] [TestCase("chr", "Chrome", SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Help cure hope raise on mind entity Chrome", SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Help cure hope raise on mind entity Chrome", SearchPrecisionScore.Low, true)] [TestCase("chr", "Help cure hope raise on mind entity Chrome", SearchPrecisionScore.Low, true)]
[TestCase("chr", "Candy Crush Saga from King", SearchPrecisionScore.Regular, false)] [TestCase("chr", "Candy Crush Saga from King", SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Candy Crush Saga from King", SearchPrecisionScore.None, true)] [TestCase("chr", "Candy Crush Saga from King", SearchPrecisionScore.None, true)]
[TestCase("ccs", "Candy Crush Saga from King", SearchPrecisionScore.Regular, true)] [TestCase("ccs", "Candy Crush Saga from King", SearchPrecisionScore.Low, true)]
[TestCase("cand", "Candy Crush Saga from King", SearchPrecisionScore.Regular, true)] [TestCase("cand", "Candy Crush Saga from King", SearchPrecisionScore.Regular, true)]
[TestCase("cand", "Help cure hope raise on mind entity Chrome", SearchPrecisionScore.Regular, [TestCase("cand", "Help cure hope raise on mind entity Chrome", SearchPrecisionScore.Regular, false)]
false)] [TestCase("vsc", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("vs", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("vc", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("vts", VisualStudioCode, SearchPrecisionScore.Regular, false)]
[TestCase("vcs", VisualStudioCode, SearchPrecisionScore.Regular, false)]
[TestCase("wt", "Windows Terminal From Microsoft Store", SearchPrecisionScore.Regular, false)]
[TestCase("vsp", "Visual Studio 2019 Preview", SearchPrecisionScore.Regular, true)]
[TestCase("vsp", "2019 Visual Studio Preview", SearchPrecisionScore.Regular, true)]
[TestCase("2019p", "Visual Studio 2019 Preview", SearchPrecisionScore.Regular, true)]
public void WhenGivenDesiredPrecision_ThenShouldReturn_AllResultsGreaterOrEqual( public void WhenGivenDesiredPrecision_ThenShouldReturn_AllResultsGreaterOrEqual(
string queryString, string queryString,
string compareString, string compareString,
@ -180,18 +190,16 @@ namespace Flow.Launcher.Test
// Should // Should
Assert.AreEqual(expectedPrecisionResult, matchResult.IsSearchPrecisionScoreMet(), Assert.AreEqual(expectedPrecisionResult, matchResult.IsSearchPrecisionScoreMet(),
$"Query:{queryString}{Environment.NewLine} " + $"Query: {queryString}{Environment.NewLine} " +
$"Compare:{compareString}{Environment.NewLine}" + $"Compare: {compareString}{Environment.NewLine}" +
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" + $"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
$"Precision Score: {(int)expectedPrecisionScore}"); $"Precision Score: {(int)expectedPrecisionScore}");
} }
[TestCase("exce", "OverLeaf-Latex: An online LaTeX editor", SearchPrecisionScore.Regular, false)] [TestCase("exce", "OverLeaf-Latex: An online LaTeX editor", SearchPrecisionScore.Regular, false)]
[TestCase("term", "Windows Terminal (Preview)", SearchPrecisionScore.Regular, true)] [TestCase("term", "Windows Terminal (Preview)", SearchPrecisionScore.Regular, true)]
[TestCase("sql s managa", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, [TestCase("sql s managa", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, false)]
false)] [TestCase("sql' s manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, false)]
[TestCase("sql' s manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular,
false)]
[TestCase("sql s manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)] [TestCase("sql s manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("sql manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)] [TestCase("sql manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("sql", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)] [TestCase("sql", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
@ -204,18 +212,13 @@ namespace Flow.Launcher.Test
[TestCase("mssms", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)] [TestCase("mssms", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("msms", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)] [TestCase("msms", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Shutdown", SearchPrecisionScore.Regular, false)] [TestCase("chr", "Shutdown", SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", [TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", SearchPrecisionScore.Regular, false)]
SearchPrecisionScore.Regular, false)] [TestCase("ch r", "Change settings for text-to-speech and for speech recognition (if installed).", SearchPrecisionScore.Regular, true)]
[TestCase("ch r", "Change settings for text-to-speech and for speech recognition (if installed).",
SearchPrecisionScore.Regular, true)]
[TestCase("a test", "This is a test", SearchPrecisionScore.Regular, true)] [TestCase("a test", "This is a test", SearchPrecisionScore.Regular, true)]
[TestCase("test", "This is a test", SearchPrecisionScore.Regular, true)] [TestCase("test", "This is a test", SearchPrecisionScore.Regular, true)]
[TestCase("cod", VisualStudioCode, SearchPrecisionScore.Regular, true)] [TestCase("cod", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("code", VisualStudioCode, SearchPrecisionScore.Regular, true)] [TestCase("code", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("codes", "Visual Studio Codes", SearchPrecisionScore.Regular, true)] [TestCase("codes", "Visual Studio Codes", SearchPrecisionScore.Regular, true)]
[TestCase("vsc", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("vs", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("vc", VisualStudioCode, SearchPrecisionScore.Regular, true)]
public void WhenGivenQuery_ShouldReturnResults_ContainingAllQuerySubstrings( public void WhenGivenQuery_ShouldReturnResults_ContainingAllQuerySubstrings(
string queryString, string queryString,
string compareString, string compareString,
@ -301,14 +304,18 @@ namespace Flow.Launcher.Test
$"Name of second: \"{secondName}\", Final Score: {secondScore}{Environment.NewLine}"); $"Name of second: \"{secondName}\", Final Score: {secondScore}{Environment.NewLine}");
} }
[TestCase("vsc","Visual Studio Code", 100)] [TestCase("vsc", "Visual Studio Code", 100)]
[TestCase("jbr","JetBrain Rider",100)] [TestCase("jbr", "JetBrain Rider", 100)]
[TestCase("jr","JetBrain Rider",90)] [TestCase("jr", "JetBrain Rider", 66)]
[TestCase("vs","Visual Studio",100)] [TestCase("vs", "Visual Studio", 100)]
[TestCase("vs","Visual Studio Preview",100)] [TestCase("vs", "Visual Studio Preview", 66)]
[TestCase("vsp","Visual Studio Preview",100)] [TestCase("vsp", "Visual Studio Preview", 100)]
[TestCase("vsp","Visual Studio",0)] [TestCase("pc", "postman canary", 100)]
[TestCase("pc","Postman Canary",100)] [TestCase("psc", "Postman super canary", 100)]
[TestCase("psc", "Postman super Canary", 100)]
[TestCase("vsp", "Visual Studio", 0)]
[TestCase("vps", "Visual Studio", 0)]
[TestCase(Chrome, HelpCureHopeRaiseOnMindEntityChrome, 75)]
public void WhenGivenAnAcronymQuery_ShouldReturnAcronymScore(string queryString, string compareString, public void WhenGivenAnAcronymQuery_ShouldReturnAcronymScore(string queryString, string compareString,
int desiredScore) int desiredScore)
{ {

View file

@ -18,6 +18,7 @@ using Flow.Launcher.Infrastructure;
using Flow.Launcher.Plugin.Program.Logger; using Flow.Launcher.Plugin.Program.Logger;
using IStream = AppxPackaing.IStream; using IStream = AppxPackaing.IStream;
using Rect = System.Windows.Rect; using Rect = System.Windows.Rect;
using Flow.Launcher.Plugin.SharedModels;
namespace Flow.Launcher.Plugin.Program.Programs namespace Flow.Launcher.Plugin.Program.Programs
{ {
@ -206,12 +207,11 @@ namespace Flow.Launcher.Plugin.Program.Programs
} }
catch (Exception e) catch (Exception e)
{ {
ProgramLogger.LogException("UWP" ,"CurrentUserPackages", $"id","An unexpected error occured and " ProgramLogger.LogException("UWP", "CurrentUserPackages", $"id", "An unexpected error occured and "
+ $"unable to verify if package is valid", e); + $"unable to verify if package is valid", e);
return false; return false;
} }
return valid; return valid;
}); });
return ps; return ps;
@ -263,24 +263,42 @@ namespace Flow.Launcher.Plugin.Program.Programs
public string LogoPath { get; set; } public string LogoPath { get; set; }
public UWP Package { get; set; } public UWP Package { get; set; }
public Application(){} public Application() { }
public Result Result(string query, IPublicAPI api) public Result Result(string query, IPublicAPI api)
{ {
var title = (Name, Description) switch string title;
MatchResult matchResult;
// We suppose Name won't be null
if (Description == null || Name.StartsWith(Description))
{ {
(var n, null) => n, title = Name;
(var n, var d) when d.StartsWith(n) => d, matchResult = StringMatcher.FuzzySearch(query, title);
(var n, var d) when n.StartsWith(d) => n, }
(var n, var d) when !string.IsNullOrEmpty(d) => $"{n}: {d}", else if (Description.StartsWith(Name))
_ => Name {
}; title = Description;
matchResult = StringMatcher.FuzzySearch(query, Description);
}
else
{
title = $"{Name}: {Description}";
var nameMatch = StringMatcher.FuzzySearch(query, Name);
var desciptionMatch = StringMatcher.FuzzySearch(query, Description);
if (desciptionMatch.Score > nameMatch.Score)
{
for (int i = 0; i < desciptionMatch.MatchData.Count; i++)
{
desciptionMatch.MatchData[i] += Name.Length + 2; // 2 is ": "
}
matchResult = desciptionMatch;
}
else matchResult = nameMatch;
}
var matchResult = StringMatcher.FuzzySearch(query, title); if (!matchResult.Success) return null;
if (!matchResult.Success)
return null;
var result = new Result var result = new Result
{ {

View file

@ -12,6 +12,7 @@ using Shell;
using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure;
using Flow.Launcher.Plugin.Program.Logger; using Flow.Launcher.Plugin.Program.Logger;
using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.Plugin.SharedModels;
namespace Flow.Launcher.Plugin.Program.Programs namespace Flow.Launcher.Plugin.Program.Programs
{ {
@ -36,19 +37,38 @@ namespace Flow.Launcher.Plugin.Program.Programs
public Result Result(string query, IPublicAPI api) public Result Result(string query, IPublicAPI api)
{ {
var title = (Name, Description) switch string title;
MatchResult matchResult;
// We suppose Name won't be null
if (Description == null || Name.StartsWith(Description))
{ {
(var n, null) => n, title = Name;
(var n, var d) when d.StartsWith(n) => d, matchResult = StringMatcher.FuzzySearch(query, title);
(var n, var d) when n.StartsWith(d) => n, }
(var n, var d) when !string.IsNullOrEmpty(d) => $"{n}: {d}", else if (Description.StartsWith(Name))
_ => Name {
}; title = Description;
matchResult = StringMatcher.FuzzySearch(query, Description);
}
else
{
title = $"{Name}: {Description}";
var nameMatch = StringMatcher.FuzzySearch(query, Name);
var desciptionMatch = StringMatcher.FuzzySearch(query, Description);
if (desciptionMatch.Score > nameMatch.Score)
{
for (int i = 0; i < desciptionMatch.MatchData.Count; i++)
{
desciptionMatch.MatchData[i] += Name.Length + 2; // 2 is ": "
}
matchResult = desciptionMatch;
}
else matchResult = nameMatch;
}
var matchResult = StringMatcher.FuzzySearch(query, title); if (!matchResult.Success) return null;
if (!matchResult.Success)
return null;
var result = new Result var result = new Result
{ {
@ -58,7 +78,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
Score = matchResult.Score, Score = matchResult.Score,
TitleHighlightData = matchResult.MatchData, TitleHighlightData = matchResult.MatchData,
ContextData = this, ContextData = this,
Action = e => Action = _ =>
{ {
var info = new ProcessStartInfo var info = new ProcessStartInfo
{ {
@ -268,10 +288,10 @@ namespace Flow.Launcher.Plugin.Program.Programs
try try
{ {
var paths = Directory.EnumerateFiles(directory, "*", new EnumerationOptions var paths = Directory.EnumerateFiles(directory, "*", new EnumerationOptions
{ {
IgnoreInaccessible = true, IgnoreInaccessible = true,
RecurseSubdirectories = true RecurseSubdirectories = true
}) })
.Where(x => suffixes.Contains(Extension(x))); .Where(x => suffixes.Contains(Extension(x)));
return paths; return paths;