1use serde::{Deserialize, Serialize};
2use std::fs;
3use std::path::PathBuf;
4
5#[derive(Debug, Serialize, Deserialize, Default, Clone)]
9pub struct Config {
10 pub theme: Option<String>,
12 pub show_logo: Option<bool>,
14 pub ascii_only: Option<bool>,
16 pub fields: Option<Vec<String>>,
18 pub custom_theme: Option<CustomTheme>,
20}
21
22#[derive(Debug, Serialize, Deserialize, Default, Clone)]
26pub struct CustomTheme {
27 pub label_color: Option<String>,
29 pub value_color: Option<String>,
31 pub accent_color: Option<String>,
33 pub title_color: Option<String>,
35 pub separator_color: Option<String>,
37}
38
39impl Config {
40 pub fn load() -> anyhow::Result<Self> {
44 if let Some(path) = Self::config_path() {
45 if path.exists() {
46 let contents = fs::read_to_string(&path)?;
47 let config: Config = toml::from_str(&contents)?;
48 return Ok(config);
49 }
50 }
51 Ok(Self::default())
52 }
53
54 pub fn config_path() -> Option<PathBuf> {
56 dirs::config_dir().map(|mut p| {
57 p.push("retch");
58 p.push("config.toml");
59 p
60 })
61 }
62
63 pub fn merge_with_cli(&self, cli: &crate::cli::Cli) -> Self {
67 let mut merged = self.clone();
68
69 if let Some(theme) = &cli.theme {
70 merged.theme = Some(theme.clone());
71 }
72 if cli.no_logo {
73 merged.show_logo = Some(false);
74 }
75 if cli.ascii_only {
76 merged.ascii_only = Some(true);
77 }
78 if let Some(fields_str) = &cli.fields {
79 let fields = fields_str
81 .split(',')
82 .map(|s| s.trim().to_string())
83 .filter(|s| !s.is_empty())
84 .collect::<Vec<String>>();
85 merged.fields = Some(fields);
86 }
87
88 merged
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95 use crate::cli::Cli;
96 use clap::Parser;
97
98 #[test]
99 fn test_config_merge_with_cli() {
100 let config = Config {
101 theme: Some("dark".to_string()),
102 show_logo: Some(true),
103 ascii_only: Some(false),
104 fields: Some(vec!["os".to_string(), "kernel".to_string()]),
105 ..Default::default()
106 };
107
108 let cli = Cli::try_parse_from(&["retch", "--theme", "light"]).unwrap();
110 let merged = config.merge_with_cli(&cli);
111 assert_eq!(merged.theme, Some("light".to_string()));
112
113 let cli = Cli::try_parse_from(&["retch", "--no-logo"]).unwrap();
115 let merged = config.merge_with_cli(&cli);
116 assert_eq!(merged.show_logo, Some(false));
117
118 let cli = Cli::try_parse_from(&["retch", "--ascii-only"]).unwrap();
120 let merged = config.merge_with_cli(&cli);
121 assert_eq!(merged.ascii_only, Some(true));
122
123 let cli = Cli::try_parse_from(&["retch", "--fields", "cpu,gpu,memory"]).unwrap();
125 let merged = config.merge_with_cli(&cli);
126 assert_eq!(
127 merged.fields,
128 Some(vec![
129 "cpu".to_string(),
130 "gpu".to_string(),
131 "memory".to_string()
132 ])
133 );
134 }
135}