tempo_cli/utils/
config.rs

1use crate::models::Config;
2use anyhow::Result;
3use std::path::PathBuf;
4
5pub fn get_config_dir() -> Result<PathBuf> {
6    let config_dir = dirs::config_dir()
7        .or_else(|| dirs::home_dir())
8        .ok_or_else(|| anyhow::anyhow!("Could not determine config directory"))?;
9    
10    let tempo_dir = config_dir.join(".tempo");
11    std::fs::create_dir_all(&tempo_dir)?;
12    
13    Ok(tempo_dir)
14}
15
16pub fn get_config_path() -> Result<PathBuf> {
17    Ok(get_config_dir()?.join("config.toml"))
18}
19
20pub fn load_config() -> Result<Config> {
21    let config_path = get_config_path()?;
22    
23    if config_path.exists() {
24        let contents = std::fs::read_to_string(&config_path)?;
25        let config: Config = toml::from_str(&contents)
26            .map_err(|e| anyhow::anyhow!("Failed to parse config file: {}. Please check the file format.", e))?;
27        
28        config.validate()?;
29        Ok(config)
30    } else {
31        let default_config = Config::default();
32        save_config(&default_config)?;
33        Ok(default_config)
34    }
35}
36
37pub fn save_config(config: &Config) -> Result<()> {
38    config.validate()?;
39    
40    let config_path = get_config_path()?;
41    let mut contents = toml::to_string_pretty(config)?;
42    
43    // Remove empty [custom_settings] section if it was written (handle various formats)
44    if config.custom_settings.is_empty() {
45        // Remove standalone [custom_settings] line
46        contents = contents.replace("[custom_settings]\n", "");
47        contents = contents.replace("\n[custom_settings]", "");
48        // Remove [custom_settings] at the end of file
49        contents = contents.replace("\n[custom_settings]", "");
50        // Clean up any double newlines
51        contents = contents.replace("\n\n\n", "\n\n");
52    }
53    
54    std::fs::write(&config_path, contents.trim_end().to_string() + "\n")?;
55    
56    Ok(())
57}