freedesktop_desktop_entry/
matching.rs1use crate::DesktopEntry;
5
6impl DesktopEntry {
7 pub fn match_query<Q, L>(
10 &self,
11 query: Q,
12 locales: &[L],
13 additional_haystack_values: &[&str],
14 ) -> f64
15 where
16 Q: AsRef<str>,
17 L: AsRef<str>,
18 {
19 #[inline]
20 fn add_value(v: &mut Vec<String>, value: &str, is_multiple: bool) {
21 if is_multiple {
22 value.split(';').for_each(|e| v.push(e.to_lowercase()));
23 } else {
24 v.push(value.to_lowercase());
25 }
26 }
27
28 let fields = [
30 ("Name", false),
31 ("GenericName", false),
32 ("Comment", false),
33 ("Categories", true),
34 ("Keywords", true),
35 ];
36
37 let mut normalized_values: Vec<String> = Vec::new();
38
39 normalized_values.extend(
40 additional_haystack_values
41 .iter()
42 .map(|val| val.to_lowercase()),
43 );
44
45 let desktop_entry_group = self.groups.group("Desktop Entry");
46
47 for field in fields {
48 if let Some(group) = desktop_entry_group {
49 if let Some((default_value, locale_map)) = group.0.get(field.0) {
50 add_value(&mut normalized_values, default_value, field.1);
51
52 let mut at_least_one_locale = false;
53
54 for locale in locales {
55 match locale_map.get(locale.as_ref()) {
56 Some(value) => {
57 add_value(&mut normalized_values, value, field.1);
58 at_least_one_locale = true;
59 }
60 None => {
61 if let Some(pos) = locale.as_ref().find('_') {
62 if let Some(value) = locale_map.get(&locale.as_ref()[..pos]) {
63 add_value(&mut normalized_values, value, field.1);
64 at_least_one_locale = true;
65 }
66 }
67 }
68 }
69 }
70
71 if !at_least_one_locale {
72 if let Some(domain) = &self.ubuntu_gettext_domain {
73 let gettext_value = crate::dgettext(domain, default_value);
74 if !gettext_value.is_empty() {
75 add_value(&mut normalized_values, &gettext_value, false);
76 }
77 }
78 }
79 }
80 }
81 }
82
83 let query = query.as_ref().to_lowercase();
84
85 let query_espaced = query.split_ascii_whitespace().collect::<Vec<_>>();
86
87 normalized_values
88 .into_iter()
89 .map(|de_field| {
90 let jaro_score = strsim::jaro_winkler(&query, &de_field);
91
92 if query_espaced.iter().any(|query| de_field.contains(*query)) {
93 (jaro_score + 0.1).clamp(0.61, 1.)
95 } else {
96 jaro_score
97 }
98 })
99 .max_by(|e1, e2| e1.total_cmp(e2))
100 .unwrap_or(0.0)
101 }
102}
103
104pub fn find_entry_from_appid<'a, I>(entries: I, appid: &str) -> Option<&'a DesktopEntry>
106where
107 I: IntoIterator<Item = &'a DesktopEntry>,
108{
109 let normalized_appid = appid.to_lowercase();
110
111 entries.into_iter().find(|e| {
112 if e.appid.to_lowercase() == normalized_appid {
113 return true;
114 }
115
116 if let Some(field) = e.startup_wm_class() {
117 if field.to_lowercase() == normalized_appid {
118 return true;
119 }
120 }
121
122 false
123 })
124}