1use std::env;
2use std::fs;
3use std::path::PathBuf;
4
5#[derive(Debug, Clone, Copy, Default)]
6pub struct AppConfig {
7 pub uppercase: bool,
8}
9
10impl AppConfig {
11 pub fn load() -> Self {
12 let Some(path) = config_path() else {
13 return Self::default();
14 };
15
16 let Ok(contents) = fs::read_to_string(path) else {
17 return Self::default();
18 };
19
20 parse_config_contents(&contents)
21 }
22}
23
24fn config_path() -> Option<PathBuf> {
25 if let Ok(config_home) = env::var("XDG_CONFIG_HOME") {
26 return Some(PathBuf::from(config_home).join("git-quick-add").join("config.toml"));
27 }
28
29 env::var("HOME")
30 .ok()
31 .map(|home| PathBuf::from(home).join(".config").join("git-quick-add").join("config.toml"))
32}
33
34fn parse_config_contents(contents: &str) -> AppConfig {
35 let mut config = AppConfig::default();
36
37 for raw_line in contents.lines() {
38 let line = raw_line.split('#').next().unwrap_or("").trim();
39 if line.is_empty() {
40 continue;
41 }
42
43 let Some((key, value)) = line.split_once('=') else {
44 continue;
45 };
46
47 if key.trim() != "uppercase" {
48 continue;
49 }
50
51 match value.trim() {
52 "true" => config.uppercase = true,
53 "false" => config.uppercase = false,
54 _ => {}
55 }
56 }
57
58 config
59}
60
61#[cfg(test)]
62mod tests {
63 use super::{AppConfig, parse_config_contents};
64
65 #[test]
66 fn defaults_to_false_when_missing() {
67 assert!(!parse_config_contents("").uppercase);
68 }
69
70 #[test]
71 fn parses_uppercase_true() {
72 assert!(parse_config_contents("uppercase = true").uppercase);
73 }
74
75 #[test]
76 fn ignores_comments_and_whitespace() {
77 let config = parse_config_contents(" uppercase = true # enable uppercase");
78 assert_eq!(config.uppercase, AppConfig { uppercase: true }.uppercase);
79 }
80}