1use std::collections::HashMap;
6
7#[derive(Debug, Clone)]
9pub enum ColorTheme {
10 Default,
12 Dark,
14 Light,
16 Custom(HashMap<String, String>),
18}
19
20#[derive(Debug, Clone)]
22pub struct LevelColors {
23 pub error: String,
24 pub warn: String,
25 pub info: String,
26 pub debug: String,
27 pub trace: String,
28}
29
30#[derive(Debug, Clone)]
32pub struct ColorConfig {
33 pub enabled: bool,
35 pub theme: ColorTheme,
37 pub level_colors: LevelColors,
39 pub keyword_colors: HashMap<String, String>,
41 pub timestamp_color: String,
43 pub filename_color: String,
45 pub line_number_color: String,
47}
48
49impl Default for LevelColors {
50 fn default() -> Self {
51 Self {
52 error: "red".to_string(),
53 warn: "yellow".to_string(),
54 info: "green".to_string(),
55 debug: "blue".to_string(),
56 trace: "magenta".to_string(),
57 }
58 }
59}
60
61impl Default for ColorConfig {
62 fn default() -> Self {
63 Self {
64 enabled: true,
65 theme: ColorTheme::Default,
66 level_colors: LevelColors::default(),
67 keyword_colors: HashMap::new(),
68 timestamp_color: "cyan".to_string(),
69 filename_color: "white".to_string(),
70 line_number_color: "bright_black".to_string(),
71 }
72 }
73}
74
75pub struct ColorApplier {
77 config: ColorConfig,
78}
79
80impl ColorApplier {
81 pub fn new(config: ColorConfig) -> Self {
83 Self { config }
84 }
85
86 pub fn apply_level_color(&self, _level: &str, text: &str) -> String {
88 text.to_string()
89 }
90
91 pub fn apply_keyword_color(&self, _keyword: &str, text: &str) -> String {
93 text.to_string()
94 }
95
96 pub fn apply_timestamp_color(&self, text: &str) -> String {
98 text.to_string()
99 }
100
101 pub fn apply_filename_color(&self, text: &str) -> String {
103 text.to_string()
104 }
105
106 pub fn apply_line_number_color(&self, text: &str) -> String {
108 text.to_string()
109 }
110
111
112
113 pub fn supports_color() -> bool {
115 false
116 }
117
118 pub fn set_override(&self, _enabled: bool) {
120 }
122}
123
124pub struct ColorConfigBuilder {
126 config: ColorConfig,
127}
128
129impl ColorConfigBuilder {
130 pub fn new() -> Self {
132 Self {
133 config: ColorConfig::default(),
134 }
135 }
136
137 pub fn enabled(mut self, enabled: bool) -> Self {
139 self.config.enabled = enabled;
140 self
141 }
142
143 pub fn theme(mut self, theme: ColorTheme) -> Self {
145 self.config.theme = theme;
146 self
147 }
148
149 pub fn error_color<S: Into<String>>(mut self, color: S) -> Self {
151 self.config.level_colors.error = color.into();
152 self
153 }
154
155 pub fn warn_color<S: Into<String>>(mut self, color: S) -> Self {
157 self.config.level_colors.warn = color.into();
158 self
159 }
160
161 pub fn info_color<S: Into<String>>(mut self, color: S) -> Self {
163 self.config.level_colors.info = color.into();
164 self
165 }
166
167 pub fn debug_color<S: Into<String>>(mut self, color: S) -> Self {
169 self.config.level_colors.debug = color.into();
170 self
171 }
172
173 pub fn trace_color<S: Into<String>>(mut self, color: S) -> Self {
175 self.config.level_colors.trace = color.into();
176 self
177 }
178
179 pub fn keyword_color<K: Into<String>, C: Into<String>>(mut self, keyword: K, color: C) -> Self {
181 self.config.keyword_colors.insert(keyword.into(), color.into());
182 self
183 }
184
185 pub fn timestamp_color<S: Into<String>>(mut self, color: S) -> Self {
187 self.config.timestamp_color = color.into();
188 self
189 }
190
191 pub fn filename_color<S: Into<String>>(mut self, color: S) -> Self {
193 self.config.filename_color = color.into();
194 self
195 }
196
197 pub fn line_number_color<S: Into<String>>(mut self, color: S) -> Self {
199 self.config.line_number_color = color.into();
200 self
201 }
202
203 pub fn build(self) -> ColorConfig {
205 self.config
206 }
207}
208
209impl ColorTheme {
211 pub fn dark() -> Self {
213 ColorTheme::Dark
214 }
215
216 pub fn light() -> Self {
218 ColorTheme::Light
219 }
220
221 pub fn custom(colors: HashMap<String, String>) -> Self {
223 ColorTheme::Custom(colors)
224 }
225}
226
227#[cfg(test)]
228mod tests {
229 use super::*;
230
231 #[test]
232 fn test_color_config_builder() {
233 let config = ColorConfigBuilder::new()
234 .enabled(true)
235 .error_color("bright_red")
236 .warn_color("bright_yellow")
237 .keyword_color("ERROR", "red")
238 .timestamp_color("blue")
239 .build();
240
241 assert!(config.enabled);
242 assert_eq!(config.level_colors.error, "bright_red");
243 assert_eq!(config.level_colors.warn, "bright_yellow");
244 assert_eq!(config.keyword_colors.get("ERROR"), Some(&"red".to_string()));
245 assert_eq!(config.timestamp_color, "blue");
246 }
247
248 #[test]
249 fn test_color_applier() {
250 let config = ColorConfig::default();
251 let applier = ColorApplier::new(config);
252
253 let colored_text = applier.apply_level_color("ERROR", "Test message");
254 assert_eq!(colored_text, "Test message");
256 }
257}