use std::sync::atomic::{AtomicBool, Ordering};
static COLOR: AtomicBool = AtomicBool::new(true);
pub fn init() {
let enabled = std::env::var_os("NO_COLOR").is_none();
COLOR.store(enabled, Ordering::Relaxed);
}
fn color_enabled() -> bool {
COLOR.load(Ordering::Relaxed)
}
fn paint(code: &str, s: &str) -> String {
if color_enabled() {
format!("\x1b[{code}m{s}\x1b[0m")
} else {
s.to_string()
}
}
pub fn bold(s: &str) -> String {
paint("1", s)
}
pub fn dim(s: &str) -> String {
paint("2", s)
}
pub fn green(s: &str) -> String {
paint("32", s)
}
pub fn red(s: &str) -> String {
paint("31", s)
}
pub fn yellow(s: &str) -> String {
paint("33", s)
}
pub fn cyan(s: &str) -> String {
paint("36", s)
}
pub const CHECK: &str = "\u{2713}"; pub const CROSS: &str = "\u{2717}"; pub const ARROW: &str = "\u{25b6}"; pub const DOT: &str = "\u{2022}";
pub const PIPE_OUT: &str = "\u{2502}"; pub const PIPE_ERR: &str = "\u{2506}";
pub fn emit(chunk: &str) {
use std::io::Write;
let stdout = std::io::stdout();
let mut handle = stdout.lock();
let _ = handle.write_all(chunk.as_bytes());
let _ = handle.flush();
}
pub fn banner(subtitle: &str) {
println!("{} {}", bold(&cyan("Flux")), dim(subtitle));
}
pub fn field(key: &str, value: &str) {
println!(" {} {}", dim(&format!("{key}:")), value);
}
pub fn heading(text: &str) {
println!("\n{}", bold(text));
}
pub fn ok_line(text: &str) {
println!(" {} {}", green(CHECK), text);
}
pub fn fail_line(text: &str) {
println!(" {} {}", red(CROSS), text);
}
pub fn info_line(text: &str) {
emit(&format!("{text}\n"));
}
pub fn warn_line(text: &str) {
eprintln!(" {} {}", yellow("warning:"), text);
}