diff --git a/examples/worf-hyprswitch/src/main.rs b/examples/worf-hyprswitch/src/main.rs index 29e818d..5e009f9 100644 --- a/examples/worf-hyprswitch/src/main.rs +++ b/examples/worf-hyprswitch/src/main.rs @@ -5,6 +5,7 @@ use hyprland::{ }; use rayon::prelude::*; use std::collections::HashMap; +use std::path::PathBuf; use std::{env, fs, sync::Arc, thread}; use sysinfo::{Pid, System}; use worf::{ @@ -115,7 +116,7 @@ impl ItemProvider for WindowProvider { } } -fn load_icon_cache(cache_path: &String) -> Result, Error> { +fn load_icon_cache(cache_path: &PathBuf) -> Result, Error> { let toml_content = fs::read_to_string(cache_path).map_err(|e| Error::UpdateCacheError(format!("{e}")))?; let cache: HashMap = toml::from_str(&toml_content) @@ -123,15 +124,6 @@ fn load_icon_cache(cache_path: &String) -> Result, Error Ok(cache) } -fn cache_path() -> Result { - let path = dirs::cache_dir() - .map(|x| x.join("worf-hyprswitch")) - .ok_or_else(|| Error::UpdateCacheError("cannot read cache file".to_owned()))?; - - desktop::create_file_if_not_exists(&path)?; - Ok(path.to_string_lossy().into_owned()) -} - fn main() -> Result<(), String> { env_logger::Builder::new() .parse_filters(&env::var("RUST_LOG").unwrap_or_else(|_| "error".to_owned())) @@ -141,7 +133,8 @@ fn main() -> Result<(), String> { let args = config::parse_args(); let config = config::load_config(Some(&args)).unwrap_or(args); - let cache_path = cache_path().map_err(|err| err.to_string())?; + let cache_path = + desktop::cache_file_path(&config, "worf-hyprswitch").map_err(|err| err.to_string())?; let mut cache = load_icon_cache(&cache_path).map_err(|e| e.to_string())?; let provider = WindowProvider::new(&config, &cache)?; diff --git a/worf/src/lib/config.rs b/worf/src/lib/config.rs index 703da58..6d1691b 100644 --- a/worf/src/lib/config.rs +++ b/worf/src/lib/config.rs @@ -245,7 +245,7 @@ pub struct Config { allow_markup: Option, #[clap(short = 'k', long = "cache-file")] - cache_file: Option, // todo support this + cache_file: Option, /// Defines which terminal to use. defaults to the first one found: /// * kitty @@ -291,6 +291,7 @@ pub struct Config { )] location: Option>, + /// If set to `true` sub actions will be disabled #[clap(short = 'a', long = "no-actions")] no_actions: Option, @@ -621,6 +622,11 @@ impl Config { self.allow_markup.unwrap_or(false) } + #[must_use] + pub fn cache_file(&self) -> Option { + self.cache_file.clone() + } + #[must_use] pub fn password(&self) -> Option { self.password.clone() diff --git a/worf/src/lib/desktop.rs b/worf/src/lib/desktop.rs index d786687..2350651 100644 --- a/worf/src/lib/desktop.rs +++ b/worf/src/lib/desktop.rs @@ -219,6 +219,22 @@ fn start_forked_cmd(mut cmd: Command) -> Result<(), Error> { Ok(()) } +/// Get the path of a given cache file +/// # Errors +/// Will return Error if the cache file cannot be created or not found. +pub fn cache_file_path(config: &Config, name: &str) -> Result { + let path = if let Some(cfg) = config.cache_file() { + PathBuf::from(cfg) + } else { + dirs::cache_dir() + .map(|x| x.join(name)) + .ok_or_else(|| Error::UpdateCacheError("cannot read cache file".to_owned()))? + }; + + create_file_if_not_exists(&path)?; + Ok(path) +} + /// Parse a simple toml cache file from the format below /// "Key"=score /// i.e. @@ -227,13 +243,9 @@ fn start_forked_cmd(mut cmd: Command) -> Result<(), Error> { /// "Files"=50 /// # Errors /// Returns an Error when the given file is not found or did not parse. -pub fn load_cache_file(cache_path: Option<&PathBuf>) -> Result, Error> { - let Some(path) = cache_path else { - return Err(Error::MissingFile); - }; - +pub fn load_cache_file(cache_path: &PathBuf) -> Result, Error> { let toml_content = - fs::read_to_string(path).map_err(|e| Error::UpdateCacheError(format!("{e}")))?; + fs::read_to_string(cache_path).map_err(|e| Error::UpdateCacheError(format!("{e}")))?; let parsed: toml::Value = toml_content .parse() .map_err(|_| Error::ParsingError("failed to parse cache".to_owned()))?; diff --git a/worf/src/lib/modes/auto.rs b/worf/src/lib/modes/auto.rs index df28f2d..b7b06e2 100644 --- a/worf/src/lib/modes/auto.rs +++ b/worf/src/lib/modes/auto.rs @@ -37,12 +37,7 @@ struct AutoItemProvider { impl AutoItemProvider { fn new(config: &Config) -> Self { AutoItemProvider { - drun: DRunProvider::new( - AutoRunType::DRun, - config.no_actions(), - config.sort_order(), - config.term(), - ), + drun: DRunProvider::new(AutoRunType::DRun, config), file: FileItemProvider::new(AutoRunType::File, config.sort_order()), math: MathProvider::new(AutoRunType::Math), ssh: SshProvider::new(AutoRunType::Ssh, &config.sort_order()), @@ -157,7 +152,7 @@ pub fn show(config: &Config) -> Result<(), Error> { provider.math.elements.push(selection_result); } AutoRunType::DRun => { - update_drun_cache_and_run(cache_path, &mut cache, selection_result)?; + update_drun_cache_and_run(&cache_path, &mut cache, selection_result)?; break; } AutoRunType::File => { diff --git a/worf/src/lib/modes/drun.rs b/worf/src/lib/modes/drun.rs index ae4c89b..1cf6995 100644 --- a/worf/src/lib/modes/drun.rs +++ b/worf/src/lib/modes/drun.rs @@ -28,7 +28,7 @@ struct DRunCache { #[derive(Clone)] pub(crate) struct DRunProvider { items: Option>>, - pub(crate) cache_path: Option, + pub(crate) cache_path: PathBuf, pub(crate) cache: HashMap, data: T, no_actions: bool, @@ -50,21 +50,16 @@ impl ItemProvider for DRunProvider { } impl DRunProvider { - pub(crate) fn new( - menu_item_data: T, - no_actions: bool, - sort_order: SortOrder, - terminal: Option, - ) -> Self { - let (cache_path, d_run_cache) = load_d_run_cache(); + pub(crate) fn new(menu_item_data: T, config: &Config) -> Self { + let (cache_path, d_run_cache) = load_cache("drun_cache", config).unwrap(); DRunProvider { items: None, cache_path, cache: d_run_cache, data: menu_item_data, - no_actions, - sort_order, - terminal, + no_actions: config.no_actions(), + sort_order: config.sort_order(), + terminal: config.term(), } } @@ -195,21 +190,14 @@ impl DRunProvider { } } -fn load_d_run_cache() -> (Option, HashMap) { - let cache_path = dirs::cache_dir().map(|x| x.join("worf-drun")); - load_cache(cache_path) -} - pub(crate) fn update_drun_cache_and_run( - cache_path: Option, + cache_path: &PathBuf, cache: &mut HashMap, selection_result: MenuItem, -) -> Result<(), Error> { - if let Some(cache_path) = cache_path { - *cache.entry(selection_result.label).or_insert(0) += 1; - if let Err(e) = save_cache_file(&cache_path, cache) { - log::warn!("cannot save drun cache {e:?}"); - } +) -> Result<(), crate::Error> { + *cache.entry(selection_result.label).or_insert(0) += 1; + if let Err(e) = save_cache_file(cache_path, cache) { + log::warn!("cannot save drun cache {e:?}"); } if let Some(action) = selection_result.action { @@ -224,14 +212,14 @@ pub(crate) fn update_drun_cache_and_run( /// /// Will return `Err` if it was not able to spawn the process pub fn show(config: &Config) -> Result<(), Error> { - let provider = DRunProvider::new(0, config.no_actions(), config.sort_order(), config.term()); + let provider = DRunProvider::new(0, config); let cache_path = provider.cache_path.clone(); let mut cache = provider.cache.clone(); // todo ues a arc instead of cloning the config let selection_result = gui::show(config.clone(), provider, false, None, None); match selection_result { - Ok(s) => update_drun_cache_and_run(cache_path, &mut cache, s.menu)?, + Ok(s) => update_drun_cache_and_run(&cache_path, &mut cache, s.menu)?, Err(_) => { log::error!("No item selected"); } diff --git a/worf/src/lib/modes/mod.rs b/worf/src/lib/modes/mod.rs index 1221c2f..7589649 100644 --- a/worf/src/lib/modes/mod.rs +++ b/worf/src/lib/modes/mod.rs @@ -1,7 +1,8 @@ +use crate::Error; +use crate::config::Config; +use crate::desktop::{cache_file_path, create_file_if_not_exists, load_cache_file}; use std::{collections::HashMap, path::PathBuf}; -use crate::desktop::{create_file_if_not_exists, load_cache_file}; - pub mod auto; pub mod dmenu; pub mod drun; @@ -12,15 +13,17 @@ pub mod run; pub mod search; pub mod ssh; -pub(crate) fn load_cache(cache_path: Option) -> (Option, HashMap) { +pub(crate) fn load_cache( + name: &str, + config: &Config, +) -> Result<(PathBuf, HashMap), Error> { + let cache_path = cache_file_path(config, name)?; let cache = { - if let Some(ref cache_path) = cache_path { - if let Err(e) = create_file_if_not_exists(cache_path) { - log::warn!("No drun cache file and cannot create: {e:?}"); - } + if let Err(e) = create_file_if_not_exists(&cache_path) { + log::warn!("No drun cache file and cannot create: {e:?}"); } - load_cache_file(cache_path.as_ref()).unwrap_or_default() + load_cache_file(&cache_path).unwrap_or_default() }; - (cache_path, cache) + Ok((cache_path, cache)) } diff --git a/worf/src/lib/modes/run.rs b/worf/src/lib/modes/run.rs index f496b0d..4bfdfda 100644 --- a/worf/src/lib/modes/run.rs +++ b/worf/src/lib/modes/run.rs @@ -30,20 +30,20 @@ impl ItemProvider for RunProvider { #[derive(Clone)] struct RunProvider { items: Option>>, - cache_path: Option, + cache_path: PathBuf, cache: HashMap, sort_order: SortOrder, } impl RunProvider { - fn new(sort_order: SortOrder) -> Self { - let (cache_path, d_run_cache) = load_run_cache(); - RunProvider { + fn new(config: &Config) -> Result { + let (cache_path, d_run_cache) = load_cache("worf-run", config)?; + Ok(RunProvider { items: None, cache_path, cache: d_run_cache, - sort_order, - } + sort_order: config.sort_order(), + }) } #[allow(clippy::cast_possible_truncation)] @@ -98,21 +98,14 @@ impl RunProvider { } } -fn load_run_cache() -> (Option, HashMap) { - let cache_path = dirs::cache_dir().map(|x| x.join("worf-run")); - load_cache(cache_path) -} - fn update_run_cache_and_run( - cache_path: Option, + cache_path: &PathBuf, cache: &mut HashMap, selection_result: MenuItem, ) -> Result<(), Error> { - if let Some(cache_path) = cache_path { - *cache.entry(selection_result.label).or_insert(0) += 1; - if let Err(e) = save_cache_file(&cache_path, cache) { - log::warn!("cannot save run cache {e:?}"); - } + *cache.entry(selection_result.label).or_insert(0) += 1; + if let Err(e) = save_cache_file(cache_path, cache) { + log::warn!("cannot save run cache {e:?}"); } if let Some(action) = selection_result.action { @@ -132,13 +125,12 @@ fn update_run_cache_and_run( /// /// Will return `Err` if it was not able to spawn the process pub fn show(config: &Config) -> Result<(), Error> { - let provider = RunProvider::new(config.sort_order()); + let provider = RunProvider::new(config)?; let cache_path = provider.cache_path.clone(); let mut cache = provider.cache.clone(); - let selection_result = gui::show(config.clone(), provider, false, None, None); match selection_result { - Ok(s) => update_run_cache_and_run(cache_path, &mut cache, s.menu)?, + Ok(s) => update_run_cache_and_run(&cache_path, &mut cache, s.menu)?, Err(_) => { log::error!("No item selected"); }