lx_cli/
config.rs

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 display: DisplayConfig,
12}
13
14#[derive(Debug, Deserialize, Clone)]
15pub struct ColorConfig {
16    #[serde(default = "default_directory_color")]
17    pub directory: String,
18    #[serde(default = "default_executable_color")]
19    pub executable: String,
20    #[serde(default = "default_regular_color")]
21    pub regular: String,
22}
23
24#[derive(Debug, Deserialize, Clone)]
25pub struct DisplayConfig {
26    #[serde(default = "default_column_spacing")]
27    pub column_spacing: usize,
28    #[serde(default = "default_max_rows")]
29    pub max_rows: usize,
30}
31
32impl Default for Config {
33    fn default() -> Self {
34        Config {
35            colors: ColorConfig::default(),
36            display: DisplayConfig::default(),
37        }
38    }
39}
40
41impl Default for ColorConfig {
42    fn default() -> Self {
43        ColorConfig {
44            directory: default_directory_color(),
45            executable: default_executable_color(),
46            regular: default_regular_color(),
47        }
48    }
49}
50
51impl Default for DisplayConfig {
52    fn default() -> Self {
53        DisplayConfig {
54            column_spacing: default_column_spacing(),
55            max_rows: default_max_rows(),
56        }
57    }
58}
59
60fn default_directory_color() -> String {
61    "blue".to_string()
62}
63
64fn default_executable_color() -> String {
65    "green".to_string()
66}
67
68fn default_regular_color() -> String {
69    "white".to_string()
70}
71
72fn default_column_spacing() -> usize {
73    2
74}
75
76fn default_max_rows() -> usize {
77    0 // 0 means no limit
78}
79
80impl ColorConfig {
81    pub fn get_directory_color(&self) -> Color {
82        parse_color(&self.directory)
83    }
84
85    pub fn get_executable_color(&self) -> Color {
86        parse_color(&self.executable)
87    }
88
89    pub fn get_regular_color(&self) -> Color {
90        parse_color(&self.regular)
91    }
92}
93
94fn parse_color(color_str: &str) -> Color {
95    match color_str.to_lowercase().as_str() {
96        "black" => Color::Black,
97        "red" => Color::Red,
98        "green" => Color::Green,
99        "yellow" => Color::Yellow,
100        "blue" => Color::Blue,
101        "magenta" => Color::Magenta,
102        "cyan" => Color::Cyan,
103        "white" => Color::White,
104        "bright_black" => Color::BrightBlack,
105        "bright_red" => Color::BrightRed,
106        "bright_green" => Color::BrightGreen,
107        "bright_yellow" => Color::BrightYellow,
108        "bright_blue" => Color::BrightBlue,
109        "bright_magenta" => Color::BrightMagenta,
110        "bright_cyan" => Color::BrightCyan,
111        "bright_white" => Color::BrightWhite,
112        _ => Color::White, // Default fallback
113    }
114}
115
116pub fn load_config() -> Config {
117    let config_path = get_config_path();
118
119    if !config_path.exists() {
120        return Config::default();
121    }
122
123    match fs::read_to_string(&config_path) {
124        Ok(contents) => match toml::from_str(&contents) {
125            Ok(config) => config,
126            Err(e) => {
127                eprintln!("Warning: Failed to parse config file: {}", e);
128                Config::default()
129            }
130        },
131        Err(_) => Config::default(),
132    }
133}
134
135fn get_config_path() -> PathBuf {
136    let mut path = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
137    path.push(".config");
138    path.push("lx");
139    path.push("config");
140    path
141}