leenfetch_core/config/
mod.rs1pub mod defaults;
2pub mod settings;
3
4use self::{
5 defaults::DEFAULT_CONFIG,
6 settings::{Config, Flags, LayoutItem},
7};
8use dirs::config_dir;
9use json5;
10use once_cell::sync::Lazy;
11use std::io::Write;
12use std::path::PathBuf;
13use std::{
14 collections::HashMap,
15 fs::{self, File},
16};
17
18static DEFAULT_CONFIG_CACHE: Lazy<Config> = Lazy::new(|| {
19 json5::from_str(DEFAULT_CONFIG).unwrap_or_else(|e| panic!("Built-in default config is invalid JSON: {e}"))
20});
21
22fn load_config() -> Result<Config, String> {
24 let path = config_file("config.jsonc");
25 let data = fs::read_to_string(&path)
26 .map_err(|e| format!("Failed to read config.jsonc ({}): {}", path.display(), e))?;
27 load_config_from_str(&data)
28}
29
30fn load_config_from_str(data: &str) -> Result<Config, String> {
31 json5::from_str(data).map_err(|e| format!("Invalid JSONC in config.jsonc: {}", e))
32}
33
34pub fn load_config_at(path: Option<&str>) -> Result<Config, String> {
36 match path {
37 Some(custom_path) => {
38 let data = fs::read_to_string(custom_path)
39 .map_err(|err| format!("Failed to read config at {}: {}", custom_path, err))?;
40 load_config_from_str(&data)
41 }
42 None => load_config(),
43 }
44}
45
46pub fn default_config() -> Config {
48 DEFAULT_CONFIG_CACHE.clone()
49}
50
51pub fn default_layout() -> Vec<LayoutItem> {
53 default_config().layout
54}
55
56pub fn load_print_layout() -> Vec<LayoutItem> {
62 let layout = load_config().unwrap_or_else(|e| {
63 eprintln!("leenfetch: config error: {e}; using defaults");
64 default_config()
65 }).layout;
66 if layout.is_empty() {
67 default_layout()
68 } else {
69 layout
70 }
71}
72
73pub fn load_flags() -> Flags {
79 load_config().unwrap_or_else(|e| {
80 eprintln!("leenfetch: config error: {e}; using defaults");
81 default_config()
82 }).flags
83}
84
85pub fn generate_config_files() -> HashMap<String, bool> {
90 let mut results = HashMap::new();
91
92 let result = save_to_config_file("config.jsonc", DEFAULT_CONFIG).is_ok();
93 results.insert("config.jsonc".to_string(), result);
94
95 results
96}
97
98fn save_to_config_file(file_name: &str, content: &str) -> std::io::Result<()> {
115 let path = config_file(file_name);
116
117 if let Some(parent) = path.parent() {
118 fs::create_dir_all(parent)?;
119 }
120
121 let mut file = File::create(&path)?;
122 file.write_all(content.as_bytes())?;
123
124 Ok(())
125}
126
127pub fn delete_config_files() -> HashMap<String, bool> {
133 let mut results = HashMap::new();
134
135 let file = "config.jsonc";
136 let result = delete_config_file(file).is_ok();
137 results.insert(file.to_string(), result);
138
139 results
140}
141
142fn delete_config_file(file_name: &str) -> std::io::Result<()> {
147 let path = config_file(file_name);
148
149 if path.exists() {
150 std::fs::remove_file(path)?;
151 }
152
153 Ok(())
154}
155
156fn config_file(name: &str) -> PathBuf {
163 config_dir()
164 .unwrap_or_else(|| PathBuf::from("."))
165 .join("leenfetch")
166 .join(name)
167}
168
169pub fn ensure_config_files_exist() -> HashMap<String, bool> {
177 let mut results = HashMap::new();
178
179 let filename = "config.jsonc";
180 let created = ensure_config_file_exists(filename, DEFAULT_CONFIG).unwrap_or(false);
181 results.insert(filename.to_string(), created);
182
183 results
184}
185
186fn ensure_config_file_exists(file_name: &str, default_content: &str) -> std::io::Result<bool> {
196 let path = config_file(file_name);
197
198 if path.exists() {
199 return Ok(false); }
201
202 save_to_config_file(file_name, default_content)?;
203 Ok(true) }