Skip to main content

retch_cli/
config.rs

1use serde::{Deserialize, Serialize};
2use std::fs;
3use std::path::PathBuf;
4
5#[derive(Debug, Serialize, Deserialize, Default, Clone)]
6pub struct Config {
7    pub theme: Option<String>,
8    pub show_logo: Option<bool>,
9    pub ascii_only: Option<bool>,
10    pub fields: Option<Vec<String>>,
11    /// Custom theme color overrides
12    pub custom_theme: Option<CustomTheme>,
13}
14
15#[derive(Debug, Serialize, Deserialize, Default, Clone)]
16pub struct CustomTheme {
17    pub label_color: Option<String>,
18    pub value_color: Option<String>,
19    pub accent_color: Option<String>,
20    pub title_color: Option<String>,
21    pub separator_color: Option<String>,
22}
23
24impl Config {
25    pub fn load() -> anyhow::Result<Self> {
26        if let Some(path) = Self::config_path() {
27            if path.exists() {
28                let contents = fs::read_to_string(&path)?;
29                let config: Config = toml::from_str(&contents)?;
30                return Ok(config);
31            }
32        }
33        Ok(Self::default())
34    }
35
36    pub fn config_path() -> Option<PathBuf> {
37        dirs::config_dir().map(|mut p| {
38            p.push("retch");
39            p.push("config.toml");
40            p
41        })
42    }
43
44    /// Merge CLI options over config (CLI takes precedence)
45    pub fn merge_with_cli(&self, cli: &crate::cli::Cli) -> Self {
46        let mut merged = self.clone();
47
48        if let Some(theme) = &cli.theme {
49            merged.theme = Some(theme.clone());
50        }
51        if cli.no_logo {
52            merged.show_logo = Some(false);
53        }
54        if cli.ascii_only {
55            merged.ascii_only = Some(true);
56        }
57        if let Some(fields) = &cli.fields {
58            merged.fields = Some(fields.clone());
59        }
60
61        merged
62    }
63}