diff --git a/Cargo.toml b/Cargo.toml index 67a5b54..1b52d6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,6 @@ desktop = [ "dep:freedesktop-desktop-entry", "dep:mime", "dep:shlex", - "dep:textdistance", "dep:zbus", ] # Enables keycode serialization @@ -92,7 +91,6 @@ rustix = { version = "0.38.34", features = ["pipe", "process"], optional = true serde = { version = "1.0.180", features = ["derive"] } slotmap = "1.0.6" smol = { version = "2.0.0", optional = true } -textdistance = { version = "1.0.2", optional = true } thiserror = "1.0.44" tokio = { version = "1.24.2", optional = true } tracing = "0.1" diff --git a/src/desktop.rs b/src/desktop.rs index 9ac4a3c..51c12ee 100644 --- a/src/desktop.rs +++ b/src/desktop.rs @@ -1,9 +1,7 @@ pub use freedesktop_desktop_entry::DesktopEntry; -use iced_widget::canvas::path::lyon_path::geom::euclid::approxord::min; pub use mime::Mime; use std::{ borrow::Cow, - cmp::max, ffi::OsStr, path::{Path, PathBuf}, }; @@ -83,121 +81,46 @@ pub fn app_id_or_fallback_matches(app_id: &str, entry: &DesktopEntryData) -> boo || app_id.to_lowercase() == entry.name.to_lowercase() } -/// From 0 to 1. -/// 1 is a perfect match. -fn match_entry(id: &str, de: &DesktopEntry) -> f32 { - let cmp = |id, de| { - let lcsstr = textdistance::str::lcsstr(id, de); - lcsstr as f32 / (max(id.len(), de.len())) as f32 - }; - - fn max_f32(a: f32, b: f32) -> f32 { - if a > b { - return a; - } else { - b - } - } - - let id = id.to_lowercase(); - let de_id = de.appid.to_lowercase(); - let de_wm_class = de.startup_wm_class().unwrap_or_default().to_lowercase(); - let de_name = de.name(None).unwrap_or_default().to_lowercase(); - - return max_f32( - cmp(&id, &de_id), - max_f32(cmp(&id, &de_wm_class), cmp(&id, &de_name)), - ); -} - pub fn load_applications_for_app_ids<'a, 'b>( locale: impl Into>, app_ids: impl Iterator, fill_missing_ones: bool, include_no_display: bool, ) -> Vec { - // need to be owned - let all_desktop_entries_string = - freedesktop_desktop_entry::Iter::new(freedesktop_desktop_entry::default_paths()) - .filter_map(|path| { - std::fs::read_to_string(&path) - .ok() - .map(|content| (path, content)) - }) - .collect::>(); - - let all_desktop_entries = all_desktop_entries_string - .iter() - .filter_map(|(path, content)| DesktopEntry::decode(&path, &content).ok()) - .collect::>(); - - let mut applications = Vec::new(); - let mut missing = Vec::new(); - - let locale = locale.into(); - - for id in app_ids { - let mut max_score = None; - let mut second_max_score = 0.; - - for de in &all_desktop_entries { - if !include_no_display && de.no_display() { - continue; - } - - let score = match_entry(id, de); - - match max_score { - Some((prev_max_score, _)) => { - if prev_max_score < score { - second_max_score = prev_max_score; - max_score = Some((score, de)); - } - } - None => { - max_score = Some((score, de)); - } - } - - if score > 0.99 { - break; - } + let mut app_ids = app_ids.collect::>(); + let mut applications = load_applications_filtered(locale, |de| { + if !include_no_display && de.no_display() { + return false; } - - let mut add_missing = false; - match max_score { - Some((max_score, de)) => { - let entropy = max_score - second_max_score; - - if max_score > 0.7 || entropy > 0.2 && max_score > 0.2 { - applications.push(DesktopEntryData::from_desktop_entry( - locale, - Some(de.path.to_path_buf()), - de, - )); - } else { - add_missing = true; - } - } - None => { - add_missing = true; - } + // If appid matches, or startup_wm_class matches... + if let Some(i) = app_ids.iter().position(|id| { + id == &de.appid + || id + .to_lowercase() + .eq(&de.startup_wm_class().unwrap_or_default().to_lowercase()) + }) { + app_ids.remove(i); + true + // Fallback: If the name matches... + } else if let Some(i) = app_ids.iter().position(|id| { + de.name(None) + .map(|n| n.to_lowercase() == id.to_lowercase()) + .unwrap_or_default() + }) { + app_ids.remove(i); + true + } else { + false } - - if fill_missing_ones && add_missing { - missing.push(id); - } - } - + }); if fill_missing_ones { - applications.extend(missing.into_iter().map(|app_id| DesktopEntryData { + applications.extend(app_ids.into_iter().map(|app_id| DesktopEntryData { id: app_id.to_string(), name: app_id.to_string(), icon: IconSource::default(), ..Default::default() })); } - applications } @@ -218,7 +141,7 @@ pub fn load_applications_filtered<'a, F: FnMut(&DesktopEntry) -> bool>( Some(DesktopEntryData::from_desktop_entry( locale, path.clone(), - &de, + de, )) }) }) @@ -234,7 +157,7 @@ pub fn load_desktop_file<'a>( std::fs::read_to_string(path).ok().and_then(|input| { DesktopEntry::decode(path, &input) .ok() - .map(|de| DesktopEntryData::from_desktop_entry(locale, PathBuf::from(path), &de)) + .map(|de| DesktopEntryData::from_desktop_entry(locale, PathBuf::from(path), de)) }) } @@ -242,7 +165,7 @@ impl DesktopEntryData { fn from_desktop_entry<'a>( locale: impl Into>, path: impl Into>, - de: &DesktopEntry, + de: DesktopEntry, ) -> DesktopEntryData { let locale = locale.into();