Cyril Levis: 1 feat: add ranking based on usage to launcher widget 3 files changed, 75 insertions(+), 4 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~kennylevinsen/public-inbox/patches/27838/mbox | git am -3Learn more about email & git
A v3, and the last ;) Less unwrap. Signed-off-by: Cyril Levis <git@levis.name> --- src/data.rs | 57 +++++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/widgets/launcher.rs | 21 ++++++++++++--- 3 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 src/data.rs diff --git a/src/data.rs b/src/data.rs new file mode 100644 index 0000000..8992b2f --- /dev/null +++ b/src/data.rs @@ -0,0 +1,57 @@ +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::env; +use std::error::Error; +use std::fs::{create_dir_all, File, OpenOptions}; +use std::path::PathBuf; + +#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)] +pub struct Data { + pub entries: HashMap<String, i64>, +} + +impl Data { + pub fn load() -> Result<Data, Box<dyn Error>> { + Ok(serde_yaml::from_reader(Self::read_file()?)?) + } + + pub fn save(&self) -> Result<(), Box<dyn Error>> { + Ok(serde_yaml::to_writer(Self::write_file()?, self)?) + } + + fn read_file() -> Result<File, Box<dyn Error>> { + Ok(OpenOptions::new() + .create(true) + .write(true) + .read(true) + .open(Self::path()?)?) + } + + fn write_file() -> Result<File, Box<dyn Error>> { + Ok(OpenOptions::new() + .create(true) + .write(true) + .truncate(true) + .open(Self::path()?)?) + } + + fn path() -> Result<PathBuf, Box<dyn Error>> { + let xdg_cache = match env::var_os("XDG_CACHE_HOME") { + Some(s) => s + .into_string() + .map_err(|_| "Unable to resolve $XDG_CACHE_HOME")?, + None => format!( + "{}/.cache", + env::var_os("HOME") + .ok_or("Unable to resolve $HOME")? + .into_string() + .map_err(|_| "Unable to resolve $HOME")? + ), + }; + + let cache_dir = PathBuf::from(xdg_cache).join("wldash"); + create_dir_all(&cache_dir)?; + + Ok(cache_dir.join("data.yaml")) + } +} diff --git a/src/main.rs b/src/main.rs index 68dd057..3d36fc6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ mod cmd; mod color; mod config; mod configfmt; +mod data; mod desktop; mod doublemempool; mod draw; diff --git a/src/widgets/launcher.rs b/src/widgets/launcher.rs index 081f266..a8593ba 100644 --- a/src/widgets/launcher.rs +++ b/src/widgets/launcher.rs @@ -14,6 +14,7 @@ use std::collections::HashMap; use std::process::Command; use std::sync::mpsc::Sender; +use crate::data::Data; use crate::keyboard::keysyms; use fuzzy_matcher::skim::SkimMatcherV2; use fuzzy_matcher::FuzzyMatcher; @@ -34,6 +35,7 @@ pub struct Launcher<'a> { length: u32, dirty: bool, tx: Sender<Cmd>, + counter: Data, } impl<'a> Launcher<'a> { @@ -61,6 +63,7 @@ impl<'a> Launcher<'a> { length, dirty: true, tx: listener, + counter: Data::load().unwrap_or_default(), }) } @@ -101,6 +104,7 @@ impl<'a> Launcher<'a> { let (_, indices) = fuzzy_matcher .fuzzy_indices(&m.name.to_lowercase(), &self.input.to_lowercase()) .unwrap_or((0, vec![])); + let mut colors = Vec::with_capacity(m.name.len()); for pos in 0..m.name.len() { if indices.contains(&pos) { @@ -215,12 +219,14 @@ fn wlcopy(s: &str) -> Result<(), String> { struct Matcher { matches: HashMap<Desktop, i64>, + counter: Data, } impl Matcher { - fn new() -> Self { + fn new(counter: Data) -> Self { Self { matches: HashMap::new(), + counter, } } @@ -248,9 +254,12 @@ impl Matcher { .collect::<Vec<(i64, Desktop)>>(); m.sort_by(|(ma1, d1), (ma2, d2)| { - if ma1 > ma2 { + let count1 = self.counter.entries.get(&d1.name).unwrap_or(&0); + let count2 = self.counter.entries.get(&d2.name).unwrap_or(&0); + + if ma1 + count1 > ma2 + count2 { Ordering::Less - } else if ma1 < ma2 { + } else if ma1 + count1 < ma2 + count2 { Ordering::Greater } else if d1.name.len() < d2.name.len() { Ordering::Less @@ -306,7 +315,7 @@ impl<'a> Widget for Launcher<'a> { } Some('!') => (), _ => { - let mut matcher = Matcher::new(); + let mut matcher = Matcher::new(self.counter.clone()); for desktop in self.options.iter() { matcher.try_match( @@ -428,6 +437,10 @@ impl<'a> Widget for Launcher<'a> { } else { lexed }; + + *self.counter.entries.entry(d.name.clone()).or_insert(0) += 1; + self.counter.save().expect("Unable to save data"); + if !lexed.is_empty() { let _ = Command::new(lexed[0].clone()).args(&lexed[1..]).spawn(); -- 2.34.1
builds.sr.ht <builds@sr.ht>wldash/patches/.build.yml: SUCCESS in 2m28s [feat: add ranking based on usage to launcher widget][0] v3 from [Cyril Levis][1] [0]: https://lists.sr.ht/~kennylevinsen/public-inbox/patches/27838 [1]: mailto:git@levis.name ✓ #660332 SUCCESS wldash/patches/.build.yml https://builds.sr.ht/~kennylevinsen/job/660332
Applied, thanks!