prettylogger/
colors.rs

1//! Contains cosmetic, color-related utilities.
2
3/// Contains various color-related utilities for cosmetic customization.
4use std::{
5    collections::HashMap,
6    fmt::{Display, Formatter},
7};
8use serde::{Serialize, Deserialize};
9use lazy_static::lazy_static;
10
11/// Represents different colors. Used to color text or modify the appearance of
12/// log headers.
13///
14/// # Examples
15///
16/// Using a standard `Color` to customize log header appearance:
17/// ```rust
18/// # use prettylogger::{
19/// #     Logger,
20/// #     colors::Color,
21/// # };
22/// let mut logger = Logger::default();
23///
24/// logger.formatter.lock().unwrap().set_debug_color(Color::Gray);
25/// logger.formatter.lock().unwrap().set_info_color(Color::Green);
26/// logger.formatter.lock().unwrap().set_warning_color(Color::Yellow);
27/// logger.formatter.lock().unwrap().set_error_color(Color::Red);
28/// logger.formatter.lock().unwrap().set_fatal_color(Color::Magenta);
29/// ```
30///
31/// Using a custom `Color` to customize log header appearance:
32/// ```rust
33/// # use prettylogger::{
34/// #     Logger,
35/// #     colors::Color,
36/// # };
37/// let mut logger = Logger::default();
38///
39/// // Set a **bold white** color
40/// logger.formatter.lock().unwrap()
41///     .set_debug_color(Color::Custom(String::from("\x1b[97m")));
42/// ```
43#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default,
44    Serialize, Deserialize)]
45#[repr(i32)]
46pub enum Color
47{
48    None = 0,
49    Black = 1,
50    #[default]
51    Blue = 2,
52    Cyan = 3,
53    Green = 4,
54    Gray = 5,
55    Magenta = 6,
56    Red = 7,
57    White = 8,
58    Yellow = 9,
59
60    Custom(String) = 10,
61}
62
63static BLACK: &str = "\x1b[30m";
64static BLUE: &str = "\x1b[34m";
65static CYAN: &str = "\x1b[36m";
66static GREEN: &str = "\x1b[32m";
67static GRAY: &str = "\x1b[90m";
68static MAGENTA: &str = "\x1b[35m";
69static RED: &str = "\x1b[31m";
70static WHITE: &str = "\x1b[37m";
71static YELLOW: &str = "\x1b[33m";
72
73pub(crate) static RESET: &str = "\x1b[0m";
74
75lazy_static! {
76    static ref COLOR_MAP: HashMap<i32, &'static str> =  {
77        let mut m = HashMap::new();
78        m.insert(Color::None.into(), "");
79        m.insert(Color::Black.into(), BLACK);
80        m.insert(Color::Blue.into(), BLUE);
81        m.insert(Color::Cyan.into(), CYAN);
82        m.insert(Color::Green.into(), GREEN);
83        m.insert(Color::Gray.into(), GRAY);
84        m.insert(Color::Magenta.into(), MAGENTA);
85        m.insert(Color::Red.into(), RED);
86        m.insert(Color::White.into(), WHITE);
87        m.insert(Color::Yellow.into(), YELLOW);
88        return m;
89    };
90}
91
92/// Colors given text based on `color` value using ANSII escape codes.
93///
94/// # Examples
95///
96/// Using a `Color` enum to color text:
97/// ```
98/// # use prettylogger::colors::{Color, color_text};
99/// let colored_text = color_text("some text", Color::Red);
100/// # assert_eq!(colored_text, "\x1b[31msome text\x1b[0m");
101/// ```
102///
103/// Using a custom `Color` to color text:
104/// ```
105/// # use prettylogger::colors::{Color, color_text};
106/// let colored_text = color_text("some text",
107///     Color::Custom(String::from("\x1b[97m")));
108/// # assert_eq!(colored_text, "\x1b[97msome text\x1b[0m");
109/// ```
110pub fn color_text(text: &str, color: Color) -> String {
111    match color {
112        Color::Custom(s) => {
113            return s + text + RESET;
114        },
115        _ => {
116            if color != Color::None {
117                return COLOR_MAP[&(color.into())].to_string() + text + RESET;
118            }
119            else{
120                return String::from(text)
121            }
122        }
123    }
124}
125
126impl Display for Color {
127    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
128        let level_str = match self {
129            Color::None => "None",
130            Color:: Black => "Black",
131            Color::Blue => "Blue",
132            Color::Cyan => "Cyan",
133            Color::Green => "Green",
134            Color::Gray => "Gray",
135            Color::Magenta => "Magenta",
136            Color::Red => "Red",
137            Color::White => "White",
138            Color::Yellow => "Yellow",
139
140            Color::Custom(str) => &format!("'{}'", str)
141        };
142        return write!(f, "{}", level_str)
143    }
144}
145
146impl TryFrom<i32> for Color {
147    type Error = &'static str;
148    fn try_from(value: i32) -> Result<Self, Self::Error> {
149        match value {
150            0 => Ok(Color::None),
151            1 => Ok(Color::Black),
152            2 => Ok(Color::Blue),
153            3 => Ok(Color::Cyan),
154            4 => Ok(Color::Green),
155            5 => Ok(Color::Gray),
156            6 => Ok(Color::Magenta),
157            7 => Ok(Color::Red),
158            8 => Ok(Color::White),
159            9 => Ok(Color::Yellow),
160            18 => {Ok(Color::Custom(String::new()))}
161            _ => Err("Invalid value! Please provide a value in range 0-9."),
162        }
163    }
164}
165
166impl From<Color> for i32 {
167    fn from(color: Color) -> Self {
168        match color {
169            Color::None => 0,
170            Color::Black => 1,
171            Color::Blue => 2,
172            Color::Cyan => 3,
173            Color::Green => 4,
174            Color::Gray => 5,
175            Color::Magenta => 6,
176            Color::Red => 7,
177            Color::White => 8,
178            Color::Yellow => 9,
179            Color::Custom(_) => 10,
180        }
181    }
182}
183
184impl AsRef<str> for Color {
185    fn as_ref(&self) -> &str {
186        match self {
187            Color::None => "None",
188            Color:: Black => "Black",
189            Color::Blue => "Blue",
190            Color::Cyan => "Cyan",
191            Color::Green => "Green",
192            Color::Gray => "Gray",
193            Color::Magenta => "Magenta",
194            Color::Red => "Red",
195            Color::White => "White",
196            Color::Yellow => "Yellow",
197            Color::Custom(str) => str.as_str(),
198        }
199    }
200}