diff --git a/README.md b/README.md index 552bbf9..ae6444c 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,13 @@ $ ./aliveline ## Configuration Aliveline tries to find config at: -- `$XDG_CONFIG_DIR/aliveline/config.toml` +- `$ALIVELINE_CONFIG` +- `$XDG_CONFIG_HOME/aliveline/config.toml` +- `$XDG_CONFIG_HOME/.aliveline` +- `$HOME/.config/aliveline/config.toml` +- `$HOME/.config/.aliveline` +- `$HOME/.aliveline/config.toml` +- `$HOME/.aliveline` - `./config.toml` (relative to working directory) If config isn't found, Aliveline uses default values defined in [config.toml](https://2ndbeam.ru/git/2ndbeam/aliveline/src/branch/master/config.toml). diff --git a/src/config.rs b/src/config.rs index 17eba1d..22ce814 100644 --- a/src/config.rs +++ b/src/config.rs @@ -20,14 +20,16 @@ impl Default for Colors { } #[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)] -#[serde(default)] pub struct Config { /// directory, where config is located #[serde(skip)] pub conf_path: PathBuf, pub log_path: PathBuf, + #[serde(default)] pub colors: Colors, + #[serde(default)] pub event_colors: Vec, + #[serde(default)] pub text_colors: Vec, } @@ -90,13 +92,13 @@ impl Config { } } - pub fn load(path: PathBuf) -> Self { + pub fn load(path: PathBuf) -> Option { if let Ok(toml_string) = std::fs::read_to_string(path.clone()) { if let Ok(mut conf) = toml::from_str::(&toml_string) { conf.conf_path = path.parent().unwrap().into(); - return conf; + return Some(conf); } } - Config::new(path) + None } } diff --git a/src/lib.rs b/src/lib.rs index 7eb4df8..df9b81e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,16 +4,47 @@ use std::{hash::{DefaultHasher, Hash, Hasher}, path::PathBuf}; pub mod config; pub mod log; -pub fn load_config() -> Config { - if let Ok(path_str) = std::env::var("XDG_CONFIG_HOME") { - let mut path = PathBuf::from(path_str); - path.push("aliveline"); - path.push("config.toml"); - return Config::load(path); +fn try_config_path(var: &'static str, path: &[&'static str]) -> Option { + match std::env::var(var) { + Ok(path_start) => { + let mut pathbuf = PathBuf::from(path_start); + for entry in path.iter() { + pathbuf.push(entry); + } + Config::load(pathbuf) + }, + Err(_) => None, } - Config::new(PathBuf::from("./config.toml")) } +/// This function tries to load config from several places (in order): +/// - $ALIVELINE_CONFIG +/// - $XDG_CONFIG_HOME/aliveline/config.toml +/// - $XDG_CONFIG_HOME/.aliveline +/// - $HOME/.config/aliveline/config.toml +/// - $HOME/.config/.aliveline +/// - $HOME/.aliveline +/// as a last resort it defaults to current working directory (./config.toml) +pub fn load_config() -> Config { + let places = [ + ("ALIVELINE_CONFIG", vec![]), + ("XDG_CONFIG_HOME", vec!["aliveline", "config.toml"]), + ("XDG_CONFIG_HOME", vec![".aliveline"]), + ("HOME", vec![".config", "aliveline", "config.toml"]), + ("HOME", vec![".config", ".aliveline"]), + ("HOME", vec![".aliveline", "config.toml"]), + ("HOME", vec![".aliveline"]), + ]; + for (place_var, place) in places { + if let Some(conf) = try_config_path(place_var, place.as_slice()) { + println!("Found config at ${place_var} / {place:?}"); + return conf; + } + println!("Config not found at ${place_var} / {place:?}"); + } + println!("Using last resort config path ./config.toml"); + Config::new(PathBuf::from("./config.toml")) +} /// Get random-like color id in range 0..16 by computing string hash pub fn color_id_from_name(name: String) -> i32 { let mut s = DefaultHasher::new();