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 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 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 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 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}