use std::cell::RefCell;
#[cfg(test)]
mod test;
thread_local! {
static COLOR_CONTEXT:RefCell<Vec<String>> = RefCell::new(vec![String::from("\x1b[37m")]);
}
#[allow(dead_code)]
pub struct ColorContext;
#[allow(dead_code)]
impl ColorContext {
pub fn push(color: &str) {
COLOR_CONTEXT.with(|ctx| ctx.borrow_mut().push(color.to_string()));
}
pub fn pop() {
COLOR_CONTEXT.with(|ctx| {
ctx.borrow_mut().pop();
})
}
pub fn current_color() -> String {
COLOR_CONTEXT.with(|ctx| {
ctx.borrow()
.last()
.cloned()
.unwrap_or_else(|| String::from("\x1b[37m"))
})
}
}
pub fn hsl_to_rgb(h: f64, s: f64, l: f64) -> (u8, u8, u8) {
let c: f64 = (1.0 - (2.0 * l - 1.0).abs()) * s;
let x: f64 = c * (1.0 - ((h / 60.0) % 2.0 - 1.0).abs());
let m: f64 = l - c / 2.0;
let (r, g, b): (f64, f64, f64) = match h {
h if h >= 0.0 && h < 60.0 => (c, x, 0.0),
h if h >= 60.0 && h < 120.0 => (x, c, 0.0),
h if h >= 120.0 && h < 180.0 => (0.0, c, x),
h if h >= 180.0 && h < 240.0 => (0.0, x, c),
h if h >= 240.0 && h < 300.0 => (x, 0.0, c),
h if h >= 300.0 && h <= 360.0 => (c, 0.0, x),
_ => (0.0, 0.0, 0.0),
};
let r: u8 = ((r + m) * 255.0).round() as u8;
let g: u8 = ((g + m) * 255.0).round() as u8;
let b: u8 = ((b + m) * 255.0).round() as u8;
(r, g, b)
}
pub fn hsv_to_rgb(h: f64, s: f64, v: f64) -> (u8, u8, u8) {
let c: f64 = v * s;
let x: f64 = c * (1.0 - ((h / 60.0) % 2.0 - 1.0).abs());
let m: f64 = v - c;
let (r, g, b): (f64, f64, f64) = match h {
h if h >= 0.0 && h < 60.0 => (c, x, 0.0),
h if h >= 60.0 && h < 120.0 => (x, c, 0.0),
h if h >= 120.0 && h < 180.0 => (0.0, c, x),
h if h >= 180.0 && h < 240.0 => (0.0, x, c),
h if h >= 240.0 && h < 300.0 => (x, 0.0, c),
h if h >= 300.0 && h <= 360.0 => (c, 0.0, x),
_ => (0.0, 0.0, 0.0),
};
let r: u8 = ((r + m) * 255.0).round() as u8;
let g: u8 = ((g + m) * 255.0).round() as u8;
let b: u8 = ((b + m) * 255.0).round() as u8;
(r, g, b)
}
pub fn reset_all() -> &'static str {
"\x1b[0m"
}
#[macro_export]
macro_rules! apply_color {
($color_code:expr,$($arg:tt)*) => {{
$crate::ColorContext::push($color_code);
let result = format!("{}{}{}",$color_code,format!($($arg)*),$crate::reset_all());
$crate::ColorContext::pop();
format!("{}{}",result,$crate::ColorContext::current_color())
}};
}
#[macro_export]
macro_rules! bg_red {
($($arg:tt)*) => {{
$crate::apply_color!("\x1b[41m",$($arg)*)
}};
}
#[macro_export]
macro_rules! bg_blue {
($($arg:tt)*) => {{
$crate::apply_color!("\x1b[44m",$($arg)*)
}};
}
#[macro_export]
macro_rules! bg_green {
($($arg:tt)*) => {{
$crate::apply_color!("\x1b[42m",$($arg)*)
}};
}
#[macro_export]
macro_rules! bg_yellow {
($($arg:tt)*) => {{
$crate::apply_color!("\x1b[43m",$($arg)*)
}};
}
#[macro_export]
macro_rules! bg_gray {
($($arg:tt)*) => {{
$crate::apply_color!("\x1b[100m",$($arg)*)
}};
}
#[macro_export]
macro_rules! black {
($($arg:tt)*) => {{
$crate::apply_color!("\x1b[90m",$($arg)*)
}};
}
#[macro_export]
macro_rules! red {
($($arg:tt)*) => {{
$crate::apply_color!("\x1b[31m",$($arg)*)
}};
}
#[macro_export]
macro_rules! blue {
($($arg:tt)*) => {{
$crate::apply_color!("\x1b[34m",$($arg)*)
}};
}
#[macro_export]
macro_rules! green {
($($arg:tt)*) => {{
$crate::apply_color!("\x1b[32m",$($arg)*)
}};
}
#[macro_export]
macro_rules! yellow {
($($arg:tt)*) => {{
$crate::apply_color!("\x1b[33m",$($arg)*)
}};
}
#[macro_export]
macro_rules! white {
($($arg:tt)*) => {{
$crate::apply_color!("\x1b[37m",$($arg)*)
}};
}
#[macro_export]
macro_rules! underline {
($($arg:tt)*) => {
{
$crate::apply_color!("\033[4m",$($arg)*)
}
};
}
#[macro_export]
macro_rules! bold {
($($arg:tt)*) => {{
$crate::apply_color!("\033[1m",$($arg)*)}
};
}
#[macro_export]
macro_rules! italic {
($($arg:tt)*) => {
{
$crate::apply_color!("\033[3m",$($arg)*)
}
};
}
#[macro_export]
macro_rules! rgb {
($r:expr,$g:expr,$b:expr,$($arg:tt)*) => {{
let color_code = format!("\x1b[38;2;{};{};{}m", $r, $g, $b);
$crate::apply_color!(&color_code,$($arg)*)
}};
}
#[macro_export]
macro_rules! hsl {
($h:expr,$s:expr,$l:expr,$($arg:tt)*) => {{
let (r,g,b) = $crate::hsl_to_rgb($h,$s,$l);
$crate::rgb!(r,g,b,$($arg)*)
}};
}
#[macro_export]
macro_rules! hsv {
($h:expr,$s:expr,$v:expr,$($arg:tt)*) => {{
let (r,g,b) = $crate::hsv_to_rgb($h,$s,$v);
$crate::rgb!(r,g,b,$($arg)*)
}};
}
#[macro_export]
macro_rules! bg_rgb {
($r:expr, $g:expr, $b:expr, $($arg:tt)*) => {{
let color_code = format!("\x1b[48;2;{};{};{}m", $r, $g, $b);
$crate::apply_color!(&color_code, $($arg)*)
}};
}
#[macro_export]
macro_rules! bg_hsl {
($h:expr, $s:expr, $l:expr, $($arg:tt)*) => {{
let (r, g, b) = $crate::hsl_to_rgb($h, $s, $l);
$crate::bg_rgb!(r, g, b, $($arg)*)
}};
}
#[macro_export]
macro_rules! bg_hsv {
($h:expr, $s:expr, $v:expr, $($arg:tt)*) => {{
let (r, g, b) = $crate::hsv_to_rgb($h, $s, $v);
$crate::bg_rgb!(r, g, b, $($arg)*)
}};
}