#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Color {
Reset,
Black,
Red,
Green,
Yellow,
Blue,
Magenta,
Cyan,
White,
BrightBlack,
BrightRed,
BrightGreen,
BrightYellow,
BrightBlue,
BrightMagenta,
BrightCyan,
BrightWhite,
}
impl Color {
pub fn code(&self) -> &'static str {
match self {
Color::Reset => "\x1b[0m",
Color::Black => "\x1b[30m",
Color::Red => "\x1b[31m",
Color::Green => "\x1b[32m",
Color::Yellow => "\x1b[33m",
Color::Blue => "\x1b[34m",
Color::Magenta => "\x1b[35m",
Color::Cyan => "\x1b[36m",
Color::White => "\x1b[37m",
Color::BrightBlack => "\x1b[90m",
Color::BrightRed => "\x1b[91m",
Color::BrightGreen => "\x1b[92m",
Color::BrightYellow => "\x1b[93m",
Color::BrightBlue => "\x1b[94m",
Color::BrightMagenta => "\x1b[95m",
Color::BrightCyan => "\x1b[96m",
Color::BrightWhite => "\x1b[97m",
}
}
pub fn colorize(text: &str, color: Color) -> String {
format!("{}{}{}", color.code(), text, Color::Reset.code())
}
pub fn colorize_bg(text: &str, bg_color: Color) -> String {
let bg_code = match bg_color {
Color::Black => "\x1b[40m",
Color::Red => "\x1b[41m",
Color::Green => "\x1b[42m",
Color::Yellow => "\x1b[43m",
Color::Blue => "\x1b[44m",
Color::Magenta => "\x1b[45m",
Color::Cyan => "\x1b[46m",
Color::White => "\x1b[47m",
Color::BrightBlack => "\x1b[100m",
Color::BrightRed => "\x1b[101m",
Color::BrightGreen => "\x1b[102m",
Color::BrightYellow => "\x1b[103m",
Color::BrightBlue => "\x1b[104m",
Color::BrightMagenta => "\x1b[105m",
Color::BrightCyan => "\x1b[106m",
Color::BrightWhite => "\x1b[107m",
_ => "\x1b[49m", };
format!("{}{}{}", bg_code, text, Color::Reset.code())
}
pub fn colorize_full(text: &str, fg_color: Color, bg_color: Color) -> String {
let bg_code = match bg_color {
Color::Black => "\x1b[40m",
Color::Red => "\x1b[41m",
Color::Green => "\x1b[42m",
Color::Yellow => "\x1b[43m",
Color::Blue => "\x1b[44m",
Color::Magenta => "\x1b[45m",
Color::Cyan => "\x1b[46m",
Color::White => "\x1b[47m",
Color::BrightBlack => "\x1b[100m",
Color::BrightRed => "\x1b[101m",
Color::BrightGreen => "\x1b[102m",
Color::BrightYellow => "\x1b[103m",
Color::BrightBlue => "\x1b[104m",
Color::BrightMagenta => "\x1b[105m",
Color::BrightCyan => "\x1b[106m",
Color::BrightWhite => "\x1b[107m",
_ => "",
};
format!("{}{}{}{}", fg_color.code(), bg_code, text, Color::Reset.code())
}
pub fn is_supported() -> bool {
true
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LogColorScheme {
pub debug: Color,
pub info: Color,
pub warn: Color,
pub error: Color,
pub critical: Color,
}
impl Default for LogColorScheme {
fn default() -> Self {
LogColorScheme {
debug: Color::Cyan,
info: Color::Green,
warn: Color::Yellow,
error: Color::Red,
critical: Color::BrightRed,
}
}
}
impl LogColorScheme {
pub fn new(debug: Color, info: Color, warn: Color, error: Color, critical: Color) -> Self {
LogColorScheme {
debug,
info,
warn,
error,
critical,
}
}
pub fn get_color(&self, level: crate::level::LogLevel) -> Color {
match level {
crate::level::LogLevel::Debug => self.debug,
crate::level::LogLevel::Info => self.info,
crate::level::LogLevel::Warn => self.warn,
crate::level::LogLevel::Error => self.error,
crate::level::LogLevel::Critical => self.critical,
}
}
pub fn colorize_message(&self, level: crate::level::LogLevel, message: &str, use_colors: bool) -> String {
if use_colors && Color::is_supported() {
let color = self.get_color(level);
Color::colorize(message, color)
} else {
message.to_string()
}
}
pub fn colorize_log_line(&self, timestamp: &str, level: crate::level::LogLevel, message: &str, use_colors: bool) -> String {
if use_colors && Color::is_supported() {
let level_str = level.to_string();
let color = self.get_color(level);
let colored_level = Color::colorize(&format!("[{}]", level_str), color);
format!("[{}] {} {}", timestamp, colored_level, message)
} else {
format!("[{}] [{}] {}", timestamp, level, message)
}
}
}
pub struct ColorFormatter {
scheme: LogColorScheme,
enabled: std::sync::Mutex<bool>,
}
impl ColorFormatter {
pub fn new() -> Self {
ColorFormatter {
scheme: LogColorScheme::default(),
enabled: std::sync::Mutex::new(true),
}
}
pub fn with_scheme(scheme: LogColorScheme) -> Self {
ColorFormatter {
scheme,
enabled: std::sync::Mutex::new(true),
}
}
pub fn set_enabled(&self, enabled: bool) {
*self.enabled.lock().unwrap() = enabled;
}
pub fn is_enabled(&self) -> bool {
*self.enabled.lock().unwrap()
}
pub fn format(&self, timestamp: &str, level: crate::level::LogLevel, message: &str, for_console: bool) -> String {
if for_console && *self.enabled.lock().unwrap() {
self.scheme.colorize_log_line(timestamp, level, message, true)
} else {
format!("[{}] [{}] {}", timestamp, level, message)
}
}
pub fn format_message(&self, level: crate::level::LogLevel, message: &str, for_console: bool) -> String {
if for_console && *self.enabled.lock().unwrap() {
self.scheme.colorize_message(level, message, true)
} else {
message.to_string()
}
}
}
impl Default for ColorFormatter {
fn default() -> Self {
ColorFormatter::new()
}
}