1use crate::style::{Color, Theme};
4use anyhow::{anyhow, Result};
5use std::collections::HashMap;
6use std::sync::Arc;
7
8pub struct ThemeResetManager {
10 default_themes: Arc<HashMap<String, Theme>>,
12}
13
14impl ThemeResetManager {
15 pub fn new() -> Self {
17 let mut defaults = HashMap::new();
18
19 defaults.insert("dark".to_string(), Theme::default());
21 defaults.insert("light".to_string(), Theme::light());
22 defaults.insert("monokai".to_string(), Theme::monokai());
23 defaults.insert("dracula".to_string(), Theme::dracula());
24 defaults.insert("nord".to_string(), Theme::nord());
25 defaults.insert("high-contrast".to_string(), Theme::high_contrast());
26
27 Self {
28 default_themes: Arc::new(defaults),
29 }
30 }
31
32 pub fn reset_colors(&self, theme: &mut Theme) -> Result<()> {
43 let default = self
44 .default_themes
45 .get(&theme.name)
46 .ok_or_else(|| anyhow!("Theme '{}' is not a built-in theme", theme.name))?;
47
48 theme.primary = default.primary;
50 theme.secondary = default.secondary;
51 theme.accent = default.accent;
52 theme.background = default.background;
53 theme.foreground = default.foreground;
54 theme.error = default.error;
55 theme.warning = default.warning;
56 theme.success = default.success;
57
58 Ok(())
59 }
60
61 pub fn reset_theme(&self, theme: &mut Theme) -> Result<()> {
72 let default = self
73 .default_themes
74 .get(&theme.name)
75 .ok_or_else(|| anyhow!("Theme '{}' is not a built-in theme", theme.name))?;
76
77 *theme = default.clone();
79
80 Ok(())
81 }
82
83 pub fn get_default_color(&self, theme_name: &str, color_name: &str) -> Result<Color> {
95 let theme = self
96 .default_themes
97 .get(theme_name)
98 .ok_or_else(|| anyhow!("Theme '{}' is not a built-in theme", theme_name))?;
99
100 match color_name.to_lowercase().as_str() {
101 "primary" => Ok(theme.primary),
102 "secondary" => Ok(theme.secondary),
103 "accent" => Ok(theme.accent),
104 "background" => Ok(theme.background),
105 "foreground" => Ok(theme.foreground),
106 "error" => Ok(theme.error),
107 "warning" => Ok(theme.warning),
108 "success" => Ok(theme.success),
109 _ => Err(anyhow!("Unknown color field: {}", color_name)),
110 }
111 }
112
113 pub fn reset_color(&self, theme: &mut Theme, color_name: &str) -> Result<()> {
125 let default_color = self.get_default_color(&theme.name, color_name)?;
126
127 match color_name.to_lowercase().as_str() {
128 "primary" => theme.primary = default_color,
129 "secondary" => theme.secondary = default_color,
130 "accent" => theme.accent = default_color,
131 "background" => theme.background = default_color,
132 "foreground" => theme.foreground = default_color,
133 "error" => theme.error = default_color,
134 "warning" => theme.warning = default_color,
135 "success" => theme.success = default_color,
136 _ => return Err(anyhow!("Unknown color field: {}", color_name)),
137 }
138
139 Ok(())
140 }
141
142 pub fn is_builtin_theme(&self, theme_name: &str) -> bool {
153 self.default_themes.contains_key(theme_name)
154 }
155
156 pub fn builtin_theme_names(&self) -> Vec<String> {
162 let mut names: Vec<_> = self.default_themes.keys().cloned().collect();
163 names.sort();
164 names
165 }
166
167 pub fn get_builtin_theme(&self, theme_name: &str) -> Result<Theme> {
178 self.default_themes
179 .get(theme_name)
180 .cloned()
181 .ok_or_else(|| anyhow!("Theme '{}' is not a built-in theme", theme_name))
182 }
183}
184
185impl Default for ThemeResetManager {
186 fn default() -> Self {
187 Self::new()
188 }
189}
190
191impl std::fmt::Debug for ThemeResetManager {
192 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193 f.debug_struct("ThemeResetManager")
194 .field("builtin_themes", &self.builtin_theme_names())
195 .finish()
196 }
197}
198
199#[cfg(test)]
200mod tests {
201 use super::*;
202
203 #[test]
204 fn test_reset_manager_creation() {
205 let manager = ThemeResetManager::new();
206 assert_eq!(manager.builtin_theme_names().len(), 6);
207 }
208
209 #[test]
210 fn test_reset_colors() {
211 let manager = ThemeResetManager::new();
212 let mut theme = Theme::default();
213
214 theme.primary = Color::new(255, 0, 0);
216 theme.error = Color::new(0, 255, 0);
217
218 manager.reset_colors(&mut theme).unwrap();
220
221 let default = Theme::default();
223 assert_eq!(theme.primary, default.primary);
224 assert_eq!(theme.error, default.error);
225 }
226
227 #[test]
228 fn test_reset_theme() {
229 let manager = ThemeResetManager::new();
230 let mut theme = Theme::light();
231
232 theme.primary = Color::new(255, 0, 0);
234 theme.background = Color::new(100, 100, 100);
235
236 manager.reset_theme(&mut theme).unwrap();
238
239 let default = Theme::light();
241 assert_eq!(theme.primary, default.primary);
242 assert_eq!(theme.secondary, default.secondary);
243 assert_eq!(theme.accent, default.accent);
244 assert_eq!(theme.background, default.background);
245 assert_eq!(theme.foreground, default.foreground);
246 assert_eq!(theme.error, default.error);
247 assert_eq!(theme.warning, default.warning);
248 assert_eq!(theme.success, default.success);
249 }
250
251 #[test]
252 fn test_reset_theme_preserves_name() {
253 let manager = ThemeResetManager::new();
254 let mut theme = Theme::monokai();
255 let original_name = theme.name.clone();
256
257 theme.primary = Color::new(255, 0, 0);
259
260 manager.reset_theme(&mut theme).unwrap();
262
263 assert_eq!(theme.name, original_name);
265 }
266
267 #[test]
268 fn test_get_default_color() {
269 let manager = ThemeResetManager::new();
270 let default_primary = manager.get_default_color("dark", "primary").unwrap();
271 let theme = Theme::default();
272 assert_eq!(default_primary, theme.primary);
273 }
274
275 #[test]
276 fn test_get_default_color_all_fields() {
277 let manager = ThemeResetManager::new();
278 let theme = Theme::dracula();
279
280 assert_eq!(
281 manager.get_default_color("dracula", "primary").unwrap(),
282 theme.primary
283 );
284 assert_eq!(
285 manager.get_default_color("dracula", "secondary").unwrap(),
286 theme.secondary
287 );
288 assert_eq!(
289 manager.get_default_color("dracula", "accent").unwrap(),
290 theme.accent
291 );
292 assert_eq!(
293 manager.get_default_color("dracula", "background").unwrap(),
294 theme.background
295 );
296 assert_eq!(
297 manager.get_default_color("dracula", "foreground").unwrap(),
298 theme.foreground
299 );
300 assert_eq!(
301 manager.get_default_color("dracula", "error").unwrap(),
302 theme.error
303 );
304 assert_eq!(
305 manager.get_default_color("dracula", "warning").unwrap(),
306 theme.warning
307 );
308 assert_eq!(
309 manager.get_default_color("dracula", "success").unwrap(),
310 theme.success
311 );
312 }
313
314 #[test]
315 fn test_get_default_color_case_insensitive() {
316 let manager = ThemeResetManager::new();
317 let color1 = manager.get_default_color("dark", "primary").unwrap();
318 let color2 = manager.get_default_color("dark", "PRIMARY").unwrap();
319 let color3 = manager.get_default_color("dark", "Primary").unwrap();
320
321 assert_eq!(color1, color2);
322 assert_eq!(color2, color3);
323 }
324
325 #[test]
326 fn test_get_default_color_invalid_theme() {
327 let manager = ThemeResetManager::new();
328 assert!(manager.get_default_color("invalid", "primary").is_err());
329 }
330
331 #[test]
332 fn test_get_default_color_invalid_field() {
333 let manager = ThemeResetManager::new();
334 assert!(manager.get_default_color("dark", "invalid").is_err());
335 }
336
337 #[test]
338 fn test_reset_color() {
339 let manager = ThemeResetManager::new();
340 let mut theme = Theme::nord();
341 let default_primary = manager.get_default_color("nord", "primary").unwrap();
342
343 theme.primary = Color::new(255, 0, 0);
345 assert_ne!(theme.primary, default_primary);
346
347 manager.reset_color(&mut theme, "primary").unwrap();
349
350 assert_eq!(theme.primary, default_primary);
352
353 let default_error = manager.get_default_color("nord", "error").unwrap();
355 assert_eq!(theme.error, default_error);
356 }
357
358 #[test]
359 fn test_reset_color_invalid_field() {
360 let manager = ThemeResetManager::new();
361 let mut theme = Theme::default();
362 assert!(manager.reset_color(&mut theme, "invalid").is_err());
363 }
364
365 #[test]
366 fn test_is_builtin_theme() {
367 let manager = ThemeResetManager::new();
368 assert!(manager.is_builtin_theme("dark"));
369 assert!(manager.is_builtin_theme("light"));
370 assert!(manager.is_builtin_theme("monokai"));
371 assert!(manager.is_builtin_theme("dracula"));
372 assert!(manager.is_builtin_theme("nord"));
373 assert!(manager.is_builtin_theme("high-contrast"));
374 assert!(!manager.is_builtin_theme("custom"));
375 assert!(!manager.is_builtin_theme("invalid"));
376 }
377
378 #[test]
379 fn test_builtin_theme_names() {
380 let manager = ThemeResetManager::new();
381 let names = manager.builtin_theme_names();
382 assert_eq!(names.len(), 6);
383 assert!(names.contains(&"dark".to_string()));
384 assert!(names.contains(&"light".to_string()));
385 assert!(names.contains(&"monokai".to_string()));
386 assert!(names.contains(&"dracula".to_string()));
387 assert!(names.contains(&"nord".to_string()));
388 assert!(names.contains(&"high-contrast".to_string()));
389 }
390
391 #[test]
392 fn test_get_builtin_theme() {
393 let manager = ThemeResetManager::new();
394 let theme = manager.get_builtin_theme("dark").unwrap();
395 assert_eq!(theme.name, "dark");
396 let default = Theme::default();
397 assert_eq!(theme.primary, default.primary);
398 assert_eq!(theme.secondary, default.secondary);
399 }
400
401 #[test]
402 fn test_get_builtin_theme_invalid() {
403 let manager = ThemeResetManager::new();
404 assert!(manager.get_builtin_theme("invalid").is_err());
405 }
406
407 #[test]
408 fn test_reset_colors_invalid_theme() {
409 let manager = ThemeResetManager::new();
410 let mut theme = Theme::light();
411 theme.name = "custom".to_string();
412
413 assert!(manager.reset_colors(&mut theme).is_err());
415 }
416
417 #[test]
418 fn test_reset_theme_invalid_theme() {
419 let manager = ThemeResetManager::new();
420 let mut theme = Theme::light();
421 theme.name = "custom".to_string();
422
423 assert!(manager.reset_theme(&mut theme).is_err());
425 }
426
427 #[test]
428 fn test_reset_all_themes() {
429 let manager = ThemeResetManager::new();
430
431 for theme_name in manager.builtin_theme_names() {
432 let mut theme = manager.get_builtin_theme(&theme_name).unwrap();
433
434 theme.primary = Color::new(255, 0, 0);
436 theme.secondary = Color::new(0, 255, 0);
437 theme.accent = Color::new(0, 0, 255);
438 theme.background = Color::new(100, 100, 100);
439 theme.foreground = Color::new(200, 200, 200);
440 theme.error = Color::new(255, 128, 128);
441 theme.warning = Color::new(255, 255, 128);
442 theme.success = Color::new(128, 255, 128);
443
444 manager.reset_colors(&mut theme).unwrap();
446
447 let default = manager.get_builtin_theme(&theme_name).unwrap();
449 assert_eq!(theme.primary, default.primary);
450 assert_eq!(theme.secondary, default.secondary);
451 assert_eq!(theme.accent, default.accent);
452 assert_eq!(theme.background, default.background);
453 assert_eq!(theme.foreground, default.foreground);
454 assert_eq!(theme.error, default.error);
455 assert_eq!(theme.warning, default.warning);
456 assert_eq!(theme.success, default.success);
457 }
458 }
459}