Hi Kenny, Another patch to apply after my 2 previous because this expects that name is unique. This give more weight to applications use more often. Wofi got this kind of behavior. This work by keeping an usage hashmap<name, counter> in a data file. I hope you will like it. Regards, Cyril Levis (1): feat: add ranking based on usage to launcher widget Cargo.lock | 51 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/data.rs | 44 +++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/widgets/launcher.rs | 21 +++++++++++++---- 5 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 src/data.rs -- 2.34.1
wldash/patches/.build.yml: FAILED in 33s [add ranking based on usage to launcher widget][0] from [Cyril Levis][1] [0]: https://lists.sr.ht/~kennylevinsen/public-inbox/patches/27816 [1]: mailto:git@levis.name ✗ #659943 FAILED wldash/patches/.build.yml https://builds.sr.ht/~kennylevinsen/job/659943
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~kennylevinsen/public-inbox/patches/27816/mbox | git am -3Learn more about email & git
--- Cargo.lock | 51 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/data.rs | 44 +++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/widgets/launcher.rs | 21 +++++++++++++---- 5 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 src/data.rs diff --git a/Cargo.lock b/Cargo.lock index 96bd23d..01a136e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -131,6 +131,26 @@ dependencies = [ "generic-array", ] +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dlib" version = "0.4.2" @@ -185,6 +205,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi", +] + [[package]] name = "itoa" version = "0.4.7" @@ -495,6 +526,25 @@ dependencies = [ "pest_derive", ] +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + [[package]] name = "rust-ini" version = "0.14.0" @@ -759,6 +809,7 @@ dependencies = [ "byteorder", "chrono", "dbus", + "dirs", "dlib", "fontconfig", "fuzzy-matcher", diff --git a/Cargo.toml b/Cargo.toml index c3fc985..232dc15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ rcalc_lib = "0.9" rust-ini = "0.14" shlex = "0.1" timerfd = "1.0.0" +dirs = "3.0" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", optional = true } diff --git a/src/data.rs b/src/data.rs new file mode 100644 index 0000000..34a5dfe --- /dev/null +++ b/src/data.rs @@ -0,0 +1,44 @@ +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +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 datadir = dirs::data_dir() + .ok_or("Unable to get data dir")? + .join("wldash"); + create_dir_all(&datadir)?; + Ok(datadir.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..f446a4b 100644 --- a/src/widgets/launcher.rs +++ b/src/widgets/launcher.rs @@ -15,6 +15,7 @@ use std::process::Command; use std::sync::mpsc::Sender; use crate::keyboard::keysyms; +use crate::data::Data; use fuzzy_matcher::skim::SkimMatcherV2; use fuzzy_matcher::FuzzyMatcher; use unicode_segmentation::UnicodeSegmentation; @@ -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: FAILED in 33s [add ranking based on usage to launcher widget][0] from [Cyril Levis][1] [0]: https://lists.sr.ht/~kennylevinsen/public-inbox/patches/27816 [1]: mailto:git@levis.name ✗ #659943 FAILED wldash/patches/.build.yml https://builds.sr.ht/~kennylevinsen/job/659943
--- Cargo.lock | 51 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/data.rs | 44 +++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/widgets/launcher.rs | 21 +++++++++++++---- 5 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 src/data.rs diff --git a/Cargo.lock b/Cargo.lock index 96bd23d..01a136e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -131,6 +131,26 @@ dependencies = [ "generic-array", ] +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dlib" version = "0.4.2" @@ -185,6 +205,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi", +] + [[package]] name = "itoa" version = "0.4.7" @@ -495,6 +526,25 @@ dependencies = [ "pest_derive", ] +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + [[package]] name = "rust-ini" version = "0.14.0" @@ -759,6 +809,7 @@ dependencies = [ "byteorder", "chrono", "dbus", + "dirs", "dlib", "fontconfig", "fuzzy-matcher", diff --git a/Cargo.toml b/Cargo.toml index c3fc985..232dc15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ rcalc_lib = "0.9" rust-ini = "0.14" shlex = "0.1" timerfd = "1.0.0" +dirs = "3.0" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", optional = true } diff --git a/src/data.rs b/src/data.rs new file mode 100644 index 0000000..34a5dfe --- /dev/null +++ b/src/data.rs @@ -0,0 +1,44 @@ +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +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 datadir = dirs::data_dir() + .ok_or("Unable to get data dir")? + .join("wldash"); + create_dir_all(&datadir)?; + Ok(datadir.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
Here the v2. --- Cargo.lock | 51 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/data.rs | 44 +++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/widgets/launcher.rs | 21 +++++++++++++---- 5 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 src/data.rs diff --git a/Cargo.lock b/Cargo.lock index 96bd23d..01a136e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -131,6 +131,26 @@ dependencies = [ "generic-array", ] +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dlib" version = "0.4.2" @@ -185,6 +205,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi", +] + [[package]] name = "itoa" version = "0.4.7" @@ -495,6 +526,25 @@ dependencies = [ "pest_derive", ] +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + [[package]] name = "rust-ini" version = "0.14.0" @@ -759,6 +809,7 @@ dependencies = [ "byteorder", "chrono", "dbus", + "dirs", "dlib", "fontconfig", "fuzzy-matcher", diff --git a/Cargo.toml b/Cargo.toml index c3fc985..232dc15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ rcalc_lib = "0.9" rust-ini = "0.14" shlex = "0.1" timerfd = "1.0.0" +dirs = "3.0" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", optional = true } diff --git a/src/data.rs b/src/data.rs new file mode 100644 index 0000000..34a5dfe --- /dev/null +++ b/src/data.rs @@ -0,0 +1,44 @@ +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +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 datadir = dirs::data_dir() + .ok_or("Unable to get data dir")? + .join("wldash"); + create_dir_all(&datadir)?; + Ok(datadir.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
This is the v2 without `dirs` crate Signed-off-by: Cyril Levis <git@levis.name> --- src/data.rs | 50 +++++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/widgets/launcher.rs | 21 +++++++++++++---- 3 files changed, 68 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..6be53d0 --- /dev/null +++ b/src/data.rs @@ -0,0 +1,50 @@ +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 home = env::var_os("HOME").unwrap().into_string().unwrap(); + let cache = match env::var_os("XDG_CACHE_HOME") { + Some(s) => s.into_string().unwrap(), + None => format!("{}/.cache", home), + }; + let datadir = Some(PathBuf::from(cache)) + .ok_or("Unable to get data dir")? + .join("wldash"); + create_dir_all(&datadir)?; + Ok(datadir.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
--- src/widgets/launcher.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/launcher.rs b/src/widgets/launcher.rs index f446a4b..a8593ba 100644 --- a/src/widgets/launcher.rs +++ b/src/widgets/launcher.rs @@ -14,8 +14,8 @@ use std::collections::HashMap; use std::process::Command; use std::sync::mpsc::Sender; -use crate::keyboard::keysyms; use crate::data::Data; +use crate::keyboard::keysyms; use fuzzy_matcher::skim::SkimMatcherV2; use fuzzy_matcher::FuzzyMatcher; use unicode_segmentation::UnicodeSegmentation; -- 2.34.1