Skip to main content

md_tui/util/
colors.rs

1use std::{
2    str::FromStr,
3    sync::{Arc, LazyLock, RwLock},
4};
5
6use config::{Config, Environment, File};
7use ratatui::style::Color;
8
9#[derive(Debug, Clone, Copy)]
10pub struct ColorConfig {
11    // Inline styles
12    pub italic_color: Color,
13    pub bold_color: Color,
14    pub striketrough_color: Color,
15    pub bold_italic_color: Color,
16    pub code_fg_color: Color,
17    pub code_bg_color: Color,
18    pub link_color: Color,
19    pub link_selected_fg_color: Color,
20    pub link_selected_bg_color: Color,
21
22    // Block styles
23    pub code_block_bg_color: Color,
24    pub heading_fg_color: Color,
25    pub heading_bg_color: Color,
26    pub table_header_fg_color: Color,
27    pub table_header_bg_color: Color,
28    pub quote_bg_color: Color,
29
30    // File tree
31    pub file_tree_selected_fg_color: Color,
32    pub file_tree_page_count_color: Color,
33    pub file_tree_name_color: Color,
34    pub file_tree_path_color: Color,
35
36    // Quote markings
37    pub quote_important: Color,
38    pub quote_warning: Color,
39    pub quote_tip: Color,
40    pub quote_note: Color,
41    pub quote_caution: Color,
42    pub quote_default: Color,
43}
44
45#[must_use]
46pub fn read_color_config_from_file() -> ColorConfig {
47    let config_dir = dirs::home_dir().unwrap();
48    let config_file = config_dir.join(".config").join("mdt").join("config.toml");
49    let settings = Config::builder()
50        .add_source(File::with_name(config_file.to_str().unwrap()).required(false))
51        .add_source(Environment::with_prefix("MDT").separator("_"))
52        .build()
53        .unwrap();
54
55    ColorConfig {
56        heading_bg_color: Color::from_str(
57            &settings.get::<String>("h_bg_color").unwrap_or_default(),
58        )
59        .unwrap_or(Color::Blue),
60        heading_fg_color: Color::from_str(
61            &settings.get::<String>("h_fg_color").unwrap_or_default(),
62        )
63        .unwrap_or(Color::Black),
64        italic_color: Color::from_str(&settings.get::<String>("italic_color").unwrap_or_default())
65            .unwrap_or(Color::Reset),
66        bold_color: Color::from_str(&settings.get::<String>("bold_color").unwrap_or_default())
67            .unwrap_or(Color::Reset),
68        striketrough_color: Color::from_str(
69            &settings
70                .get_string("striketrough_color")
71                .unwrap_or_default(),
72        )
73        .unwrap_or(Color::Reset),
74        quote_bg_color: Color::from_str(
75            &settings.get::<String>("quote_bg_color").unwrap_or_default(),
76        )
77        .unwrap_or(Color::Reset),
78        code_fg_color: Color::from_str(
79            &settings.get::<String>("code_fg_color").unwrap_or_default(),
80        )
81        .unwrap_or(Color::Red),
82        code_bg_color: Color::from_str(
83            &settings.get::<String>("code_bg_color").unwrap_or_default(),
84        )
85        .unwrap_or(Color::Rgb(48, 48, 48)),
86        code_block_bg_color: Color::from_str(
87            &settings
88                .get::<String>("code_block_bg_color")
89                .unwrap_or_default(),
90        )
91        .unwrap_or(Color::Rgb(48, 48, 48)),
92        link_color: Color::from_str(&settings.get::<String>("link_color").unwrap_or_default())
93            .unwrap_or(Color::Blue),
94        link_selected_fg_color: Color::from_str(
95            &settings
96                .get::<String>("link_selected_fg_color")
97                .unwrap_or_default(),
98        )
99        .unwrap_or(Color::Green),
100        link_selected_bg_color: Color::from_str(
101            &settings
102                .get::<String>("link_selected_bg_color")
103                .unwrap_or_default(),
104        )
105        .unwrap_or(Color::DarkGray),
106        table_header_fg_color: Color::from_str(
107            &settings
108                .get::<String>("table_header_fg_color")
109                .unwrap_or_default(),
110        )
111        .unwrap_or(Color::Yellow),
112        table_header_bg_color: Color::from_str(
113            &settings
114                .get::<String>("table_header_bg_color")
115                .unwrap_or_default(),
116        )
117        .unwrap_or(Color::Reset),
118        file_tree_selected_fg_color: Color::from_str(
119            &settings
120                .get::<String>("file_tree_selected_fg_color")
121                .unwrap_or_default(),
122        )
123        .unwrap_or(Color::LightGreen),
124        file_tree_page_count_color: Color::from_str(
125            &settings
126                .get::<String>("file_tree_page_count_color")
127                .unwrap_or_default(),
128        )
129        .unwrap_or(Color::LightGreen),
130        file_tree_name_color: Color::from_str(
131            &settings
132                .get::<String>("file_tree_name_color")
133                .unwrap_or_default(),
134        )
135        .unwrap_or(Color::Blue),
136        file_tree_path_color: Color::from_str(
137            &settings
138                .get::<String>("file_tree_path_color")
139                .unwrap_or_default(),
140        )
141        .unwrap_or(Color::DarkGray),
142        bold_italic_color: Color::from_str(
143            &settings
144                .get::<String>("bold_italic_color")
145                .unwrap_or_default(),
146        )
147        .unwrap_or(Color::Reset),
148        quote_important: Color::from_str(
149            &settings
150                .get::<String>("quote_important")
151                .unwrap_or_default(),
152        )
153        .unwrap_or(Color::LightRed),
154        quote_warning: Color::from_str(
155            &settings.get::<String>("quote_warning").unwrap_or_default(),
156        )
157        .unwrap_or(Color::LightYellow),
158
159        quote_tip: Color::from_str(&settings.get::<String>("quote_tip").unwrap_or_default())
160            .unwrap_or(Color::LightGreen),
161
162        quote_note: Color::from_str(&settings.get::<String>("quote_note").unwrap_or_default())
163            .unwrap_or(Color::LightBlue),
164
165        quote_caution: Color::from_str(
166            &settings.get::<String>("quote_caution").unwrap_or_default(),
167        )
168        .unwrap_or(Color::LightMagenta),
169
170        quote_default: Color::from_str(
171            &settings.get::<String>("quote_default").unwrap_or_default(),
172        )
173        .unwrap_or(Color::White),
174    }
175}
176
177static COLOR_CONFIG_INTERNAL: LazyLock<Arc<RwLock<ColorConfig>>> =
178    LazyLock::new(|| Arc::new(RwLock::new(read_color_config_from_file())));
179
180pub fn set_color_config(config: ColorConfig) {
181    let mut color_config_internal = COLOR_CONFIG_INTERNAL.write().unwrap();
182    *color_config_internal = config;
183}
184
185#[must_use]
186pub fn color_config() -> ColorConfig {
187    *COLOR_CONFIG_INTERNAL.read().unwrap()
188}
189
190#[derive(Clone, Copy)]
191pub struct HeadingColors {
192    pub level_2: Color,
193    pub level_3: Color,
194    pub level_4: Color,
195    pub level_5: Color,
196    pub level_6: Color,
197}
198
199#[must_use]
200pub fn read_heading_colors_from_file() -> HeadingColors {
201    let config_dir = dirs::home_dir().unwrap();
202    let config_file = config_dir.join(".config").join("mdt").join("config.toml");
203    let settings = Config::builder()
204        .add_source(File::with_name(config_file.to_str().unwrap()).required(false))
205        .build()
206        .unwrap();
207
208    HeadingColors {
209        level_2: settings
210            .get::<String>("h2_fg_color")
211            .map(|s| Color::from_str(&s).unwrap_or(Color::Green))
212            .unwrap_or(Color::Green),
213        level_3: settings
214            .get_string("h3_fg_color")
215            .map(|s| Color::from_str(&s).unwrap_or(Color::Magenta))
216            .unwrap_or(Color::Magenta),
217        level_4: settings
218            .get_string("h4_fg_color")
219            .map(|s| Color::from_str(&s).unwrap_or(Color::Cyan))
220            .unwrap_or(Color::Cyan),
221        level_5: settings
222            .get_string("h5_fg_color")
223            .map(|s| Color::from_str(&s).unwrap_or(Color::Yellow))
224            .unwrap_or(Color::Yellow),
225        level_6: settings
226            .get_string("h6_fg_color")
227            .map(|s| Color::from_str(&s).unwrap_or(Color::LightRed))
228            .unwrap_or(Color::LightRed),
229    }
230}
231
232static HEADING_COLORS_INTERNAL: LazyLock<Arc<RwLock<HeadingColors>>> =
233    LazyLock::new(|| Arc::new(RwLock::new(read_heading_colors_from_file())));
234
235pub fn set_heading_colors(config: HeadingColors) {
236    let mut heading_colors_internal = HEADING_COLORS_INTERNAL.write().unwrap();
237    *heading_colors_internal = config;
238}
239
240#[must_use]
241pub fn heading_colors() -> HeadingColors {
242    *HEADING_COLORS_INTERNAL.read().unwrap()
243}