use std::io::IsTerminal;
use std::sync::OnceLock;
const SAGE: (u8, u8, u8) = (127, 176, 105); const CORAL: (u8, u8, u8) = (230, 126, 94); const AMBER: (u8, u8, u8) = (217, 165, 92); const TEAL: (u8, u8, u8) = (107, 164, 160);
fn color_enabled() -> bool {
static ENABLED: OnceLock<bool> = OnceLock::new();
*ENABLED.get_or_init(|| {
if std::env::var_os("NO_COLOR").is_some() {
return false;
}
if matches!(std::env::var("TERM").as_deref(), Ok("dumb")) {
return false;
}
if std::env::var_os("FORCE_COLOR").is_some() || std::env::var_os("CLICOLOR_FORCE").is_some()
{
return true;
}
std::io::stdout().is_terminal()
})
}
fn paint_rgb(rgb: (u8, u8, u8), s: &str) -> String {
if color_enabled() {
format!("\x1b[38;2;{};{};{}m{s}\x1b[0m", rgb.0, rgb.1, rgb.2)
} else {
s.to_string()
}
}
fn paint_sgr(code: &str, s: &str) -> String {
if color_enabled() {
format!("\x1b[{code}m{s}\x1b[0m")
} else {
s.to_string()
}
}
pub fn green(s: &str) -> String {
paint_rgb(SAGE, s)
}
pub fn red(s: &str) -> String {
paint_rgb(CORAL, s)
}
pub fn yellow(s: &str) -> String {
paint_rgb(AMBER, s)
}
pub fn cyan(s: &str) -> String {
paint_rgb(TEAL, s)
}
pub fn dim(s: &str) -> String {
paint_sgr("2", s)
}
pub fn bold(s: &str) -> String {
paint_sgr("1", s)
}
pub fn ok_mark() -> String {
green("✓")
}
pub fn fail_mark() -> String {
red("✗")
}
pub fn skip_mark() -> String {
yellow("-")
}
pub fn arrow() -> String {
dim("→")
}