use anyhow::{Context, Result, anyhow};
use serde::Deserialize;
use std::path::PathBuf;
#[derive(Debug, Default, Deserialize)]
#[serde(default)]
pub struct Config {
pub format: Option<crate::ByteFormat>,
pub keys: KeysConfig,
}
#[derive(Debug, Deserialize)]
#[serde(default)]
pub struct KeysConfig {
#[serde(default = "default_esc_navigates_back")]
pub esc_navigates_back: bool,
}
fn default_esc_navigates_back() -> bool {
true
}
impl Default for KeysConfig {
fn default() -> Self {
Self {
esc_navigates_back: default_esc_navigates_back(),
}
}
}
impl Config {
pub fn load() -> Result<Self> {
let Ok(path) = Self::path() else {
log::info!("Configuration path couldn't be determined. Using defaults.");
return Ok(Config::default());
};
let contents = match std::fs::read_to_string(&path) {
Ok(c) => c,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
log::info!(
"Configuration not loaded from {}: file not found. Using defaults.",
path.display()
);
return Ok(Config::default());
}
Err(e) => {
return Err(e)
.with_context(|| format!("Failed to read config at {}", path.display()));
}
};
toml::from_str(&contents)
.with_context(|| format!("Failed to parse config at {}", path.display()))
}
pub fn default_file_content() -> &'static str {
concat!(
"# dua-cli configuration\n",
"#\n",
"# Byte count format to use when --format and DUA_FORMAT are not set.\n",
"# Supported values: metric, binary, bytes, gb, gib, mb, mib.\n",
"# format = \"binary\"\n",
"#\n",
"[keys]\n",
"# If true, pressing <Esc> in the main pane ascends to the parent directory.\n",
"# If false, <Esc> follows the default quit behavior.\n",
"esc_navigates_back = true\n",
)
}
pub fn path() -> Result<PathBuf> {
let config_dir = dirs::config_dir()
.ok_or_else(|| anyhow!("platform config directory is unavailable"))?;
Ok(config_dir.join("dua-cli").join("config.toml"))
}
}
#[cfg(test)]
mod tests {
use super::Config;
#[test]
fn parses_configured_byte_format() {
let config: Config = toml::from_str(
r#"
format = "mb"
[keys]
esc_navigates_back = false
"#,
)
.expect("valid config");
assert_eq!(config.format, Some(crate::ByteFormat::MB));
assert!(!config.keys.esc_navigates_back);
}
}