rush_sync_server/ui/
color.rs1use crate::core::prelude::*;
3use log::Level;
4use once_cell::sync::Lazy;
5use std::collections::HashMap;
6use std::fmt;
7
8#[derive(Debug, Clone, Copy, PartialEq)]
9pub struct AppColor(Color);
10
11static COLOR_MAP: Lazy<HashMap<&'static str, Color>> = Lazy::new(|| {
13 let mut map = HashMap::new();
14
15 map.insert("black", Color::Black);
17 map.insert("red", Color::Red);
18 map.insert("green", Color::Green);
19 map.insert("yellow", Color::Yellow);
20 map.insert("blue", Color::Blue);
21 map.insert("magenta", Color::Magenta);
22 map.insert("cyan", Color::Cyan);
23 map.insert("gray", Color::Gray);
24 map.insert("darkgray", Color::DarkGray);
25 map.insert("lightred", Color::LightRed);
26 map.insert("lightgreen", Color::LightGreen);
27 map.insert("lightyellow", Color::LightYellow);
28 map.insert("lightblue", Color::LightBlue);
29 map.insert("lightmagenta", Color::LightMagenta);
30 map.insert("lightcyan", Color::LightCyan);
31 map.insert("white", Color::White);
32
33 map.insert("error", Color::Red);
35 map.insert("warning", Color::Yellow);
36 map.insert("warn", Color::Yellow);
37 map.insert("info", Color::Green);
38 map.insert("debug", Color::Blue);
39 map.insert("trace", Color::White);
40 map.insert("lang", Color::Cyan);
41 map.insert("version", Color::LightBlue);
42 map.insert("startup", Color::Magenta);
43
44 map
45});
46
47impl AppColor {
48 pub fn new(color: Color) -> Self {
49 Self(color)
50 }
51
52 pub fn from_any<T: Into<String>>(source: T) -> Self {
54 let key = source.into().to_lowercase();
55 Self(*COLOR_MAP.get(key.as_str()).unwrap_or(&Color::Gray))
56 }
57
58 pub fn from_log_level(level: Level) -> Self {
60 Self::from_any(level.to_string())
61 }
62
63 pub fn from_string(color_str: &str) -> crate::core::error::Result<Self> {
65 COLOR_MAP
66 .get(&color_str.to_lowercase().as_str())
67 .map(|&c| Self(c))
68 .ok_or_else(|| AppError::Validation(format!("Ungültige Farbe: {}", color_str)))
69 }
70
71 pub fn format_message(&self, level: &str, message: &str) -> String {
72 if level.is_empty() {
73 format!("\x1B[{}m{}\x1B[0m", self.to_ansi_code(), message)
74 } else {
75 format!(
76 "\x1B[{}m[{}] {}\x1B[0m",
77 self.to_ansi_code(),
78 level,
79 message
80 )
81 }
82 }
83
84 pub fn to_ansi_code(&self) -> u8 {
85 match self.0 {
86 Color::Black => 30,
87 Color::Red => 31,
88 Color::Green => 32,
89 Color::Yellow => 33,
90 Color::Blue => 34,
91 Color::Magenta => 35,
92 Color::Cyan => 36,
93 Color::Gray => 37,
94 Color::DarkGray => 90,
95 Color::LightRed => 91,
96 Color::LightGreen => 92,
97 Color::LightYellow => 93,
98 Color::LightBlue => 94,
99 Color::LightMagenta => 95,
100 Color::LightCyan => 96,
101 Color::White => 97,
102 _ => 37,
103 }
104 }
105
106 pub fn to_name(&self) -> &'static str {
107 COLOR_MAP
108 .iter()
109 .find(|(_, &v)| v == self.0)
110 .map(|(k, _)| *k)
111 .unwrap_or("gray")
112 }
113}
114
115impl fmt::Display for AppColor {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 write!(f, "{}", self.to_name())
118 }
119}
120
121impl From<AppColor> for Color {
122 fn from(app_color: AppColor) -> Self {
123 app_color.0
124 }
125}
126
127impl From<&AppColor> for Color {
128 fn from(app_color: &AppColor) -> Self {
129 app_color.0
130 }
131}
132
133impl Default for AppColor {
134 fn default() -> Self {
135 Self(Color::Gray)
136 }
137}
138