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).map_err(|e| {
26            anyhow::anyhow!(
27                "Failed to parse config file: {}. Please check the file format.",
28                e
29            )
30        })?;
31
32        config.validate()?;
33        Ok(config)
34    } else {
35        let default_config = Config::default();
36        save_config(&default_config)?;
37        Ok(default_config)
38    }
39}
40
41pub fn save_config(config: &Config) -> Result<()> {
42    config.validate()?;
43
44    let config_path = get_config_path()?;
45    let mut contents = toml::to_string_pretty(config)?;
46
47    // Remove empty [custom_settings] section if it was written (handle various formats)
48    if config.custom_settings.is_empty() {
49        // Remove standalone [custom_settings] line
50        contents = contents.replace("[custom_settings]\n", "");
51        contents = contents.replace("\n[custom_settings]", "");
52        // Remove [custom_settings] at the end of file
53        contents = contents.replace("\n[custom_settings]", "");
54        // Clean up any double newlines
55        contents = contents.replace("\n\n\n", "\n\n");
56    }
57
58    std::fs::write(&config_path, contents.trim_end().to_string() + "\n")?;
59
60    Ok(())
61}