diff options
| author | delta <darkussdelta@gmail.com> | 2025-10-29 16:35:38 +0100 |
|---|---|---|
| committer | delta <darkussdelta@gmail.com> | 2025-10-29 16:35:38 +0100 |
| commit | d7c66522cf365f516babcfeb1d4a2d36c3ea41af (patch) | |
| tree | 30c7d6103037b31170ae6d8fd58e3849e3cea823 /.config/awesome/quarrel/native/src/lenses/application.rs | |
| parent | df418700b7d776f03ee5b58daa2d497cddb45aca (diff) | |
a small refactor
Diffstat (limited to '.config/awesome/quarrel/native/src/lenses/application.rs')
| -rw-r--r-- | .config/awesome/quarrel/native/src/lenses/application.rs | 108 |
1 files changed, 84 insertions, 24 deletions
diff --git a/.config/awesome/quarrel/native/src/lenses/application.rs b/.config/awesome/quarrel/native/src/lenses/application.rs index 89b7bb4..38a7762 100644 --- a/.config/awesome/quarrel/native/src/lenses/application.rs +++ b/.config/awesome/quarrel/native/src/lenses/application.rs @@ -1,58 +1,118 @@ use std::{ - fs::read_dir, path::PathBuf + any::type_name, + fs::read_dir, + path::PathBuf, + sync::{ + atomic::{ + AtomicBool, + Ordering, + }, + Arc, + OnceLock, + RwLock, + }, }; use freedesktop_entry_parser as fd; use mlua::prelude::*; +use notify::RecommendedWatcher; use rayon::prelude::*; use url::Url; use crate::lenses::{ - Entry, - Lense, - Cache + Cache, Entries, Entry, Lense }; +static APPS_DIR: &'static str = "/usr/share/applications"; +static WATCHER: OnceLock<RecommendedWatcher> = OnceLock::new(); + #[derive(Default)] -pub struct Application(pub Cache); +pub struct Application { + cache: RwLock<Cache>, + should_interrupt: AtomicBool, +} impl Lense for Application { const NAME: &str = "Application"; - fn get_cache(&self) -> &Cache { - &self.0 + fn init() -> Arc<Self> { + let this = Arc::new(Application::default()); + let watcher_this = this.clone(); + WATCHER + .set( + notify::recommended_watcher(move |event| { + match event { + Ok(_) => { + // We don't care what specifically changed, just that *it did* + watcher_this.set_cache(Cache::Stale); + } + Err(err) => { + eprintln!("Watch error: {:?}", err) + } + } + }) + .expect("Failed to instantiate a watcher"), + ) + .expect("Failed to set a watcher"); + this + } + + #[inline] + fn set_cache(&self, cache: Cache) { + if let Err(err) = self.cache.write().map(|mut place| *place = cache) { + eprintln!( + "Failed to write cache value for {}: {:?}", + type_name::<Self>(), + err + ) + } + } + + #[inline] + fn get_cache(&self) -> Cache { + match self.cache.read() { + Ok(ok) => ok.clone(), + Err(err) => { + eprintln!( + "Failed to read cache value for {}: {:?}", + type_name::<Self>(), + err + ); + Cache::Stale + } + } + } + + #[inline] + fn set_interrupt(&self, interrupt: bool) { + // self.should_interrupt.store(interrupt, Ordering::Relaxed) } - fn set_cache(&mut self, cache: Cache) { - self.0 = cache; + #[inline] + fn get_interrupt(&self) -> bool { + false + // self.should_interrupt.load(Ordering::Relaxed) } - fn query(_: &Lua, input: String) -> Result<Vec<Entry>, anyhow::Error> { - let applications_dir = "/usr/share/applications"; - let entries = read_dir(applications_dir)? + fn entries(&self, _: &Lua, _: String) -> Result<Entries, anyhow::Error> { + let entries = read_dir(APPS_DIR)? .map(|result| result.map(|e| e.path())) .collect::<Result<Vec<_>, std::io::Error>>()?; - let parsed_entries: Vec<Entry> = entries + let parsed_entries: Entries = entries .into_par_iter() .filter(|path| path.extension().is_some_and(|ext| ext == "desktop")) - .filter_map(|path| { - parse_entry(path).ok().flatten() - }) - .collect(); + .filter_map(|path| parse_entry(path).ok().flatten()) + .collect::<Vec<Entry>>() + .into(); - Ok( - parsed_entries - .into_iter() - .filter(|entry| entry.message.to_lowercase().contains(&input.to_lowercase())) - .collect(), - ) + Ok(parsed_entries) } } fn parse_entry(path: PathBuf) -> Result<Option<Entry>, ()> { let Ok(entry) = fd::parse_entry(&path) else { - return Err(()) + return Err(()); }; let section = entry.section("Desktop Entry"); |
