use crate::theme::model::ThemeName;
use anyhow::{Context, Result};
use serde::Deserialize;
use std::path::PathBuf;
pub const THEME_FILE_NAME: &str = ".colorantrc";
#[derive(Debug, Clone, Deserialize)]
#[serde(default)]
pub struct Config {
pub base_theme_dir: PathBuf,
pub default_theme: Option<ThemeName>,
}
impl Default for Config {
fn default() -> Self {
let base_theme_dir = config_dir()
.map(|p| p.join("themes"))
.unwrap_or_else(|| PathBuf::from(".colorant/themes"));
Self {
base_theme_dir,
default_theme: None,
}
}
}
impl Config {
pub fn load() -> Result<Self> {
let Some(dir) = config_dir() else {
return Ok(Self::default());
};
let path = dir.join("config.toml");
if !path.exists() {
return Ok(Self::default());
}
let content = std::fs::read_to_string(&path)
.with_context(|| format!("reading {}", path.display()))?;
let cfg: Config =
toml::from_str(&content).with_context(|| format!("parsing {}", path.display()))?;
Ok(cfg)
}
}
fn config_dir() -> Option<PathBuf> {
if let Ok(xdg) = std::env::var("XDG_CONFIG_HOME")
&& !xdg.is_empty()
{
return Some(PathBuf::from(xdg).join("colorant"));
}
dirs::home_dir().map(|h| h.join(".config").join("colorant"))
}
pub fn cache_dir() -> Option<PathBuf> {
cache_dir_for(std::env::var("XDG_CACHE_HOME").ok(), dirs::home_dir())
}
fn cache_dir_for(xdg: Option<String>, home: Option<PathBuf>) -> Option<PathBuf> {
if let Some(xdg) = xdg
&& !xdg.is_empty()
{
return Some(PathBuf::from(xdg).join("colorant"));
}
home.map(|h| h.join(".cache").join("colorant"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cache_dir_uses_xdg_when_set() {
let xdg = Some("/tmp/xdg".to_string());
let home = Some(PathBuf::from("/home/me"));
assert_eq!(
cache_dir_for(xdg, home),
Some(PathBuf::from("/tmp/xdg/colorant"))
);
}
#[test]
fn cache_dir_falls_back_when_xdg_empty() {
let xdg = Some(String::new());
let home = Some(PathBuf::from("/home/me"));
assert_eq!(
cache_dir_for(xdg, home),
Some(PathBuf::from("/home/me/.cache/colorant"))
);
}
#[test]
fn cache_dir_falls_back_when_xdg_unset() {
let home = Some(PathBuf::from("/home/me"));
assert_eq!(
cache_dir_for(None, home),
Some(PathBuf::from("/home/me/.cache/colorant"))
);
}
#[test]
fn cache_dir_returns_none_when_no_home_and_no_xdg() {
assert_eq!(cache_dir_for(None, None), None);
assert_eq!(cache_dir_for(Some(String::new()), None), None);
}
}