Skip to content
71 changes: 1 addition & 70 deletions Flow.Launcher.Infrastructure/StringMatcher.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using Flow.Launcher.Plugin.SharedModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using static Flow.Launcher.Infrastructure.StringMatcher;

namespace Flow.Launcher.Infrastructure
{
Expand Down Expand Up @@ -239,74 +238,6 @@ private static int CalculateSearchScore(string query, string stringToCompare, in

return score;
}

public enum SearchPrecisionScore
{
Regular = 50,
Low = 20,
None = 0
}
}

public class MatchResult
{
public MatchResult(bool success, SearchPrecisionScore searchPrecision)
{
Success = success;
SearchPrecision = searchPrecision;
}

public MatchResult(bool success, SearchPrecisionScore searchPrecision, List<int> matchData, int rawScore)
{
Success = success;
SearchPrecision = searchPrecision;
MatchData = matchData;
RawScore = rawScore;
}

public bool Success { get; set; }

/// <summary>
/// The final score of the match result with search precision filters applied.
/// </summary>
public int Score { get; private set; }

/// <summary>
/// The raw calculated search score without any search precision filtering applied.
/// </summary>
private int _rawScore;

public int RawScore
{
get { return _rawScore; }
set
{
_rawScore = value;
Score = ScoreAfterSearchPrecisionFilter(_rawScore);
}
}

/// <summary>
/// Matched data to highlight.
/// </summary>
public List<int> MatchData { get; set; }

public SearchPrecisionScore SearchPrecision { get; set; }

public bool IsSearchPrecisionScoreMet()
{
return IsSearchPrecisionScoreMet(_rawScore);
}

private bool IsSearchPrecisionScoreMet(int rawScore)
{
return rawScore >= (int)SearchPrecision;
}

private int ScoreAfterSearchPrecisionFilter(int rawScore)
{
return IsSearchPrecisionScoreMet(rawScore) ? rawScore : 0;
}
}

public class MatchOption
Expand Down
11 changes: 6 additions & 5 deletions Flow.Launcher.Infrastructure/UserSettings/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Drawing;
using System.Text.Json.Serialization;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedModels;

