use std::io::IsTerminal;
use std::sync::OnceLock;
const RED: &str = "\x1b[0;31m";
const GREEN: &str = "\x1b[0;32m";
const YELLOW: &str = "\x1b[0;33m";
const DIM: &str = "\x1b[2m";
const BOLD: &str = "\x1b[1m";
const OFF: &str = "\x1b[0m";
pub fn styled() -> bool {
static DECIDED: OnceLock<bool> = OnceLock::new();
*DECIDED.get_or_init(|| {
if std::env::var_os("CLICOLOR_FORCE").is_some_and(|v| v != "0") {
return true;
}
if std::env::var_os("NO_COLOR").is_some() {
return false;
}
if std::env::var("TERM").is_ok_and(|t| t == "dumb") {
return false;
}
std::io::stdout().is_terminal()
})
}
fn paint(colour: &str, text: &str) -> String {
if styled() {
format!("{colour}{text}{OFF}")
} else {
text.to_string()
}
}
pub fn red(text: &str) -> String {
paint(RED, text)
}
pub fn green(text: &str) -> String {
paint(GREEN, text)
}
pub fn yellow(text: &str) -> String {
paint(YELLOW, text)
}
pub fn dim(text: &str) -> String {
paint(DIM, text)
}
pub fn bold(text: &str) -> String {
paint(BOLD, text)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_pipe_gets_no_escape_sequences() {
assert!(!styled(), "styling was enabled for a non-terminal stdout");
for painted in [red("x"), green("x"), yellow("x"), dim("x"), bold("x")] {
assert_eq!(painted, "x", "an escape sequence reached a pipe");
}
}
}