prettylogger/
colors.rs

1//! Contains cosmetic color-related utilities.
2
3/// Contains various color-related utilities for cosmetic customization.
4
5use std::collections::HashMap;
6use serde::{Serialize, Deserialize};
7use lazy_static::lazy_static;
8use std::fmt::{Display, Formatter};
9
10#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default,
11    Serialize, Deserialize)]
12/// Represents different colors. Used to color text or set log header colors.
13pub enum Color
14{
15    None = 0,
16    Black = 1,
17    #[default]
18    Blue = 2,
19    Cyan = 3,
20    Green = 4,
21    Gray = 5,
22    Magenta = 6,
23    Red = 7,
24    White = 8,
25    Yellow = 9,
26}
27
28static BLACK: &str = "\x1b[30m";
29static BLUE: &str = "\x1b[34m";
30static CYAN: &str = "\x1b[36m";
31static GREEN: &str = "\x1b[32m";
32static GRAY: &str = "\x1b[90m";
33static MAGENTA: &str = "\x1b[35m";
34static RED: &str = "\x1b[31m";
35static WHITE: &str = "\x1b[37m";
36static YELLOW: &str = "\x1b[33m";
37pub(crate) static RESET: &str = "\x1b[0m";
38
39lazy_static! {
40    static ref COLOR_MAP: HashMap<i32, &'static str> =  {
41        let mut m = HashMap::new();
42        m.insert(Color::None as i32, "");
43        m.insert(Color::Black as i32, BLACK);
44        m.insert(Color::Blue as i32, BLUE);
45        m.insert(Color::Cyan as i32, CYAN);
46        m.insert(Color::Green as i32, GREEN);
47        m.insert(Color::Gray as i32, GRAY);
48        m.insert(Color::Magenta as i32, MAGENTA);
49        m.insert(Color::Red as i32, RED);
50        m.insert(Color::White as i32, WHITE);
51        m.insert(Color::Yellow as i32, YELLOW);
52        return m;
53    };
54}
55
56/// Colors the given text based on `color` value using ANSII escape codes.
57///
58/// # Example
59/// ```
60/// # use prettylogger::colors::{Color, color_text};
61/// let colored_text = color_text("a piece of text", Color::Red);
62/// assert_eq!(colored_text, "\x1b[31ma piece of text\x1b[0m");
63/// ```
64pub fn color_text(text: &str, color: Color) -> String {
65    if color != Color::None {
66        return COLOR_MAP[&(color as i32)].to_string() + text + RESET;
67    }
68    return String::from(text);
69}
70
71impl Display for Color {
72    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
73        let level_str = match *self {
74            Color::None => "None",
75            Color:: Black => "Black",
76            Color::Blue => "Blue",
77            Color::Cyan => "Cyan",
78            Color::Green => "Green",
79            Color::Gray => "Gray",
80            Color::Magenta => "Magenta",
81            Color::Red => "Red",
82            Color::White => "White",
83            Color::Yellow => "Yellow",
84        };
85        write!(f, "{}", level_str)
86    }
87}
88
89impl TryFrom<i32> for Color {
90    type Error = &'static str;
91    fn try_from(value: i32) -> Result<Self, Self::Error> {
92        match value {
93            0 => Ok(Color::None),
94            1 => Ok(Color::Black),
95            2 => Ok(Color::Blue),
96            3 => Ok(Color::Cyan),
97            4 => Ok(Color::Green),
98            5 => Ok(Color::Gray),
99            6 => Ok(Color::Magenta),
100            7 => Ok(Color::Red),
101            8 => Ok(Color::White),
102            9 => Ok(Color::Yellow),
103            _ => Err("Invalid value! Please provide a value in range 0-9."),
104        }
105    }
106}
107
108impl AsRef<str> for Color {
109    fn as_ref(&self) -> &str {
110        match self {
111            Color::None => "None",
112            Color::Black => "Black",
113            Color::Blue => "Blue",
114            Color::Cyan => "Cyan",
115            Color::Green => "Green",
116            Color::Gray => "Gray",
117            Color::Magenta => "Magenta",
118            Color::Red => "Red",
119            Color::White => "White",
120            Color::Yellow => "Yellow",
121        }
122    }
123}