Skip to main content

ck_tui/
config.rs

1use anyhow::Result;
2use ck_core::SearchMode;
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use std::path::PathBuf;
5
6#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
7pub enum PreviewMode {
8    Heatmap, // Semantic similarity coloring
9    Syntax,  // Syntax highlighting
10    Chunks,  // Show chunk boundaries
11}
12
13#[derive(Serialize, Deserialize)]
14pub struct TuiConfig {
15    #[serde(with = "search_mode_serde")]
16    pub search_mode: SearchMode,
17    pub preview_mode: PreviewMode,
18    pub full_file_mode: bool,
19}
20
21mod search_mode_serde {
22    use super::*;
23
24    pub fn serialize<S>(mode: &SearchMode, serializer: S) -> Result<S::Ok, S::Error>
25    where
26        S: Serializer,
27    {
28        let s = match mode {
29            SearchMode::Semantic => "semantic",
30            SearchMode::Regex => "regex",
31            SearchMode::Hybrid => "hybrid",
32            SearchMode::Lexical => "lexical",
33        };
34        serializer.serialize_str(s)
35    }
36
37    pub fn deserialize<'de, D>(deserializer: D) -> Result<SearchMode, D::Error>
38    where
39        D: Deserializer<'de>,
40    {
41        let s = String::deserialize(deserializer)?;
42        Ok(match s.as_str() {
43            "semantic" => SearchMode::Semantic,
44            "regex" => SearchMode::Regex,
45            "hybrid" => SearchMode::Hybrid,
46            "lexical" => SearchMode::Lexical,
47            _ => SearchMode::Semantic, // Default fallback
48        })
49    }
50}
51
52impl Default for TuiConfig {
53    fn default() -> Self {
54        Self {
55            search_mode: SearchMode::Semantic,
56            preview_mode: PreviewMode::Heatmap,
57            full_file_mode: true,
58        }
59    }
60}
61
62impl TuiConfig {
63    pub fn load() -> Self {
64        let config_path = Self::config_path();
65        if let Ok(contents) = std::fs::read_to_string(&config_path) {
66            serde_json::from_str(&contents).unwrap_or_default()
67        } else {
68            Self::default()
69        }
70    }
71
72    pub fn save(&self) -> Result<()> {
73        let config_path = Self::config_path();
74        if let Some(parent) = config_path.parent() {
75            std::fs::create_dir_all(parent)?;
76        }
77        let contents = serde_json::to_string_pretty(self)?;
78        std::fs::write(&config_path, contents)?;
79        Ok(())
80    }
81
82    fn config_path() -> PathBuf {
83        if let Some(config_dir) = dirs::config_dir() {
84            config_dir.join("ck").join("tui.json")
85        } else {
86            PathBuf::from(".ck_tui.json")
87        }
88    }
89}