namespace Flow.Launcher.Infrastructure.UserSettings
{
Expand Down Expand Up @@ -38,7 +39,7 @@ public string Language
/// </summary>
public bool ShouldUsePinyin { get; set; } = false;

internal StringMatcher.SearchPrecisionScore QuerySearchPrecision { get; private set; } = StringMatcher.SearchPrecisionScore.Regular;
internal SearchPrecisionScore QuerySearchPrecision { get; private set; } = SearchPrecisionScore.Regular;

[JsonIgnore]
public string QuerySearchPrecisionString
Expand All @@ -48,8 +49,8 @@ public string QuerySearchPrecisionString
{
try
{
var precisionScore = (StringMatcher.SearchPrecisionScore)Enum
.Parse(typeof(StringMatcher.SearchPrecisionScore), value);
var precisionScore = (SearchPrecisionScore)Enum
.Parse(typeof(SearchPrecisionScore), value);

QuerySearchPrecision = precisionScore;
StringMatcher.Instance.UserSettingSearchPrecision = precisionScore;
Expand All @@ -58,8 +59,8 @@ public string QuerySearchPrecisionString
{
Logger.Log.Exception(nameof(Settings), "Failed to load QuerySearchPrecisionString value from Settings file", e);

QuerySearchPrecision = StringMatcher.SearchPrecisionScore.Regular;
StringMatcher.Instance.UserSettingSearchPrecision = StringMatcher.SearchPrecisionScore.Regular;
QuerySearchPrecision = SearchPrecisionScore.Regular;
StringMatcher.Instance.UserSettingSearchPrecision = SearchPrecisionScore.Regular;

throw;
}
Expand Down
2 changes: 1 addition & 1 deletion Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
Expand Down
19 changes: 18 additions & 1 deletion Flow.Launcher.Plugin/IPublicAPI.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
using System;
using Flow.Launcher.Plugin.SharedModels;
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Flow.Launcher.Plugin
Expand Down Expand Up @@ -83,5 +87,18 @@ public interface IPublicAPI
/// if you want to hook something like Ctrl+R, you should use this event
/// </summary>
event FlowLauncherGlobalKeyboardEventHandler GlobalKeyboardEvent;

MatchResult FuzzySearch(string query, string stringToCompare);

Task<string> HttpGetStringAsync(string url, CancellationToken token = default);

Task<Stream> HttpGetStreamAsync(string url, CancellationToken token = default);

Task HttpDownloadAsync([NotNull] string url, [NotNull] string filePath);

void AddActionKeyword(string pluginId, string newActionKeyword);

void RemoveActionKeyword(string pluginId, string oldActionKeyword);

}
}
72 changes: 72 additions & 0 deletions Flow.Launcher.Plugin/SharedModels/MatchResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System.Collections.Generic;

namespace Flow.Launcher.Plugin.SharedModels
{
public class MatchResult
{
public MatchResult(bool success, SearchPrecisionScore searchPrecision)
{
Success = success;
SearchPrecision = searchPrecision;
}

public MatchResult(bool success, SearchPrecisionScore searchPrecision, List<int> matchData, int rawScore)
{
Success = success;
SearchPrecision = searchPrecision;
MatchData = matchData;
RawScore = rawScore;
}

public bool Success { get; set; }

/// <summary>
/// The final score of the match result with search precision filters applied.
/// </summary>
public int Score { get; private set; }

/// <summary>
/// The raw calculated search score without any search precision filtering applied.
/// </summary>
private int _rawScore;

public int RawScore
{
get { return _rawScore; }
set
{
_rawScore = value;
Score = ScoreAfterSearchPrecisionFilter(_rawScore);
}
}

/// <summary>
/// Matched data to highlight.
/// </summary>
public List<int> MatchData { get; set; }

public SearchPrecisionScore SearchPrecision { get; set; }

public bool IsSearchPrecisionScoreMet()
{
return IsSearchPrecisionScoreMet(_rawScore);
}

private bool IsSearchPrecisionScoreMet(int rawScore)
{
return rawScore >= (int)SearchPrecision;
}

private int ScoreAfterSearchPrecisionFilter(int rawScore)
{
return IsSearchPrecisionScoreMet(rawScore) ? rawScore : 0;
}
}

public enum SearchPrecisionScore
{
Regular = 50,
Low = 20,
None = 0
}
}
75 changes: 38 additions & 37 deletions Flow.Launcher.Test/FuzzyMatcherTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using NUnit.Framework;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedModels;

namespace Flow.Launcher.Test
{
Expand Down Expand Up @@ -37,8 +38,8 @@ public List<int> GetPrecisionScores()
{
var listToReturn = new List<int>();

Enum.GetValues(typeof(StringMatcher.SearchPrecisionScore))
.Cast<StringMatcher.SearchPrecisionScore>()
Enum.GetValues(typeof(SearchPrecisionScore))
.Cast<SearchPrecisionScore>()
.ToList()
.ForEach(x => listToReturn.Add((int)x));

Expand Down Expand Up @@ -145,20 +146,20 @@ public void WhenGivenQueryString_ThenShouldReturn_TheDesiredScoring(
$"Expected score for compare string '{compareString}': {expectedScore}, Actual: {rawScore}");
}

[TestCase("goo", "Google Chrome", StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Google Chrome", StringMatcher.SearchPrecisionScore.Low, true)]
[TestCase("chr", "Chrome", StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Help cure hope raise on mind entity Chrome", StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Help cure hope raise on mind entity Chrome", StringMatcher.SearchPrecisionScore.Low, true)]
[TestCase("chr", "Candy Crush Saga from King", StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Candy Crush Saga from King", StringMatcher.SearchPrecisionScore.None, true)]
[TestCase("ccs", "Candy Crush Saga from King", StringMatcher.SearchPrecisionScore.Low, true)]
[TestCase("cand", "Candy Crush Saga from King",StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("cand", "Help cure hope raise on mind entity Chrome", StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("goo", "Google Chrome", SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Google Chrome", SearchPrecisionScore.Low, 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", "Candy Crush Saga from King", SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Candy Crush Saga from King", SearchPrecisionScore.None, true)]
[TestCase("ccs", "Candy Crush Saga from King", SearchPrecisionScore.Low, true)]
[TestCase("cand", "Candy Crush Saga from King",SearchPrecisionScore.Regular, true)]
[TestCase("cand", "Help cure hope raise on mind entity Chrome", SearchPrecisionScore.Regular, false)]
public void WhenGivenDesiredPrecision_ThenShouldReturn_AllResultsGreaterOrEqual(
string queryString,
string compareString,
StringMatcher.SearchPrecisionScore expectedPrecisionScore,
SearchPrecisionScore expectedPrecisionScore,
bool expectedPrecisionResult)
{
// When
Expand All @@ -182,32 +183,32 @@ public void WhenGivenDesiredPrecision_ThenShouldReturn_AllResultsGreaterOrEqual(
$"Precision Score: {(int)expectedPrecisionScore}");
}

[TestCase("exce", "OverLeaf-Latex: An online LaTeX editor", StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("term", "Windows Terminal (Preview)", StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql s managa", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("sql' s manag", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("sql s manag", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql manag", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql serv", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("servez", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("sql servz", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("sql serv man", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql studio", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("mic", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Shutdown", StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("mssms", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("ch r", "Change settings for text-to-speech and for speech recognition (if installed).", StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("a test", "This is a test", StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("test", "This is a test", StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("cod", VisualStudioCode, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("code", VisualStudioCode, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("codes", "Visual Studio Codes", StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("exce", "OverLeaf-Latex: An online LaTeX editor", SearchPrecisionScore.Regular, false)]
[TestCase("term", "Windows Terminal (Preview)", SearchPrecisionScore.Regular, true)]
[TestCase("sql s managa", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, false)]
[TestCase("sql' s manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, false)]
[TestCase("sql s manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("sql manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("sql", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("sql serv", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("servez", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, false)]
[TestCase("sql servz", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, false)]
[TestCase("sql serv man", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("sql studio", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("mic", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Shutdown", SearchPrecisionScore.Regular, false)]
[TestCase("mssms", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", SearchPrecisionScore.Regular, false)]
[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("test", "This is a test", SearchPrecisionScore.Regular, true)]
[TestCase("cod", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("code", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("codes", "Visual Studio Codes", SearchPrecisionScore.Regular, true)]
public void WhenGivenQuery_ShouldReturnResults_ContainingAllQuerySubstrings(
string queryString,
string compareString,
StringMatcher.SearchPrecisionScore expectedPrecisionScore,
SearchPrecisionScore expectedPrecisionScore,
bool expectedPrecisionResult)
{
// When
Expand Down Expand Up @@ -238,7 +239,7 @@ public void WhenGivenAQuery_Scoring_ShouldGiveMoreWeightToStartOfNewWord(
string queryString, string compareString1, string compareString2)
{
// When
var matcher = new StringMatcher { UserSettingSearchPrecision = StringMatcher.SearchPrecisionScore.Regular };
var matcher = new StringMatcher { UserSettingSearchPrecision = SearchPrecisionScore.Regular };

// Given
var compareString1Result = matcher.FuzzyMatch(queryString, compareString1);
Expand Down
Loading