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