diff --git a/Wox.Infrastructure/FuzzyMatcher.cs b/Wox.Infrastructure/FuzzyMatcher.cs
new file mode 100644
index 0000000000..693bd9592a
--- /dev/null
+++ b/Wox.Infrastructure/FuzzyMatcher.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Wox.Infrastructure
+{
+ //From:http://crossplatform.net/sublime-text-ctrl-p-fuzzy-matching-in-python/
+ public class FuzzyMatcher
+ {
+ private Regex reg = null;
+ private string rawQuery = "";
+
+ private FuzzyMatcher(string query)
+ {
+ this.rawQuery = query;
+ this.reg = GetPattern(query);
+ }
+
+ private Regex GetPattern(string query)
+ {
+ var pattern = string.Join(".*?", query.ToCharArray().Select(x => Regex.Escape(x.ToString())).ToArray());
+ return new Regex(pattern, RegexOptions.IgnoreCase);
+ }
+
+ public int Score(string str)
+ {
+ var match = reg.Match(str);
+ if (!match.Success)
+ return 0;
+
+ //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, while the score is lower if they are more spread out
+ var score = 100 * (this.rawQuery.Length + 1) / ((1 + match.Index) + (match.Length + 1));
+ //a match with less characters assigning more weights
+ if (str.Length - this.rawQuery.Length < 5)
+ score = score + 20;
+ else if (str.Length - this.rawQuery.Length < 10)
+ score = score + 10;
+
+ return score;
+ }
+
+ public static FuzzyMatcher Create(string query)
+ {
+ return new FuzzyMatcher(query);
+ }
+ }
+}
diff --git a/Wox.Infrastructure/Wox.Infrastructure.csproj b/Wox.Infrastructure/Wox.Infrastructure.csproj
index f538f42196..4aa8966552 100644
--- a/Wox.Infrastructure/Wox.Infrastructure.csproj
+++ b/Wox.Infrastructure/Wox.Infrastructure.csproj
@@ -49,6 +49,7 @@
+
diff --git a/Wox.Plugin.System/Programs.cs b/Wox.Plugin.System/Programs.cs
index 37fd46b462..4c4d71854c 100644
--- a/Wox.Plugin.System/Programs.cs
+++ b/Wox.Plugin.System/Programs.cs
@@ -37,7 +37,8 @@ namespace Wox.Plugin.System
{
if (string.IsNullOrEmpty(query.RawQuery) || query.RawQuery.EndsWith(" ") || query.RawQuery.Length <= 1) return new List();
- List returnList = installedList.Where(o => MatchProgram(o, query)).ToList();
+ var fuzzyMather = FuzzyMatcher.Create(query.RawQuery);
+ List returnList = installedList.Where(o => MatchProgram(o, fuzzyMather)).ToList();
returnList.ForEach(ScoreFilter);
return returnList.Select(c => new Result()
@@ -71,10 +72,12 @@ namespace Wox.Plugin.System
}).ToList();
}
- private bool MatchProgram(Program program, Query query)
+ private bool MatchProgram(Program program, FuzzyMatcher matcher)
{
- if (program.Title.ToLower().Contains(query.RawQuery.ToLower())) return true;
- if (ChineseToPinYin.ToPinYin(program.Title).Replace(" ", "").ToLower().Contains(query.RawQuery.ToLower())) return true;
+ program.Score = matcher.Score(program.Title);
+ if (program.Score > 0) return true;
+ program.Score = matcher.Score(ChineseToPinYin.ToPinYin(program.Title).Replace(" ", ""));
+ if (program.Score > 0) return true;
return false;
}
diff --git a/Wox.Test/FuzzyMatcherTest.cs b/Wox.Test/FuzzyMatcherTest.cs
new file mode 100644
index 0000000000..8f92de72bd
--- /dev/null
+++ b/Wox.Test/FuzzyMatcherTest.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using Wox.Infrastructure;
+
+namespace Wox.Test
+{
+ [TestFixture]
+ public class FuzzyMatcherTest
+ {
+ [Test]
+ public void MatchTest()
+ {
+ var sources = new List()
+ {
+ "file open in browser-test",
+ "Install Package",
+ "add new bsd",
+ "Inste",
+ "aac",
+ };
+
+
+ var results = new List();
+ foreach (var str in sources)
+ {
+ results.Add(new Plugin.Result()
+ {
+ Title = str,
+ Score = FuzzyMatcher.Create("inst").Score(str)
+ });
+ }
+
+ results = results.Where(x => x.Score > 0).OrderByDescending(x => x.Score).ToList();
+
+ Assert.IsTrue(results.Count == 3);
+ Assert.IsTrue(results[0].Title == "Inste");
+ Assert.IsTrue(results[1].Title == "Install Package");
+ Assert.IsTrue(results[2].Title == "file open in browser-test");
+ }
+ }
+}
diff --git a/Wox.Test/Wox.Test.csproj b/Wox.Test/Wox.Test.csproj
index 2544075926..f66ade2d3e 100644
--- a/Wox.Test/Wox.Test.csproj
+++ b/Wox.Test/Wox.Test.csproj
@@ -43,6 +43,7 @@
+
@@ -55,6 +56,10 @@
{097B4AC0-74E9-4C58-BCF8-C69746EC8271}
Python.Runtime
+
+ {4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}
+ Wox.Infrastructure
+
{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}
Wox.Plugin