1use BgColor::*;
26use Color::*;
27use Style::*;
28
29use std::mem;
30
31#[derive(Clone, Copy)]
33pub enum Color {
34 Black = 30,
35 Red = 31,
36 Green = 32,
37 Yellow = 33,
38 Blue = 34,
39 Magenta = 35,
40 Cyan = 36,
41 Grey = 37,
42 Default = 39,
43 BrightBlack = 90,
44 BrightRed = 91,
45 BrightGreen = 92,
46 BrightYellow = 93,
47 BrightBlue = 94,
48 BrightMagenta = 95,
49 BrightCyan = 96,
50 BrightGrey = 97,
51}
52
53#[derive(Clone, Copy)]
54pub enum BgColor {
55 Blackb = 40,
56 Redb = 41,
57 Greenb = 42,
58 Yellowb = 43,
59 Blueb = 44,
60 Magentab = 45,
61 Cyanb = 46,
62 Greyb = 47,
63 Defaultb = 49,
64 BrightBlackb = 100,
65 BrightRedb = 101,
66 BrightGreenb = 102,
67 BrightYellowb = 103,
68 BrightBlueb = 104,
69 BrightMagentab = 105,
70 BrightCyanb = 106,
71 BrightGreyb = 107,
72}
73
74#[derive(Clone, Copy)]
75pub enum Style {
76 Underscore = 4,
77 Bold = 1,
78 Blink = 5,
79 Reverse = 7,
80 Concealed = 8,
81 Faint = 2,
82 Italic = 3,
83 CrossedOut = 9,
84}
85
86impl internal::TermAttrib for Color {
87 fn to_int(&self) -> i32 {
88 *self as i32
89 }
90}
91
92impl internal::TermAttrib for BgColor {
93 fn to_int(&self) -> i32 {
94 *self as i32
95 }
96}
97
98impl internal::TermAttrib for Style {
99 fn to_int(&self) -> i32 {
100 *self as i32
101 }
102}
103
104impl BgColor {
105 fn from_fg(color: Color) -> BgColor {
106 unsafe { mem::transmute(color as i8 + 10) }
107 }
108}
109
110mod internal {
111 use super::{BgColor, Color};
112 use std::cell::RefCell;
113
114 static DEFAULT_FG: i32 = 39;
115 static DEFAULT_BG: i32 = 49;
116 thread_local!(static GLOB_COLOR: RefCell<GlobalColor> = RefCell::new(GlobalColor {fg: DEFAULT_FG, bg: DEFAULT_BG, enabled: true}));
117
118 pub trait TermAttrib {
119 fn to_int(&self) -> i32;
120 }
121
122 #[derive(Clone)]
123 pub struct GlobalColor {
124 fg: i32,
125 bg: i32,
126 enabled: bool,
127 }
128
129 impl Drop for GlobalColor {
130 fn drop(&mut self) {
131 print!("\x1b[0;{};{}m", DEFAULT_FG, DEFAULT_BG)
132 }
133 }
134
135 fn get_glob() -> (i32, i32, bool) {
136 GLOB_COLOR.with(|cell| {
137 let g = cell.borrow();
138 (g.fg, g.bg, g.enabled)
139 })
140 }
141
142 pub fn global_color(fg_color: Option<Color>, bg_color: Option<BgColor>, enabled: Option<bool>) {
143 GLOB_COLOR.with(|cell| {
144 let mut g = cell.borrow_mut();
145 match fg_color {
146 Some(c) => g.fg = c.to_int(),
147 None => g.fg = g.fg,
148 }
149 match bg_color {
150 Some(c) => g.bg = c.to_int(),
151 None => g.bg = g.bg,
152 }
153 match enabled {
154 Some(c) => g.enabled = c,
155 None => g.enabled = g.enabled,
156 }
157 })
158 }
159
160 pub fn pack<T: TermAttrib>(attrib: T, mut text: String) -> String {
161 if {
162 let (_, _, en) = get_glob();
163 !en
164 } {
165 return text;
166 }
167 if text.as_str().starts_with("\x1b[") {
168 unsafe {
169 text.as_mut_vec().remove(0);
170 text.as_mut_vec().remove(0);
171 }
172 let tmp = text;
173 text = String::from("\x1b[");
174 text.push_str(format!("{};", attrib.to_int()).as_str());
175 text.push_str(tmp.as_str());
176 } else {
177 let tmp = text;
178 text = format!("\x1b[{}m", attrib.to_int());
179 text.push_str(tmp.as_str());
180 let (fg, bg, _) = get_glob();
181 text.push_str(format!("\x1b[0;{};{}m", fg, bg).as_str());
182 }
183 text
184 }
185}
186
187pub fn global_fg(color: Color) {
189 internal::global_color(Some(color), None, None)
190}
191
192pub fn global_bg(color: Color) {
194 internal::global_color(None, Some(BgColor::from_fg(color)), None)
195}
196pub fn color_enabled(enabled: bool) {
198 internal::global_color(None, None, Some(enabled))
199}
200
201pub fn reset() {
203 internal::global_color(Some(Default), Some(Defaultb), None)
204}
205
206pub trait AnsiColor {
209 fn black(self) -> String;
211 fn red(self) -> String;
213 fn green(self) -> String;
215 fn yellow(self) -> String;
217 fn blue(self) -> String;
219 fn magenta(self) -> String;
221 fn cyan(self) -> String;
223 fn grey(self) -> String;
225 fn b_black(self) -> String;
227 fn b_red(self) -> String;
229 fn b_green(self) -> String;
231 fn b_yellow(self) -> String;
233 fn b_blue(self) -> String;
235 fn b_magenta(self) -> String;
237 fn b_cyan(self) -> String;
239 fn b_grey(self) -> String;
241 fn default(self) -> String;
243
244 fn blackb(self) -> String;
246 fn redb(self) -> String;
248 fn greenb(self) -> String;
250 fn yellowb(self) -> String;
252 fn blueb(self) -> String;
254 fn magentab(self) -> String;
256 fn cyanb(self) -> String;
258 fn greyb(self) -> String;
260 fn b_blackb(self) -> String;
262 fn b_redb(self) -> String;
264 fn b_greenb(self) -> String;
266 fn b_yellowb(self) -> String;
268 fn b_blueb(self) -> String;
270 fn b_magentab(self) -> String;
272 fn b_cyanb(self) -> String;
274 fn b_greyb(self) -> String;
276 fn defaultb(self) -> String;
278
279 fn underlined(self) -> String;
281 fn bold(self) -> String;
283 fn blink(self) -> String;
285 fn reverse(self) -> String;
287 fn concealed(self) -> String;
289 fn faint(self) -> String;
291 fn italic(self) -> String;
293 fn crossedout(self) -> String;
295}
296
297impl AnsiColor for String {
298 fn black(self) -> String {
300 internal::pack(Black, self)
301 }
302 fn red(self) -> String {
303 internal::pack(Red, self)
304 }
305 fn green(self) -> String {
306 internal::pack(Green, self)
307 }
308 fn yellow(self) -> String {
309 internal::pack(Yellow, self)
310 }
311 fn blue(self) -> String {
312 internal::pack(Blue, self)
313 }
314 fn magenta(self) -> String {
315 internal::pack(Magenta, self)
316 }
317 fn cyan(self) -> String {
318 internal::pack(Cyan, self)
319 }
320 fn grey(self) -> String {
321 internal::pack(Grey, self)
322 }
323 fn b_black(self) -> String {
324 internal::pack(BrightBlack, self)
325 }
326 fn b_red(self) -> String {
327 internal::pack(BrightRed, self)
328 }
329 fn b_green(self) -> String {
330 internal::pack(BrightGreen, self)
331 }
332 fn b_yellow(self) -> String {
333 internal::pack(BrightYellow, self)
334 }
335 fn b_blue(self) -> String {
336 internal::pack(BrightBlue, self)
337 }
338 fn b_magenta(self) -> String {
339 internal::pack(BrightMagenta, self)
340 }
341 fn b_cyan(self) -> String {
342 internal::pack(BrightCyan, self)
343 }
344 fn b_grey(self) -> String {
345 internal::pack(BrightGrey, self)
346 }
347 fn default(self) -> String {
348 internal::pack(Default, self)
349 }
350
351 fn blackb(self) -> String {
353 internal::pack(Blackb, self)
354 }
355 fn redb(self) -> String {
356 internal::pack(Redb, self)
357 }
358 fn greenb(self) -> String {
359 internal::pack(Greenb, self)
360 }
361 fn yellowb(self) -> String {
362 internal::pack(Yellowb, self)
363 }
364 fn blueb(self) -> String {
365 internal::pack(Blueb, self)
366 }
367 fn magentab(self) -> String {
368 internal::pack(Magentab, self)
369 }
370 fn cyanb(self) -> String {
371 internal::pack(Cyanb, self)
372 }
373 fn greyb(self) -> String {
374 internal::pack(Greyb, self)
375 }
376 fn b_blackb(self) -> String {
377 internal::pack(BrightBlackb, self)
378 }
379 fn b_redb(self) -> String {
380 internal::pack(BrightRedb, self)
381 }
382 fn b_greenb(self) -> String {
383 internal::pack(BrightGreenb, self)
384 }
385 fn b_yellowb(self) -> String {
386 internal::pack(BrightYellowb, self)
387 }
388 fn b_blueb(self) -> String {
389 internal::pack(BrightBlueb, self)
390 }
391 fn b_magentab(self) -> String {
392 internal::pack(BrightMagentab, self)
393 }
394 fn b_cyanb(self) -> String {
395 internal::pack(BrightCyanb, self)
396 }
397 fn b_greyb(self) -> String {
398 internal::pack(BrightGreyb, self)
399 }
400 fn defaultb(self) -> String {
401 internal::pack(Defaultb, self)
402 }
403
404 fn underlined(self) -> String {
406 internal::pack(Underscore, self)
407 }
408 fn bold(self) -> String {
409 internal::pack(Bold, self)
410 }
411 fn blink(self) -> String {
412 internal::pack(Blink, self)
413 }
414 fn reverse(self) -> String {
415 internal::pack(Reverse, self)
416 }
417 fn concealed(self) -> String {
418 internal::pack(Concealed, self)
419 }
420 fn faint(self) -> String {
421 internal::pack(Faint, self)
422 }
423 fn italic(self) -> String {
424 internal::pack(Italic, self)
425 }
426 fn crossedout(self) -> String {
427 internal::pack(CrossedOut, self)
428 }
429}
430
431impl AnsiColor for &'static str {
432 fn black(self) -> String {
434 String::from(self).black()
435 }
436 fn red(self) -> String {
437 String::from(self).red()
438 }
439 fn green(self) -> String {
440 String::from(self).green()
441 }
442 fn yellow(self) -> String {
443 String::from(self).yellow()
444 }
445 fn blue(self) -> String {
446 String::from(self).blue()
447 }
448 fn magenta(self) -> String {
449 String::from(self).magenta()
450 }
451 fn cyan(self) -> String {
452 String::from(self).cyan()
453 }
454 fn grey(self) -> String {
455 String::from(self).grey()
456 }
457 fn b_black(self) -> String {
458 String::from(self).b_black()
459 }
460 fn b_red(self) -> String {
461 String::from(self).b_red()
462 }
463 fn b_green(self) -> String {
464 String::from(self).b_green()
465 }
466 fn b_yellow(self) -> String {
467 String::from(self).b_yellow()
468 }
469 fn b_blue(self) -> String {
470 String::from(self).b_blue()
471 }
472 fn b_magenta(self) -> String {
473 String::from(self).b_magenta()
474 }
475 fn b_cyan(self) -> String {
476 String::from(self).b_cyan()
477 }
478 fn b_grey(self) -> String {
479 String::from(self).b_grey()
480 }
481 fn default(self) -> String {
482 String::from(self).default()
483 }
484
485 fn blackb(self) -> String {
487 String::from(self).blackb()
488 }
489 fn redb(self) -> String {
490 String::from(self).redb()
491 }
492 fn greenb(self) -> String {
493 String::from(self).greenb()
494 }
495 fn yellowb(self) -> String {
496 String::from(self).yellowb()
497 }
498 fn blueb(self) -> String {
499 String::from(self).blueb()
500 }
501 fn magentab(self) -> String {
502 String::from(self).magentab()
503 }
504 fn cyanb(self) -> String {
505 String::from(self).cyanb()
506 }
507 fn greyb(self) -> String {
508 String::from(self).greyb()
509 }
510 fn b_blackb(self) -> String {
511 String::from(self).b_blackb()
512 }
513 fn b_redb(self) -> String {
514 String::from(self).b_redb()
515 }
516 fn b_greenb(self) -> String {
517 String::from(self).b_greenb()
518 }
519 fn b_yellowb(self) -> String {
520 String::from(self).b_yellowb()
521 }
522 fn b_blueb(self) -> String {
523 String::from(self).b_blueb()
524 }
525 fn b_magentab(self) -> String {
526 String::from(self).b_magentab()
527 }
528 fn b_cyanb(self) -> String {
529 String::from(self).b_cyanb()
530 }
531 fn b_greyb(self) -> String {
532 String::from(self).b_greyb()
533 }
534 fn defaultb(self) -> String {
535 String::from(self).defaultb()
536 }
537
538 fn underlined(self) -> String {
540 String::from(self).underlined()
541 }
542 fn bold(self) -> String {
543 String::from(self).bold()
544 }
545 fn blink(self) -> String {
546 String::from(self).blink()
547 }
548 fn reverse(self) -> String {
549 String::from(self).reverse()
550 }
551 fn concealed(self) -> String {
552 String::from(self).concealed()
553 }
554 fn faint(self) -> String {
555 String::from(self).faint()
556 }
557 fn italic(self) -> String {
558 String::from(self).italic()
559 }
560 fn crossedout(self) -> String {
561 String::from(self).crossedout()
562 }
563}