support custom cache file, fixes 26
This commit is contained in:
parent
184c9a2b77
commit
74594d688d
7 changed files with 68 additions and 79 deletions
|
@ -5,6 +5,7 @@ use hyprland::{
|
||||||
};
|
};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::{env, fs, sync::Arc, thread};
|
use std::{env, fs, sync::Arc, thread};
|
||||||
use sysinfo::{Pid, System};
|
use sysinfo::{Pid, System};
|
||||||
use worf::{
|
use worf::{
|
||||||
|
@ -115,7 +116,7 @@ impl ItemProvider<Window> for WindowProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_icon_cache(cache_path: &String) -> Result<HashMap<String, String>, Error> {
|
fn load_icon_cache(cache_path: &PathBuf) -> Result<HashMap<String, String>, Error> {
|
||||||
let toml_content =
|
let toml_content =
|
||||||
fs::read_to_string(cache_path).map_err(|e| Error::UpdateCacheError(format!("{e}")))?;
|
fs::read_to_string(cache_path).map_err(|e| Error::UpdateCacheError(format!("{e}")))?;
|
||||||
let cache: HashMap<String, String> = toml::from_str(&toml_content)
|
let cache: HashMap<String, String> = toml::from_str(&toml_content)
|
||||||
|
@ -123,15 +124,6 @@ fn load_icon_cache(cache_path: &String) -> Result<HashMap<String, String>, Error
|
||||||
Ok(cache)
|
Ok(cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cache_path() -> Result<String, Error> {
|
|
||||||
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> {
|
fn main() -> Result<(), String> {
|
||||||
env_logger::Builder::new()
|
env_logger::Builder::new()
|
||||||
.parse_filters(&env::var("RUST_LOG").unwrap_or_else(|_| "error".to_owned()))
|
.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 args = config::parse_args();
|
||||||
let config = config::load_config(Some(&args)).unwrap_or(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 mut cache = load_icon_cache(&cache_path).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let provider = WindowProvider::new(&config, &cache)?;
|
let provider = WindowProvider::new(&config, &cache)?;
|
||||||
|
|
|
@ -245,7 +245,7 @@ pub struct Config {
|
||||||
allow_markup: Option<bool>,
|
allow_markup: Option<bool>,
|
||||||
|
|
||||||
#[clap(short = 'k', long = "cache-file")]
|
#[clap(short = 'k', long = "cache-file")]
|
||||||
cache_file: Option<String>, // todo support this
|
cache_file: Option<String>,
|
||||||
|
|
||||||
/// Defines which terminal to use. defaults to the first one found:
|
/// Defines which terminal to use. defaults to the first one found:
|
||||||
/// * kitty
|
/// * kitty
|
||||||
|
@ -291,6 +291,7 @@ pub struct Config {
|
||||||
)]
|
)]
|
||||||
location: Option<Vec<Anchor>>,
|
location: Option<Vec<Anchor>>,
|
||||||
|
|
||||||
|
/// If set to `true` sub actions will be disabled
|
||||||
#[clap(short = 'a', long = "no-actions")]
|
#[clap(short = 'a', long = "no-actions")]
|
||||||
no_actions: Option<bool>,
|
no_actions: Option<bool>,
|
||||||
|
|
||||||
|
@ -621,6 +622,11 @@ impl Config {
|
||||||
self.allow_markup.unwrap_or(false)
|
self.allow_markup.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn cache_file(&self) -> Option<String> {
|
||||||
|
self.cache_file.clone()
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn password(&self) -> Option<String> {
|
pub fn password(&self) -> Option<String> {
|
||||||
self.password.clone()
|
self.password.clone()
|
||||||
|
|
|
@ -219,6 +219,22 @@ fn start_forked_cmd(mut cmd: Command) -> Result<(), Error> {
|
||||||
Ok(())
|
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<PathBuf, Error> {
|
||||||
|
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
|
/// Parse a simple toml cache file from the format below
|
||||||
/// "Key"=score
|
/// "Key"=score
|
||||||
/// i.e.
|
/// i.e.
|
||||||
|
@ -227,13 +243,9 @@ fn start_forked_cmd(mut cmd: Command) -> Result<(), Error> {
|
||||||
/// "Files"=50
|
/// "Files"=50
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// Returns an Error when the given file is not found or did not parse.
|
/// Returns an Error when the given file is not found or did not parse.
|
||||||
pub fn load_cache_file(cache_path: Option<&PathBuf>) -> Result<HashMap<String, i64>, Error> {
|
pub fn load_cache_file(cache_path: &PathBuf) -> Result<HashMap<String, i64>, Error> {
|
||||||
let Some(path) = cache_path else {
|
|
||||||
return Err(Error::MissingFile);
|
|
||||||
};
|
|
||||||
|
|
||||||
let toml_content =
|
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
|
let parsed: toml::Value = toml_content
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| Error::ParsingError("failed to parse cache".to_owned()))?;
|
.map_err(|_| Error::ParsingError("failed to parse cache".to_owned()))?;
|
||||||
|
|
|
@ -37,12 +37,7 @@ struct AutoItemProvider {
|
||||||
impl AutoItemProvider {
|
impl AutoItemProvider {
|
||||||
fn new(config: &Config) -> Self {
|
fn new(config: &Config) -> Self {
|
||||||
AutoItemProvider {
|
AutoItemProvider {
|
||||||
drun: DRunProvider::new(
|
drun: DRunProvider::new(AutoRunType::DRun, config),
|
||||||
AutoRunType::DRun,
|
|
||||||
config.no_actions(),
|
|
||||||
config.sort_order(),
|
|
||||||
config.term(),
|
|
||||||
),
|
|
||||||
file: FileItemProvider::new(AutoRunType::File, config.sort_order()),
|
file: FileItemProvider::new(AutoRunType::File, config.sort_order()),
|
||||||
math: MathProvider::new(AutoRunType::Math),
|
math: MathProvider::new(AutoRunType::Math),
|
||||||
ssh: SshProvider::new(AutoRunType::Ssh, &config.sort_order()),
|
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);
|
provider.math.elements.push(selection_result);
|
||||||
}
|
}
|
||||||
AutoRunType::DRun => {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
AutoRunType::File => {
|
AutoRunType::File => {
|
||||||
|
|
|
@ -28,7 +28,7 @@ struct DRunCache {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct DRunProvider<T: Clone> {
|
pub(crate) struct DRunProvider<T: Clone> {
|
||||||
items: Option<Vec<MenuItem<T>>>,
|
items: Option<Vec<MenuItem<T>>>,
|
||||||
pub(crate) cache_path: Option<PathBuf>,
|
pub(crate) cache_path: PathBuf,
|
||||||
pub(crate) cache: HashMap<String, i64>,
|
pub(crate) cache: HashMap<String, i64>,
|
||||||
data: T,
|
data: T,
|
||||||
no_actions: bool,
|
no_actions: bool,
|
||||||
|
@ -50,21 +50,16 @@ impl<T: Clone + Send + Sync> ItemProvider<T> for DRunProvider<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone + Send + Sync> DRunProvider<T> {
|
impl<T: Clone + Send + Sync> DRunProvider<T> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(menu_item_data: T, config: &Config) -> Self {
|
||||||
menu_item_data: T,
|
let (cache_path, d_run_cache) = load_cache("drun_cache", config).unwrap();
|
||||||
no_actions: bool,
|
|
||||||
sort_order: SortOrder,
|
|
||||||
terminal: Option<String>,
|
|
||||||
) -> Self {
|
|
||||||
let (cache_path, d_run_cache) = load_d_run_cache();
|
|
||||||
DRunProvider {
|
DRunProvider {
|
||||||
items: None,
|
items: None,
|
||||||
cache_path,
|
cache_path,
|
||||||
cache: d_run_cache,
|
cache: d_run_cache,
|
||||||
data: menu_item_data,
|
data: menu_item_data,
|
||||||
no_actions,
|
no_actions: config.no_actions(),
|
||||||
sort_order,
|
sort_order: config.sort_order(),
|
||||||
terminal,
|
terminal: config.term(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,21 +190,14 @@ impl<T: Clone + Send + Sync> DRunProvider<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_d_run_cache() -> (Option<PathBuf>, HashMap<String, i64>) {
|
|
||||||
let cache_path = dirs::cache_dir().map(|x| x.join("worf-drun"));
|
|
||||||
load_cache(cache_path)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn update_drun_cache_and_run<T: Clone>(
|
pub(crate) fn update_drun_cache_and_run<T: Clone>(
|
||||||
cache_path: Option<PathBuf>,
|
cache_path: &PathBuf,
|
||||||
cache: &mut HashMap<String, i64>,
|
cache: &mut HashMap<String, i64>,
|
||||||
selection_result: MenuItem<T>,
|
selection_result: MenuItem<T>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), crate::Error> {
|
||||||
if let Some(cache_path) = cache_path {
|
*cache.entry(selection_result.label).or_insert(0) += 1;
|
||||||
*cache.entry(selection_result.label).or_insert(0) += 1;
|
if let Err(e) = save_cache_file(cache_path, cache) {
|
||||||
if let Err(e) = save_cache_file(&cache_path, cache) {
|
log::warn!("cannot save drun cache {e:?}");
|
||||||
log::warn!("cannot save drun cache {e:?}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(action) = selection_result.action {
|
if let Some(action) = selection_result.action {
|
||||||
|
@ -224,14 +212,14 @@ pub(crate) fn update_drun_cache_and_run<T: Clone>(
|
||||||
///
|
///
|
||||||
/// Will return `Err` if it was not able to spawn the process
|
/// Will return `Err` if it was not able to spawn the process
|
||||||
pub fn show(config: &Config) -> Result<(), Error> {
|
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 cache_path = provider.cache_path.clone();
|
||||||
let mut cache = provider.cache.clone();
|
let mut cache = provider.cache.clone();
|
||||||
|
|
||||||
// todo ues a arc instead of cloning the config
|
// todo ues a arc instead of cloning the config
|
||||||
let selection_result = gui::show(config.clone(), provider, false, None, None);
|
let selection_result = gui::show(config.clone(), provider, false, None, None);
|
||||||
match selection_result {
|
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(_) => {
|
Err(_) => {
|
||||||
log::error!("No item selected");
|
log::error!("No item selected");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use crate::desktop::{create_file_if_not_exists, load_cache_file};
|
|
||||||
|
|
||||||
pub mod auto;
|
pub mod auto;
|
||||||
pub mod dmenu;
|
pub mod dmenu;
|
||||||
pub mod drun;
|
pub mod drun;
|
||||||
|
@ -12,15 +13,17 @@ pub mod run;
|
||||||
pub mod search;
|
pub mod search;
|
||||||
pub mod ssh;
|
pub mod ssh;
|
||||||
|
|
||||||
pub(crate) fn load_cache(cache_path: Option<PathBuf>) -> (Option<PathBuf>, HashMap<String, i64>) {
|
pub(crate) fn load_cache(
|
||||||
|
name: &str,
|
||||||
|
config: &Config,
|
||||||
|
) -> Result<(PathBuf, HashMap<String, i64>), Error> {
|
||||||
|
let cache_path = cache_file_path(config, name)?;
|
||||||
let cache = {
|
let cache = {
|
||||||
if let Some(ref cache_path) = cache_path {
|
if let Err(e) = create_file_if_not_exists(&cache_path) {
|
||||||
if let Err(e) = create_file_if_not_exists(cache_path) {
|
log::warn!("No drun cache file and cannot create: {e:?}");
|
||||||
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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,20 +30,20 @@ impl ItemProvider<i32> for RunProvider {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct RunProvider {
|
struct RunProvider {
|
||||||
items: Option<Vec<MenuItem<i32>>>,
|
items: Option<Vec<MenuItem<i32>>>,
|
||||||
cache_path: Option<PathBuf>,
|
cache_path: PathBuf,
|
||||||
cache: HashMap<String, i64>,
|
cache: HashMap<String, i64>,
|
||||||
sort_order: SortOrder,
|
sort_order: SortOrder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RunProvider {
|
impl RunProvider {
|
||||||
fn new(sort_order: SortOrder) -> Self {
|
fn new(config: &Config) -> Result<Self, Error> {
|
||||||
let (cache_path, d_run_cache) = load_run_cache();
|
let (cache_path, d_run_cache) = load_cache("worf-run", config)?;
|
||||||
RunProvider {
|
Ok(RunProvider {
|
||||||
items: None,
|
items: None,
|
||||||
cache_path,
|
cache_path,
|
||||||
cache: d_run_cache,
|
cache: d_run_cache,
|
||||||
sort_order,
|
sort_order: config.sort_order(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
@ -98,21 +98,14 @@ impl RunProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_run_cache() -> (Option<PathBuf>, HashMap<String, i64>) {
|
|
||||||
let cache_path = dirs::cache_dir().map(|x| x.join("worf-run"));
|
|
||||||
load_cache(cache_path)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_run_cache_and_run<T: Clone>(
|
fn update_run_cache_and_run<T: Clone>(
|
||||||
cache_path: Option<PathBuf>,
|
cache_path: &PathBuf,
|
||||||
cache: &mut HashMap<String, i64>,
|
cache: &mut HashMap<String, i64>,
|
||||||
selection_result: MenuItem<T>,
|
selection_result: MenuItem<T>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if let Some(cache_path) = cache_path {
|
*cache.entry(selection_result.label).or_insert(0) += 1;
|
||||||
*cache.entry(selection_result.label).or_insert(0) += 1;
|
if let Err(e) = save_cache_file(cache_path, cache) {
|
||||||
if let Err(e) = save_cache_file(&cache_path, cache) {
|
log::warn!("cannot save run cache {e:?}");
|
||||||
log::warn!("cannot save run cache {e:?}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(action) = selection_result.action {
|
if let Some(action) = selection_result.action {
|
||||||
|
@ -132,13 +125,12 @@ fn update_run_cache_and_run<T: Clone>(
|
||||||
///
|
///
|
||||||
/// Will return `Err` if it was not able to spawn the process
|
/// Will return `Err` if it was not able to spawn the process
|
||||||
pub fn show(config: &Config) -> Result<(), Error> {
|
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 cache_path = provider.cache_path.clone();
|
||||||
let mut cache = provider.cache.clone();
|
let mut cache = provider.cache.clone();
|
||||||
|
|
||||||
let selection_result = gui::show(config.clone(), provider, false, None, None);
|
let selection_result = gui::show(config.clone(), provider, false, None, None);
|
||||||
match selection_result {
|
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(_) => {
|
Err(_) => {
|
||||||
log::error!("No item selected");
|
log::error!("No item selected");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue