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