Skip to main content

lean_ctx/core/
config.rs

1use serde::{Deserialize, Serialize};
2use std::path::PathBuf;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5#[serde(default)]
6pub struct Config {
7    pub ultra_compact: bool,
8    pub tee_on_error: bool,
9    pub checkpoint_interval: u32,
10    pub excluded_commands: Vec<String>,
11    pub custom_aliases: Vec<AliasEntry>,
12    /// Commands taking longer than this threshold (ms) are recorded in the slow log.
13    /// Set to 0 to disable slow logging.
14    pub slow_command_threshold_ms: u64,
15    #[serde(default = "default_theme")]
16    pub theme: String,
17    #[serde(default)]
18    pub cloud: CloudConfig,
19}
20
21fn default_theme() -> String {
22    "default".to_string()
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, Default)]
26#[serde(default)]
27pub struct CloudConfig {
28    pub contribute_enabled: bool,
29    pub last_contribute: Option<String>,
30    pub last_sync: Option<String>,
31    pub last_model_pull: Option<String>,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct AliasEntry {
36    pub command: String,
37    pub alias: String,
38}
39
40impl Default for Config {
41    fn default() -> Self {
42        Self {
43            ultra_compact: false,
44            tee_on_error: false,
45            checkpoint_interval: 15,
46            excluded_commands: Vec::new(),
47            custom_aliases: Vec::new(),
48            slow_command_threshold_ms: 5000,
49            theme: default_theme(),
50            cloud: CloudConfig::default(),
51        }
52    }
53}
54
55impl Config {
56    pub fn path() -> Option<PathBuf> {
57        dirs::home_dir().map(|h| h.join(".lean-ctx").join("config.toml"))
58    }
59
60    pub fn load() -> Self {
61        let path = match Self::path() {
62            Some(p) => p,
63            None => return Self::default(),
64        };
65        match std::fs::read_to_string(&path) {
66            Ok(content) => toml::from_str(&content).unwrap_or_default(),
67            Err(_) => Self::default(),
68        }
69    }
70
71    pub fn save(&self) -> Result<(), String> {
72        let path = Self::path().ok_or("cannot determine home directory")?;
73        if let Some(parent) = path.parent() {
74            std::fs::create_dir_all(parent).map_err(|e| e.to_string())?;
75        }
76        let content = toml::to_string_pretty(self).map_err(|e| e.to_string())?;
77        std::fs::write(&path, content).map_err(|e| e.to_string())
78    }
79
80    pub fn show(&self) -> String {
81        let path = Self::path()
82            .map(|p| p.to_string_lossy().to_string())
83            .unwrap_or_else(|| "~/.lean-ctx/config.toml".to_string());
84        let content = toml::to_string_pretty(self).unwrap_or_default();
85        format!("Config: {path}\n\n{content}")
86    }
87}