mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-11 14:02:24 +02:00
fixes to string matcher alg and some logging stuff
This commit is contained in:
@@ -47,8 +47,53 @@ namespace Wox.Infrastructure.Logger
|
||||
return valid;
|
||||
}
|
||||
|
||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||
public static void Error(string message)
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public static void Exception(string className, string message, System.Exception exception, [CallerMemberName] string methodName = "")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(className))
|
||||
{
|
||||
LogFaultyFormat($"Fail to specify a class name during logging of message: {message ?? "no message entered"}");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
{ // todo: not sure we really need that
|
||||
LogFaultyFormat($"Fail to specify a message during logging");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(methodName))
|
||||
{
|
||||
className += "." + methodName;
|
||||
}
|
||||
|
||||
ExceptionInternal(className, message, exception);
|
||||
}
|
||||
|
||||
private static void ExceptionInternal(string classAndMethod, string message, System.Exception e)
|
||||
{
|
||||
var logger = LogManager.GetLogger(classAndMethod);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"ERROR|{message}");
|
||||
|
||||
logger.Error("-------------------------- Begin exception --------------------------");
|
||||
logger.Error(message);
|
||||
|
||||
do
|
||||
{
|
||||
logger.Error($"Exception full name:\n <{e.GetType().FullName}>");
|
||||
logger.Error($"Exception message:\n <{e.Message}>");
|
||||
logger.Error($"Exception stack trace:\n <{e.StackTrace}>");
|
||||
logger.Error($"Exception source:\n <{e.Source}>");
|
||||
logger.Error($"Exception target site:\n <{e.TargetSite}>");
|
||||
logger.Error($"Exception HResult:\n <{e.HResult}>");
|
||||
e = e.InnerException;
|
||||
} while (e != null);
|
||||
|
||||
logger.Error("-------------------------- End exception --------------------------");
|
||||
}
|
||||
|
||||
private static void LogInternal(string message, LogLevel level)
|
||||
{
|
||||
if (FormatValid(message))
|
||||
{
|
||||
@@ -57,8 +102,8 @@ namespace Wox.Infrastructure.Logger
|
||||
var unprefixed = parts[2];
|
||||
var logger = LogManager.GetLogger(prefix);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"ERROR|{message}");
|
||||
logger.Error(unprefixed);
|
||||
System.Diagnostics.Debug.WriteLine($"{level.Name}|{message}");
|
||||
logger.Log(level, unprefixed);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -78,25 +123,7 @@ namespace Wox.Infrastructure.Logger
|
||||
var parts = message.Split('|');
|
||||
var prefix = parts[1];
|
||||
var unprefixed = parts[2];
|
||||
var logger = LogManager.GetLogger(prefix);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"ERROR|{message}");
|
||||
|
||||
logger.Error("-------------------------- Begin exception --------------------------");
|
||||
logger.Error(unprefixed);
|
||||
|
||||
do
|
||||
{
|
||||
logger.Error($"Exception full name:\n <{e.GetType().FullName}>");
|
||||
logger.Error($"Exception message:\n <{e.Message}>");
|
||||
logger.Error($"Exception stack trace:\n <{e.StackTrace}>");
|
||||
logger.Error($"Exception source:\n <{e.Source}>");
|
||||
logger.Error($"Exception target site:\n <{e.TargetSite}>");
|
||||
logger.Error($"Exception HResult:\n <{e.HResult}>");
|
||||
e = e.InnerException;
|
||||
} while (e != null);
|
||||
|
||||
logger.Error("-------------------------- End exception --------------------------");
|
||||
ExceptionInternal(prefix, unprefixed, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -105,61 +132,28 @@ namespace Wox.Infrastructure.Logger
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||
public static void Error(string message)
|
||||
{
|
||||
LogInternal(message, LogLevel.Error);
|
||||
}
|
||||
|
||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||
public static void Debug(string message)
|
||||
{
|
||||
if (FormatValid(message))
|
||||
{
|
||||
var parts = message.Split('|');
|
||||
var prefix = parts[1];
|
||||
var unprefixed = parts[2];
|
||||
var logger = LogManager.GetLogger(prefix);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"DEBUG|{message}");
|
||||
logger.Debug(unprefixed);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFaultyFormat(message);
|
||||
}
|
||||
LogInternal(message, LogLevel.Debug);
|
||||
}
|
||||
|
||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||
public static void Info(string message)
|
||||
{
|
||||
if (FormatValid(message))
|
||||
{
|
||||
var parts = message.Split('|');
|
||||
var prefix = parts[1];
|
||||
var unprefixed = parts[2];
|
||||
var logger = LogManager.GetLogger(prefix);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"INFO|{message}");
|
||||
logger.Info(unprefixed);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFaultyFormat(message);
|
||||
}
|
||||
LogInternal(message, LogLevel.Info);
|
||||
}
|
||||
|
||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||
public static void Warn(string message)
|
||||
{
|
||||
if (FormatValid(message))
|
||||
{
|
||||
var parts = message.Split('|');
|
||||
var prefix = parts[1];
|
||||
var unprefixed = parts[2];
|
||||
var logger = LogManager.GetLogger(prefix);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"WARN|{message}");
|
||||
logger.Warn(unprefixed);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFaultyFormat(message);
|
||||
}
|
||||
LogInternal(message, LogLevel.Warn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,8 @@ namespace Wox.Infrastructure
|
||||
{
|
||||
public static MatchOption DefaultMatchOption = new MatchOption();
|
||||
|
||||
public static string UserSettingSearchPrecision { get; set; }
|
||||
public static int UserSettingSearchPrecision { get; set; }
|
||||
|
||||
public static bool ShouldUsePinyin { get; set; }
|
||||
|
||||
[Obsolete("This method is obsolete and should not be used. Please use the static function StringMatcher.FuzzySearch")]
|
||||
@@ -48,48 +49,103 @@ namespace Wox.Infrastructure
|
||||
|
||||
query = query.Trim();
|
||||
|
||||
var len = stringToCompare.Length;
|
||||
var compareString = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
|
||||
var pattern = opt.IgnoreCase ? query.ToLower() : query;
|
||||
var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
|
||||
|
||||
var sb = new StringBuilder(stringToCompare.Length + (query.Length * (opt.Prefix.Length + opt.Suffix.Length)));
|
||||
var patternIdx = 0;
|
||||
var queryWithoutCase = opt.IgnoreCase ? query.ToLower() : query;
|
||||
|
||||
int currentQueryToCompareIndex = 0;
|
||||
var queryToCompareSeparated = queryWithoutCase.Split(' ');
|
||||
var currentQueryToCompare = queryToCompareSeparated[currentQueryToCompareIndex];
|
||||
|
||||
var patternIndex = 0;
|
||||
var firstMatchIndex = -1;
|
||||
var firstMatchIndexInWord = -1;
|
||||
var lastMatchIndex = 0;
|
||||
char ch;
|
||||
bool allMatched = false;
|
||||
bool isFullWordMatched = false;
|
||||
bool allWordsFullyMatched = true;
|
||||
|
||||
var indexList = new List<int>();
|
||||
|
||||
for (var idx = 0; idx < len; idx++)
|
||||
for (var index = 0; index < fullStringToCompareWithoutCase.Length; index++)
|
||||
{
|
||||
ch = stringToCompare[idx];
|
||||
if (compareString[idx] == pattern[patternIdx])
|
||||
var ch = stringToCompare[index];
|
||||
if (fullStringToCompareWithoutCase[index] == currentQueryToCompare[patternIndex])
|
||||
{
|
||||
if (firstMatchIndex < 0)
|
||||
firstMatchIndex = idx;
|
||||
lastMatchIndex = idx + 1;
|
||||
{ // first matched char will become the start of the compared string
|
||||
firstMatchIndex = index;
|
||||
}
|
||||
|
||||
indexList.Add(idx);
|
||||
sb.Append(opt.Prefix + ch + opt.Suffix);
|
||||
patternIdx += 1;
|
||||
if (patternIndex == 0)
|
||||
{ // first letter of current word
|
||||
isFullWordMatched = true;
|
||||
firstMatchIndexInWord = index;
|
||||
}
|
||||
else if (!isFullWordMatched)
|
||||
{ // we want to verify that there is not a better match if this is not a full word
|
||||
// in order to do so we need to verify all previous chars are part of the pattern
|
||||
int startIndexToVerify = index - patternIndex;
|
||||
bool allMatch = true;
|
||||
for (int indexToCheck = 0; indexToCheck < patternIndex; indexToCheck++)
|
||||
{
|
||||
if (fullStringToCompareWithoutCase[startIndexToVerify + indexToCheck] !=
|
||||
currentQueryToCompare[indexToCheck])
|
||||
{
|
||||
allMatch = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (allMatch)
|
||||
{ // update to this as a full word
|
||||
isFullWordMatched = true;
|
||||
if (currentQueryToCompareIndex == 0)
|
||||
{ // first word so we need to update start index
|
||||
firstMatchIndex = startIndexToVerify;
|
||||
}
|
||||
|
||||
indexList.RemoveAll(x => x >= firstMatchIndexInWord);
|
||||
for (int indexToCheck = 0; indexToCheck < patternIndex; indexToCheck++)
|
||||
{ // update the index list
|
||||
indexList.Add(startIndexToVerify + indexToCheck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastMatchIndex = index + 1;
|
||||
indexList.Add(index);
|
||||
|
||||
// increase the pattern matched index and check if everything was matched
|
||||
if (++patternIndex == currentQueryToCompare.Length)
|
||||
{
|
||||
if (++currentQueryToCompareIndex >= queryToCompareSeparated.Length)
|
||||
{ // moved over all the words
|
||||
allMatched = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise move to the next word
|
||||
currentQueryToCompare = queryToCompareSeparated[currentQueryToCompareIndex];
|
||||
patternIndex = 0;
|
||||
if (!isFullWordMatched)
|
||||
{ // if any of the words was not fully matched all are not fully matched
|
||||
allWordsFullyMatched = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(ch);
|
||||
}
|
||||
|
||||
// match success, append remain char
|
||||
if (patternIdx == pattern.Length && (idx + 1) != compareString.Length)
|
||||
{
|
||||
sb.Append(stringToCompare.Substring(idx + 1));
|
||||
break;
|
||||
isFullWordMatched = false;
|
||||
}
|
||||
}
|
||||
|
||||
// return rendered string if we have a match for every char
|
||||
if (patternIdx == pattern.Length)
|
||||
|
||||
// return rendered string if we have a match for every char or all substring without whitespaces matched
|
||||
if (allMatched)
|
||||
{
|
||||
var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex, lastMatchIndex - firstMatchIndex);
|
||||
// check if all query string was contained in string to compare
|
||||
bool containedFully = lastMatchIndex - firstMatchIndex == queryWithoutCase.Length;
|
||||
var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex, lastMatchIndex - firstMatchIndex, containedFully, allWordsFullyMatched);
|
||||
var pinyinScore = ScoreForPinyin(stringToCompare, query);
|
||||
|
||||
var result = new MatchResult
|
||||
@@ -105,7 +161,8 @@ namespace Wox.Infrastructure
|
||||
return new MatchResult { Success = false };
|
||||
}
|
||||
|
||||
private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen)
|
||||
private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen,
|
||||
bool isFullyContained, bool allWordsFullyMatched)
|
||||
{
|
||||
// A match found near the beginning of a string is scored more than a match found near the end
|
||||
// A match is scored more if the characters in the patterns are closer to each other,
|
||||
@@ -122,6 +179,16 @@ namespace Wox.Infrastructure
|
||||
score += 10;
|
||||
}
|
||||
|
||||
if (isFullyContained)
|
||||
{
|
||||
score += 20; // honestly I'm not sure what would be a good number here or should it factor the size of the pattern
|
||||
}
|
||||
|
||||
if (allWordsFullyMatched)
|
||||
{
|
||||
score += 20;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
@@ -178,6 +245,7 @@ namespace Wox.Infrastructure
|
||||
/// The raw calculated search score without any search precision filtering applied.
|
||||
/// </summary>
|
||||
private int _rawScore;
|
||||
|
||||
public int RawScore
|
||||
{
|
||||
get { return _rawScore; }
|
||||
@@ -200,10 +268,7 @@ namespace Wox.Infrastructure
|
||||
|
||||
private bool IsSearchPrecisionScoreMet(int score)
|
||||
{
|
||||
var precisionScore = (SearchPrecisionScore)Enum.Parse(
|
||||
typeof(SearchPrecisionScore),
|
||||
UserSettingSearchPrecision ?? SearchPrecisionScore.Regular.ToString());
|
||||
return score >= (int)precisionScore;
|
||||
return score >= UserSettingSearchPrecision;
|
||||
}
|
||||
|
||||
private int ApplySearchPrecisionFilter(int score)
|
||||
@@ -214,22 +279,18 @@ namespace Wox.Infrastructure
|
||||
|
||||
public class MatchOption
|
||||
{
|
||||
public MatchOption()
|
||||
{
|
||||
Prefix = "";
|
||||
Suffix = "";
|
||||
IgnoreCase = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// prefix of match char, use for hightlight
|
||||
/// </summary>
|
||||
public string Prefix { get; set; }
|
||||
[Obsolete("this is never used")]
|
||||
public string Prefix { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// suffix of match char, use for hightlight
|
||||
/// </summary>
|
||||
public string Suffix { get; set; }
|
||||
[Obsolete("this is never used")]
|
||||
public string Suffix { get; set; } = "";
|
||||
|
||||
public bool IgnoreCase { get; set; }
|
||||
public bool IgnoreCase { get; set; } = true;
|
||||
}
|
||||
}
|
||||
@@ -36,14 +36,27 @@ namespace Wox.Infrastructure.UserSettings
|
||||
}
|
||||
|
||||
|
||||
private string _querySearchPrecision { get; set; } = StringMatcher.SearchPrecisionScore.Regular.ToString();
|
||||
public string QuerySearchPrecision
|
||||
internal StringMatcher.SearchPrecisionScore QuerySearchPrecision { get; private set; } = StringMatcher.SearchPrecisionScore.Regular;
|
||||
|
||||
public string QuerySearchPrecisionString
|
||||
{
|
||||
get { return _querySearchPrecision; }
|
||||
get { return QuerySearchPrecision.ToString(); }
|
||||
set
|
||||
{
|
||||
_querySearchPrecision = value;
|
||||
StringMatcher.UserSettingSearchPrecision = value;
|
||||
try
|
||||
{
|
||||
var precisionScore = (StringMatcher.SearchPrecisionScore)Enum.Parse(
|
||||
typeof(StringMatcher.SearchPrecisionScore),
|
||||
value);
|
||||
QuerySearchPrecision = precisionScore;
|
||||
StringMatcher.UserSettingSearchPrecision = (int)precisionScore;
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
// what do we do here?!
|
||||
Logger.Log.Exception(nameof(Settings), "Fail to set QuerySearchPrecision", e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,17 +12,25 @@ namespace Wox.Test
|
||||
[TestFixture]
|
||||
public class FuzzyMatcherTest
|
||||
{
|
||||
private const string Chrome = "Chrome";
|
||||
private const string CandyCrushSagaFromKing = "Candy Crush Saga from King";
|
||||
private const string HelpCureHopeRaiseOnMindEntityChrome = "Help cure hope raise on mind entity Chrome";
|
||||
private const string UninstallOrChangeProgramsOnYourComputer = "Uninstall or change programs on your computer";
|
||||
private const string LastIsChrome = "Last is chrome";
|
||||
private const string OneOneOneOne = "1111";
|
||||
private const string MicrosoftSqlServerManagementStudio = "Microsoft SQL Server Management Studio";
|
||||
|
||||
public List<string> GetSearchStrings()
|
||||
=> new List<string>
|
||||
{
|
||||
"Chrome",
|
||||
Chrome,
|
||||
"Choose which programs you want Windows to use for activities like web browsing, editing photos, sending e-mail, and playing music.",
|
||||
"Help cure hope raise on mind entity Chrome ",
|
||||
"Candy Crush Saga from King",
|
||||
"Uninstall or change programs on your computer",
|
||||
HelpCureHopeRaiseOnMindEntityChrome,
|
||||
CandyCrushSagaFromKing,
|
||||
UninstallOrChangeProgramsOnYourComputer,
|
||||
"Add, change, and manage fonts on your computer",
|
||||
"Last is chrome",
|
||||
"1111"
|
||||
LastIsChrome,
|
||||
OneOneOneOne
|
||||
};
|
||||
|
||||
public List<int> GetPrecisionScores()
|
||||
@@ -114,20 +122,23 @@ namespace Wox.Test
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase("chrome")]
|
||||
public void WhenGivenStringsForCalScoreMethodThenShouldReturnCurrentScoring(string searchTerm)
|
||||
[TestCase]
|
||||
public void WhenGivenStringsForCalScoreMethodThenShouldReturnCurrentScoring()
|
||||
{
|
||||
// Arrange
|
||||
string searchTerm = "chrome"; // since this looks for specific results it will always be one case
|
||||
var searchStrings = new List<string>
|
||||
{
|
||||
"Chrome",//SCORE: 107
|
||||
"Last is chrome",//SCORE: 53
|
||||
"Help cure hope raise on mind entity Chrome",//SCORE: 21
|
||||
"Uninstall or change programs on your computer", //SCORE: 15
|
||||
"Candy Crush Saga from King"//SCORE: 0
|
||||
Chrome,//SCORE: 107
|
||||
LastIsChrome,//SCORE: 53
|
||||
HelpCureHopeRaiseOnMindEntityChrome,//SCORE: 21
|
||||
UninstallOrChangeProgramsOnYourComputer, //SCORE: 15
|
||||
CandyCrushSagaFromKing//SCORE: 0
|
||||
}
|
||||
.OrderByDescending(x => x)
|
||||
.ToList();
|
||||
|
||||
// Act
|
||||
var results = new List<Result>();
|
||||
foreach (var str in searchStrings)
|
||||
{
|
||||
@@ -138,23 +149,23 @@ namespace Wox.Test
|
||||
});
|
||||
}
|
||||
|
||||
var orderedResults = results.OrderByDescending(x => x.Title).ToList();
|
||||
// Assert
|
||||
VerifyResult(147, Chrome);
|
||||
VerifyResult(93, LastIsChrome);
|
||||
VerifyResult(41, HelpCureHopeRaiseOnMindEntityChrome);
|
||||
VerifyResult(35, UninstallOrChangeProgramsOnYourComputer);
|
||||
VerifyResult(0, CandyCrushSagaFromKing);
|
||||
|
||||
Debug.WriteLine("");
|
||||
Debug.WriteLine("###############################################");
|
||||
Debug.WriteLine("SEARCHTERM: " + searchTerm);
|
||||
foreach (var item in orderedResults)
|
||||
void VerifyResult(int expectedScore, string expectedTitle)
|
||||
{
|
||||
Debug.WriteLine("SCORE: " + item.Score.ToString() + ", FoundString: " + item.Title);
|
||||
}
|
||||
Debug.WriteLine("###############################################");
|
||||
Debug.WriteLine("");
|
||||
var result = results.FirstOrDefault(x => x.Title == expectedTitle);
|
||||
if (result == null)
|
||||
{
|
||||
Assert.Fail($"Fail to find result: {expectedTitle} in result list");
|
||||
}
|
||||
|
||||
Assert.IsTrue(orderedResults[0].Score == 15 && orderedResults[0].Title == searchStrings[0]);
|
||||
Assert.IsTrue(orderedResults[1].Score == 53 && orderedResults[1].Title == searchStrings[1]);
|
||||
Assert.IsTrue(orderedResults[2].Score == 21 && orderedResults[2].Title == searchStrings[2]);
|
||||
Assert.IsTrue(orderedResults[3].Score == 107 && orderedResults[3].Title == searchStrings[3]);
|
||||
Assert.IsTrue(orderedResults[4].Score == 0 && orderedResults[4].Title == searchStrings[4]);
|
||||
Assert.AreEqual(expectedScore, result.Score, $"Expected score for {expectedTitle}: {expectedScore}, Actual: {result.Score}");
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase("goo", "Google Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
@@ -173,19 +184,53 @@ namespace Wox.Test
|
||||
int expectedPrecisionScore,
|
||||
bool expectedPrecisionResult)
|
||||
{
|
||||
// Arrange
|
||||
var expectedPrecisionString = (StringMatcher.SearchPrecisionScore)expectedPrecisionScore;
|
||||
StringMatcher.UserSettingSearchPrecision = expectedPrecisionString.ToString();
|
||||
StringMatcher.UserSettingSearchPrecision = expectedPrecisionScore; // this is why static state is evil...
|
||||
|
||||
// Act
|
||||
var matchResult = StringMatcher.FuzzySearch(queryString, compareString);
|
||||
|
||||
Debug.WriteLine("");
|
||||
Debug.WriteLine("###############################################");
|
||||
Debug.WriteLine($"SearchTerm: {queryString} PrecisionLevelSetAt: {expectedPrecisionString} ({expectedPrecisionScore})");
|
||||
Debug.WriteLine($"SCORE: {matchResult.Score.ToString()}, ComparedString: {compareString}");
|
||||
Debug.WriteLine("###############################################");
|
||||
Debug.WriteLine("");
|
||||
// Assert
|
||||
Assert.AreEqual(expectedPrecisionResult, matchResult.IsSearchPrecisionScoreMet(),
|
||||
$"Query:{queryString}{Environment.NewLine} " +
|
||||
$"Compare:{compareString}{Environment.NewLine}" +
|
||||
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
|
||||
$"Precision Level: {expectedPrecisionString}={expectedPrecisionScore}");
|
||||
}
|
||||
|
||||
var matchPrecisionResult = matchResult.IsSearchPrecisionScoreMet();
|
||||
Assert.IsTrue(matchPrecisionResult == expectedPrecisionResult);
|
||||
[TestCase("exce", "OverLeaf-Latex: An online LaTeX editor", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("term", "Windows Terminal (Preview)", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("sql s managa", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("sql' s manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("sql s manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("sql manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("sql", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("sql serv", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("mic", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("chr", "Shutdown", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("a test", "This is a test", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("test", "This is a test", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
public void WhenGivenQueryShouldReturnResultsContainingAllQuerySubstrings(
|
||||
string queryString,
|
||||
string compareString,
|
||||
int expectedPrecisionScore,
|
||||
bool expectedPrecisionResult)
|
||||
{
|
||||
// Arrange
|
||||
var expectedPrecisionString = (StringMatcher.SearchPrecisionScore)expectedPrecisionScore;
|
||||
StringMatcher.UserSettingSearchPrecision = expectedPrecisionScore; // this is why static state is evil...
|
||||
|
||||
// Act
|
||||
var matchResult = StringMatcher.FuzzySearch(queryString, compareString);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(expectedPrecisionResult, matchResult.IsSearchPrecisionScoreMet(),
|
||||
$"Query:{queryString}{Environment.NewLine} " +
|
||||
$"Compare:{compareString}{Environment.NewLine}" +
|
||||
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
|
||||
$"Precision Level: {expectedPrecisionString}={expectedPrecisionScore}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ namespace Wox
|
||||
|
||||
Alphabet.Initialize(_settings);
|
||||
|
||||
StringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision;
|
||||
StringMatcher.UserSettingSearchPrecision = (int)_settings.QuerySearchPrecision;
|
||||
StringMatcher.ShouldUsePinyin = _settings.ShouldUsePinyin;
|
||||
|
||||
PluginManager.LoadPlugins(_settings.PluginSettings);
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<TextBlock Text="{DynamicResource querySearchPrecision}" />
|
||||
<ComboBox Margin="10 0 0 0" Width="120"
|
||||
ItemsSource="{Binding QuerySearchPrecisionStrings}"
|
||||
SelectedItem="{Binding Settings.QuerySearchPrecision}" />
|
||||
SelectedItem="{Binding Settings.QuerySearchPrecisionString}" />
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10" Orientation="Horizontal">
|
||||
<TextBlock Text="{DynamicResource lastQueryMode}" />
|
||||
|
||||
Reference in New Issue
Block a user