mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge pull request #4 from Flow-Launcher/acronym_scoring
Acronym Scoring Change
This commit is contained in:
commit
95325a8f0c
4 changed files with 173 additions and 109 deletions
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
@ -300,15 +303,19 @@ namespace Flow.Launcher.Test
|
||||||
$"Should be greater than{Environment.NewLine}" +
|
$"Should be greater than{Environment.NewLine}" +
|
||||||
$"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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
@ -311,7 +329,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
||||||
|
|
||||||
Action = _ =>
|
Action = _ =>
|
||||||
{
|
{
|
||||||
Main.StartProcess(Process.Start,
|
Main.StartProcess(Process.Start,
|
||||||
new ProcessStartInfo(
|
new ProcessStartInfo(
|
||||||
!string.IsNullOrEmpty(Main._settings.CustomizedExplorer)
|
!string.IsNullOrEmpty(Main._settings.CustomizedExplorer)
|
||||||
? Main._settings.CustomizedExplorer
|
? Main._settings.CustomizedExplorer
|
||||||
|
|
@ -403,14 +421,14 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
||||||
public string FormattedPriReferenceValue(string packageName, string rawPriReferenceValue)
|
public string FormattedPriReferenceValue(string packageName, string rawPriReferenceValue)
|
||||||
{
|
{
|
||||||
const string prefix = "ms-resource:";
|
const string prefix = "ms-resource:";
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(rawPriReferenceValue) || !rawPriReferenceValue.StartsWith(prefix))
|
if (string.IsNullOrWhiteSpace(rawPriReferenceValue) || !rawPriReferenceValue.StartsWith(prefix))
|
||||||
return rawPriReferenceValue;
|
return rawPriReferenceValue;
|
||||||
|
|
||||||
string key = rawPriReferenceValue.Substring(prefix.Length);
|
string key = rawPriReferenceValue.Substring(prefix.Length);
|
||||||
if (key.StartsWith("//"))
|
if (key.StartsWith("//"))
|
||||||
return $"{prefix}{key}";
|
return $"{prefix}{key}";
|
||||||
|
|
||||||
if (!key.StartsWith("/"))
|
if (!key.StartsWith("/"))
|
||||||
{
|
{
|
||||||
key = $"/{key}";
|
key = $"/{key}";
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue