use crate::{Error, Result}; use figment::{providers::Serialized, value, Figment, Metadata, Profile, Provider}; use serde::{Deserialize, Serialize}; use std::{fs::File, path::PathBuf, sync::Arc}; use tracing_subscriber::{Layer, Registry}; #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Config { pub log_enabled: bool, pub log_file: PathBuf, pub paths: crate::directories::Config, pub finder: crate::finder::Config, } impl Config { pub fn from(provider: T) -> figment::error::Result { Figment::from(provider).extract() } pub fn as_layer(&self) -> Result + Send + Sync>>> { let mut layers = Vec::new(); if self.log_enabled { let file = File::create(&self.log_file)?; let log_layer = tracing_subscriber::fmt::layer() .with_writer(Arc::new(file)) .boxed(); layers.push(log_layer); }; Ok(layers) } } impl Default for Config { fn default() -> Self { Self { paths: Default::default(), finder: Default::default(), log_enabled: Default::default(), log_file: dirs::cache_dir() .map(|p| p.join("tmuxr")) .unwrap_or_default() .join("tmuxr.log"), } } } impl Provider for Config { fn metadata(&self) -> Metadata { Metadata::named("Tmuxr directory config") } fn data(&self) -> figment::error::Result> { Serialized::defaults(Config::default()).data() } } impl TryFrom for Config { type Error = Error; fn try_from(value: Figment) -> Result { value.extract().map_err(Into::into) } } #[cfg(test)] mod tests { use crate::{finder, directories}; use super::*; use figment::providers::{Format, Serialized, Toml}; #[test] fn defaults() { figment::Jail::expect_with(|jail| { jail.create_file( "tmuxr.toml", r#" log_enabled = false [paths] search = [] add = [] hidden = false [finder] program = "fzf-tmux" args = [ "--", "--multi", "--print-query", "-d/", "--preview-window='right,75%,<80(up,75%,border-bottom)'", "--preview='sel={}; less ${sel:-{q}} 2>/dev/null'", ] "#, )?; let config: Config = Figment::from(Serialized::defaults(Config::default())) .merge(Toml::file("tmuxr.toml")) .extract()?; assert_eq!(config, Config::default()); Ok(()) }); } #[test] fn custom() { figment::Jail::expect_with(|jail| { jail.create_file( "tmuxr.toml", r#" log_enabled = true log_file = "/tmp/tmuxr/test/tmuxr.log" [paths] search = [ "/tmp/tmuxr/test/projects" ] add = [ "/tmp/tmuxr/test/other_projects" ] hidden = true [finder] program = "fzf" args = ["-0", "-1", "--preview='cat'"] "#, )?; let config: Config = Figment::from(Serialized::defaults(Config::default())) .merge(Toml::file("tmuxr.toml")) .extract()?; assert_eq!( config, Config { paths: directories::Config { search: vec!["/tmp/tmuxr/test/projects".into()], add: vec!["/tmp/tmuxr/test/extra_project".into()], hidden: true, }, finder: finder::Config { program: "fzf".into(), args: vec!["-0".into(), "-1".into(), "--preview='cat'".into()], }, log_enabled: true, log_file: "/tmp/tmuxr/test/tmuxr.log".into() } ); Ok(()) }); } }