use clap::Parser; use self::{ cli::Args, config_file::{find_config_file, Configs}, }; mod cli; mod config_file; /// this struct may hold all configuration pub struct Config { pub startup_msg: bool, } impl Config { pub fn read() -> Self { let args = Args::parse(); let config_path = if let Some(config_path) = args.config_path { Ok(config_path) } else { find_config_file() }; let file_config = if let Ok(config_path) = config_path { let file_config = Configs::read(config_path); match file_config { Ok(c) => Some(c), Err(e) => { eprintln!("Config error: {e:?}"); eprintln!("Proceeding with defaults or cli args..."); None } } } else { None }; if let Some(file_config) = file_config { Self { // this is negated because to an outward api, the negative is more intuitive, // while in the source the other way around is more intuitive startup_msg: !(args.no_startup_message || file_config.no_startup_message), } } else { Self { startup_msg: !args.no_startup_message, } } } } pub mod error { #[derive(Debug)] pub enum ConfigError { NoConfigDir, NoConfigFileFound, IoError(std::io::Error), UnknownExtension(Option), SerdeJsonError(serde_json::Error), SerdeRonError(ron::error::SpannedError), } impl From for ConfigError { fn from(value: std::io::Error) -> Self { Self::IoError(value) } } impl From for ConfigError { fn from(value: serde_json::Error) -> Self { Self::SerdeJsonError(value) } } impl From for ConfigError { fn from(value: ron::error::SpannedError) -> Self { Self::SerdeRonError(value) } } }