1use std::fmt::Display;
2
3pub enum Color {
4 Black = 30,
5 Red = 31,
6 Green = 32,
7 Yellow = 33,
8 Blue = 34,
9 Magenta = 35,
10 Cyan = 36,
11 White = 37,
12 BrightBlack = 90,
14 BrightRed = 91,
15 BrightGreen = 92,
16 BrightYellow = 93,
17 BrightBlue = 94,
18 BrightMagenta = 95,
19 BrightCyan = 96,
20 BrightWhite = 97,
21}
22
23pub struct Colorizer;
24
25impl Colorizer {
26 pub fn new() -> Colorizer {
27 Colorizer
28 }
29
30 fn supports_aixterm() -> bool {
32 std::env::var("TERM").unwrap_or_default().contains("xterm")
33 }
34
35 fn ansi<T: Display>(&self, input: T, ansi_code: u8) -> String {
36 format!("\x1b[{}m{}\x1b[0m", ansi_code, input)
37 }
38
39 pub fn underline<T: Display>(&self, input: T) -> String {
40 self.ansi(input, 4)
41 }
42
43 pub fn bold<T: Display>(&self, input: T) -> String {
44 self.ansi(input, 1)
45 }
46
47 pub fn italic<T: Display>(&self, input: T) -> String {
48 self.ansi(input, 3)
49 }
50
51 pub fn strikethrough<T: Display>(&self, input: T) -> String {
52 self.ansi(input, 9)
53 }
54
55 pub fn black<T: Display>(&self, input: T) -> String {
56 self.ansi(input, Color::Black as u8)
57 }
58
59 pub fn red<T: Display>(&self, input: T) -> String {
60 self.ansi(input, Color::Red as u8)
61 }
62
63 pub fn green<T: Display>(&self, input: T) -> String {
64 self.ansi(input, Color::Green as u8)
65 }
66
67 pub fn yellow<T: Display>(&self, input: T) -> String {
68 self.ansi(input, Color::Yellow as u8)
69 }
70
71 pub fn blue<T: Display>(&self, input: T) -> String {
72 self.ansi(input, Color::Blue as u8)
73 }
74
75 pub fn magenta<T: Display>(&self, input: T) -> String {
76 self.ansi(input, Color::Magenta as u8)
77 }
78
79 pub fn cyan<T: Display>(&self, input: T) -> String {
80 self.ansi(input, Color::Cyan as u8)
81 }
82
83 pub fn white<T: Display>(&self, input: T) -> String {
84 self.ansi(input, Color::White as u8)
85 }
86
87 pub fn bright_black<T: Display>(&self, input: T) -> String {
88 assert!(
89 Self::supports_aixterm(),
90 "Bright colors require aixterm support",
91 );
92 self.ansi(input, Color::BrightBlack as u8)
93 }
94
95 pub fn bright_red<T: Display>(&self, input: T) -> String {
96 assert!(
97 Self::supports_aixterm(),
98 "Bright colors require aixterm support",
99 );
100 self.ansi(input, Color::BrightRed as u8)
101 }
102
103 pub fn bright_green<T: Display>(&self, input: T) -> String {
104 assert!(
105 Self::supports_aixterm(),
106 "Bright colors require aixterm support",
107 );
108 self.ansi(input, Color::BrightGreen as u8)
109 }
110
111 pub fn bright_yellow<T: Display>(&self, input: T) -> String {
112 assert!(
113 Self::supports_aixterm(),
114 "Bright colors require aixterm support",
115 );
116 self.ansi(input, Color::BrightYellow as u8)
117 }
118
119 pub fn bright_blue<T: Display>(&self, input: T) -> String {
120 assert!(
121 Self::supports_aixterm(),
122 "Bright colors require aixterm support",
123 );
124 self.ansi(input, Color::BrightBlue as u8)
125 }
126
127 pub fn bright_magenta<T: Display>(&self, input: T) -> String {
128 assert!(
129 Self::supports_aixterm(),
130 "Bright colors require aixterm support",
131 );
132 self.ansi(input, Color::BrightMagenta as u8)
133 }
134
135 pub fn bright_cyan<T: Display>(&self, input: T) -> String {
136 assert!(
137 Self::supports_aixterm(),
138 "Bright colors require aixterm support",
139 );
140 self.ansi(input, Color::BrightCyan as u8)
141 }
142
143 pub fn bright_white<T: Display>(&self, input: T) -> String {
144 assert!(
145 Self::supports_aixterm(),
146 "Bright colors require aixterm support",
147 );
148 self.ansi(input, Color::BrightWhite as u8)
149 }
150
151 pub fn bg_black<T: Display>(&self, input: T) -> String {
152 format!("\x1b[40m{}\x1b[0m", input)
153 }
154
155 pub fn bg_red<T: Display>(&self, input: T) -> String {
156 format!("\x1b[41m{}\x1b[0m", input)
157 }
158
159 pub fn bg_green<T: Display>(&self, input: T) -> String {
160 format!("\x1b[42m{}\x1b[0m", input)
161 }
162
163 pub fn bg_yellow<T: Display>(&self, input: T) -> String {
164 format!("\x1b[43m{}\x1b[0m", input)
165 }
166
167 pub fn bg_blue<T: Display>(&self, input: T) -> String {
168 format!("\x1b[44m{}\x1b[0m", input)
169 }
170
171 pub fn bg_magenta<T: Display>(&self, input: T) -> String {
172 format!("\x1b[45m{}\x1b[0m", input)
173 }
174
175 pub fn bg_cyan<T: Display>(&self, input: T) -> String {
176 format!("\x1b[46m{}\x1b[0m", input)
177 }
178
179 pub fn bg_white<T: Display>(&self, input: T) -> String {
180 format!("\x1b[47m{}\x1b[0m", input)
181 }
182
183 pub fn rgb<T: Display>(&self, input: T, r: u8, g: u8, b: u8) -> String {
184 format!("\x1b[38;2;{};{};{}m{}\x1b[0m", r, g, b, input)
185 }
186
187 pub fn bg_rgb<T: Display>(&self, input: T, r: u8, g: u8, b: u8) -> String {
188 format!("\x1b[48;2;{};{};{}m{}\x1b[0m", r, g, b, input)
189 }
190
191 pub fn rgb256<T: Display>(&self, input: T, r: u8, g: u8, b: u8) -> String {
192 format!("\x1b[38;5;{}m{}\x1b[0m", 16 + 36 * r + 6 * g + b, input)
193 }
194
195 pub fn bg_rgb256<T: Display>(&self, input: T, r: u8, g: u8, b: u8) -> String {
196 format!("\x1b[48;5;{}m{}\x1b[0m", 16 + 36 * r + 6 * g + b, input)
197 }
198
199 pub fn reset<T: Display>(&self, input: T) -> String {
200 format!("\x1b[0m{}\x1b[0m", input)
201 }
202
203 pub fn bold_underline<T: Display>(&self, input: T) -> String {
204 self.ansi(self.underline(self.bold(input)), 1)
205 }
206
207 pub fn bold_italic<T: Display>(&self, input: T) -> String {
208 self.ansi(self.italic(self.bold(input)), 1)
209 }
210
211 pub fn bold_strikethrough<T: Display>(&self, input: T) -> String {
212 self.ansi(self.strikethrough(self.bold(input)), 1)
213 }
214
215 pub fn underline_italic<T: Display>(&self, input: T) -> String {
216 self.ansi(self.italic(self.underline(input)), 1)
217 }
218
219 pub fn underline_strikethrough<T: Display>(&self, input: T) -> String {
220 self.ansi(self.strikethrough(self.underline(input)), 1)
221 }
222
223 pub fn italic_strikethrough<T: Display>(&self, input: T) -> String {
224 self.ansi(self.strikethrough(self.italic(input)), 1)
225 }
226
227 pub fn bold_underline_italic<T: Display>(&self, input: T) -> String {
228 self.ansi(self.italic(self.underline(self.bold(input))), 1)
229 }
230
231 pub fn bold_underline_strikethrough<T: Display>(&self, input: T) -> String {
232 self.ansi(self.strikethrough(self.underline(self.bold(input))), 1)
233 }
234
235 pub fn bold_italic_strikethrough<T: Display>(&self, input: T) -> String {
236 self.ansi(self.strikethrough(self.italic(self.bold(input))), 1)
237 }
238
239 pub fn underline_italic_strikethrough<T: Display>(&self, input: T) -> String {
240 self.ansi(self.strikethrough(self.italic(self.underline(input))), 1)
241 }
242
243 pub fn rainbow<T: Display>(&self, input: T) -> String {
244 let mut rainbow = String::new();
245 for (i, c) in input.to_string().chars().enumerate() {
246 let color = match i % 6 {
247 0 => self.red(c),
248 1 => self.yellow(c),
249 2 => self.green(c),
250 3 => self.cyan(c),
251 4 => self.blue(c),
252 5 => self.magenta(c),
253 _ => unreachable!(),
254 };
255 rainbow.push_str(&color);
256 }
257 rainbow
258 }
259
260 pub fn bg_rainbow<T: Display>(&self, input: T) -> String {
261 let mut rainbow = String::new();
262 for (i, c) in input.to_string().chars().enumerate() {
263 let color = match i % 6 {
264 0 => self.bg_red(c),
265 1 => self.bg_yellow(c),
266 2 => self.bg_green(c),
267 3 => self.bg_cyan(c),
268 4 => self.bg_blue(c),
269 5 => self.bg_magenta(c),
270 _ => unreachable!(),
271 };
272 rainbow.push_str(&color);
273 }
274 rainbow
275 }
276
277 pub fn bg_rainbow256<T: Display>(&self, input: T) -> String {
278 let mut rainbow = String::new();
279 for (i, c) in input.to_string().chars().enumerate() {
280 let color = match i % 6 {
281 0 => self.bg_rgb256(c, 5, 0, 0),
282 1 => self.bg_rgb256(c, 5, 5, 0),
283 2 => self.bg_rgb256(c, 0, 5, 0),
284 3 => self.bg_rgb256(c, 0, 5, 5),
285 4 => self.bg_rgb256(c, 0, 0, 5),
286 5 => self.bg_rgb256(c, 5, 0, 5),
287 _ => unreachable!(),
288 };
289 rainbow.push_str(&color);
290 }
291 rainbow
292 }
293
294 pub fn bg_rainbow_rgb<T: Display>(&self, input: T) -> String {
295 let mut rainbow = String::new();
296 for (i, c) in input.to_string().chars().enumerate() {
297 let color = match i % 6 {
298 0 => self.bg_rgb(c, 255, 0, 0),
299 1 => self.bg_rgb(c, 255, 255, 0),
300 2 => self.bg_rgb(c, 0, 255, 0),
301 3 => self.bg_rgb(c, 0, 255, 255),
302 4 => self.bg_rgb(c, 0, 0, 255),
303 5 => self.bg_rgb(c, 255, 0, 255),
304 _ => unreachable!(),
305 };
306 rainbow.push_str(&color);
307 }
308 rainbow
309 }
310}