lx_cli/
config.rs

1use colored::Color;
2use serde::Deserialize;
3use std::fs;
4use std::path::PathBuf;
5
6#[derive(Debug, Deserialize, Clone, Default)]
7pub struct Config {
8    #[serde(default)]
9    pub colors: ColorConfig,
10    #[serde(default)]
11    pub icons: IconConfig,
12    #[serde(default)]
13    pub display: DisplayConfig,
14}
15
16#[derive(Debug, Deserialize, Clone)]
17pub struct ColorConfig {
18    #[serde(default = "default_directory_color")]
19    pub directory: String,
20    #[serde(default = "default_executable_color")]
21    pub executable: String,
22    #[serde(default = "default_regular_color")]
23    pub regular: String,
24}
25
26#[derive(Debug, Deserialize, Clone)]
27pub struct IconConfig {
28    #[serde(default = "default_directory_icon")]
29    pub directory: String,
30    #[serde(default = "default_executable_icon")]
31    pub executable: String,
32    #[serde(default = "default_regular_icon")]
33    pub regular: String,
34    #[serde(default)]
35    pub colors: IconColorConfig,
36}
37
38#[derive(Debug, Deserialize, Clone)]
39pub struct IconColorConfig {
40    #[serde(default = "default_directory_icon_color")]
41    pub directory: String,
42    #[serde(default = "default_executable_icon_color")]
43    pub executable: String,
44    #[serde(default = "default_regular_icon_color")]
45    pub regular: String,
46}
47
48#[derive(Debug, Deserialize, Clone)]
49pub struct DisplayConfig {
50    #[serde(default = "default_column_spacing")]
51    pub column_spacing: usize,
52    #[serde(default = "default_max_rows")]
53    pub max_rows: usize,
54    #[serde(default)]
55    pub tree: TreeConfig,
56}
57
58#[derive(Debug, Deserialize, Clone)]
59pub struct TreeConfig {
60    #[serde(default = "default_tree_style")]
61    pub style: String,
62}
63
64impl Default for TreeConfig {
65    fn default() -> Self {
66        TreeConfig {
67            style: default_tree_style(),
68        }
69    }
70}
71
72impl Default for IconConfig {
73    fn default() -> Self {
74        IconConfig {
75            directory: default_directory_icon(),
76            executable: default_executable_icon(),
77            regular: default_regular_icon(),
78            colors: IconColorConfig::default(),
79        }
80    }
81}
82
83impl Default for IconColorConfig {
84    fn default() -> Self {
85        IconColorConfig {
86            directory: default_directory_icon_color(),
87            executable: default_executable_icon_color(),
88            regular: default_regular_icon_color(),
89        }
90    }
91}
92
93impl Default for ColorConfig {
94    fn default() -> Self {
95        ColorConfig {
96            directory: default_directory_color(),
97            executable: default_executable_color(),
98            regular: default_regular_color(),
99        }
100    }
101}
102
103impl Default for DisplayConfig {
104    fn default() -> Self {
105        DisplayConfig {
106            column_spacing: default_column_spacing(),
107            max_rows: default_max_rows(),
108            tree: TreeConfig::default(),
109        }
110    }
111}
112
113fn default_directory_color() -> String {
114    "blue".to_string()
115}
116
117fn default_executable_color() -> String {
118    "green".to_string()
119}
120
121fn default_regular_color() -> String {
122    "white".to_string()
123}
124
125fn default_column_spacing() -> usize {
126    2
127}
128
129fn default_max_rows() -> usize {
130    0 // 0 means no limit
131}
132
133fn default_tree_style() -> String {
134    "ascii".to_string()
135}
136
137fn default_directory_icon() -> String {
138    "".to_string()
139}
140
141fn default_executable_icon() -> String {
142    "".to_string()
143}
144
145fn default_regular_icon() -> String {
146    "".to_string()
147}
148
149fn default_directory_icon_color() -> String {
150    "blue".to_string()
151}
152
153fn default_executable_icon_color() -> String {
154    "green".to_string()
155}
156
157fn default_regular_icon_color() -> String {
158    "white".to_string()
159}
160
161impl ColorConfig {
162    pub fn get_directory_color(&self) -> Color {
163        parse_color(&self.directory)
164    }
165
166    pub fn get_executable_color(&self) -> Color {
167        parse_color(&self.executable)
168    }
169
170    pub fn get_regular_color(&self) -> Color {
171        parse_color(&self.regular)
172    }
173}
174
175impl IconColorConfig {
176    pub fn get_directory_color(&self) -> Color {
177        parse_color(&self.directory)
178    }
179
180    pub fn get_executable_color(&self) -> Color {
181        parse_color(&self.executable)
182    }
183
184    pub fn get_regular_color(&self) -> Color {
185        parse_color(&self.regular)
186    }
187}
188
189impl IconConfig {
190    pub fn get_directory_icon(&self) -> String {
191        self.directory.clone()
192    }
193
194    pub fn get_executable_icon(&self) -> String {
195        self.executable.clone()
196    }
197
198    pub fn get_regular_icon(&self) -> String {
199        self.regular.clone()
200    }
201}
202
203fn parse_color(color_str: &str) -> Color {
204    match color_str.to_lowercase().as_str() {
205        "black" => Color::Black,
206        "red" => Color::Red,
207        "green" => Color::Green,
208        "yellow" => Color::Yellow,
209        "blue" => Color::Blue,
210        "magenta" => Color::Magenta,
211        "cyan" => Color::Cyan,
212        "white" => Color::White,
213        "bright_black" => Color::BrightBlack,
214        "bright_red" => Color::BrightRed,
215        "bright_green" => Color::BrightGreen,
216        "bright_yellow" => Color::BrightYellow,
217        "bright_blue" => Color::BrightBlue,
218        "bright_magenta" => Color::BrightMagenta,
219        "bright_cyan" => Color::BrightCyan,
220        "bright_white" => Color::BrightWhite,
221        _ => Color::White, // Default fallback
222    }
223}
224
225pub fn load_config() -> Config {
226    let config_path = get_config_path();
227
228    if !config_path.exists() {
229        return Config::default();
230    }
231
232    match fs::read_to_string(&config_path) {
233        Ok(contents) => match toml::from_str(&contents) {
234            Ok(config) => config,
235            Err(e) => {
236                eprintln!("Warning: Failed to parse config file: {}", e);
237                Config::default()
238            }
239        },
240        Err(_) => Config::default(),
241    }
242}
243
244fn get_config_path() -> PathBuf {
245    let mut path = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
246    path.push(".config");
247    path.push("lx");
248    path.push("config");
249    path
250}