diff options
Diffstat (limited to 'src/application.vala')
-rw-r--r-- | src/application.vala | 99 |
1 files changed, 76 insertions, 23 deletions
diff --git a/src/application.vala b/src/application.vala index b5cdcfd..896799d 100644 --- a/src/application.vala +++ b/src/application.vala @@ -1,7 +1,7 @@ namespace AstalApps { public class Application : Object { public DesktopAppInfo app { get; construct set; } - public uint frequency { get; set; } + public int frequency { get; set; default = 0; } public string name { get { return app.get_name(); } } public string entry { get { return app.get_id(); } } public string description { get { return app.get_description(); } } @@ -9,8 +9,9 @@ public class Application : Object { public string executable { owned get { return app.get_string("Exec"); } } public string icon_name { owned get { return app.get_string("Icon"); } } - internal Application(string id, uint? frequency = 0) { - Object(app: new DesktopAppInfo(id), frequency: frequency); + internal Application(string id, int? frequency = 0) { + Object(app: new DesktopAppInfo(id)); + this.frequency = frequency; } public string get_key(string key) { @@ -26,26 +27,32 @@ public class Application : Object { } } - public double match(string term) { - int n = 0; - double score = 0; - if (name != null) { - score += jaro_winkler_similarity(term, name); - ++n; - } - if (entry != null) { - score += jaro_winkler_similarity(term, entry); - ++n; - } - if (executable != null) { - score += jaro_winkler_similarity(term, executable); - ++n; - } - if (description != null) { - score += levenshtein_distance(term, description); - ++n; - } - return n > 0 ? score / n : 0; + public Score fuzzy_match(string term) { + var score = Score(); + if (name != null) + score.name = levenshtein(term, name); + if (entry != null) + score.entry = levenshtein(term, entry); + if (executable != null) + score.executable = levenshtein(term, executable); + if (description != null) + score.description = levenshtein(term, description); + + return score; + } + + public Score exact_match(string term) { + var score = Score(); + if (name != null) + score.name = name.down().contains(term.down()) ? 1 : 0; + if (entry != null) + score.entry = entry.down().contains(term.down()) ? 1 : 0; + if (executable != null) + score.executable = executable.down().contains(term.down()) ? 1 : 0; + if (description != null) + score.description = description.down().contains(term.down()) ? 1 : 0; + + return score; } internal Json.Node to_json() { @@ -56,8 +63,54 @@ public class Application : Object { .set_member_name("executable").add_string_value(executable) .set_member_name("description").add_string_value(description) .set_member_name("icon_name").add_string_value(icon_name) + .set_member_name("frequency").add_int_value(frequency) .end_object() .get_root(); } } + +int min3(int a, int b, int c) { + return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c); +} + +double levenshtein(string s1, string s2) { + int len1 = s1.length; + int len2 = s2.length; + + int[, ] d = new int[len1 + 1, len2 + 1]; + + for (int i = 0; i <= len1; i++) { + d[i, 0] = i; + } + for (int j = 0; j <= len2; j++) { + d[0, j] = j; + } + + for (int i = 1; i <= len1; i++) { + for (int j = 1; j <= len2; j++) { + int cost = (s1[i - 1] == s2[j - 1]) ? 0 : 1; + d[i, j] = min3( + d[i - 1, j] + 1, // deletion + d[i, j - 1] + 1, // insertion + d[i - 1, j - 1] + cost // substitution + ); + } + } + + var distance = d[len1, len2]; + int max_len = len1 > len2 ? len1 : len2; + + if (max_len == 0) { + return 1.0; + } + + return 1.0 - ((double)distance / max_len); +} + +public struct Score { + double name; + double entry; + double executable; + double description; +} } |