microfetch/crates/lib/src/colors.rs
2026-06-10 21:18:41 +02:00

122 lines
3 KiB
Rust

include!(concat!(env!("OUT_DIR"), "/colors_config.rs"));
use alloc::string::String;
/// Color codes for terminal output
pub struct Colors {
pub reset: &'static str,
pub blue: &'static str,
pub cyan: &'static str,
pub green: &'static str,
pub yellow: &'static str,
pub red: &'static str,
pub magenta: &'static str,
pub l1: &'static str,
pub l2: &'static str,
pub icon: &'static str,
pub key: &'static str,
pub value: &'static str,
}
impl Colors {
#[must_use]
pub const fn new(is_no_color: bool) -> Self {
if is_no_color {
Self {
reset: "",
blue: "",
cyan: "",
green: "",
yellow: "",
red: "",
magenta: "",
l1: "",
l2: "",
icon: "",
key: "",
value: "",
}
} else {
Self {
reset: "\x1b[0m",
blue: "\x1b[34m",
cyan: "\x1b[36m",
green: "\x1b[32m",
yellow: "\x1b[33m",
red: "\x1b[31m",
magenta: "\x1b[35m",
l1: COLOR_LOGO1,
l2: COLOR_LOGO2,
icon: COLOR_ICON,
key: COLOR_KEY,
value: COLOR_VAL,
}
}
}
}
use core::sync::atomic::{AtomicBool, Ordering};
// Check if NO_COLOR is set (only once, lazily)
// Only presence matters; value is irrelevant per the NO_COLOR spec
static NO_COLOR_CHECKED: AtomicBool = AtomicBool::new(false);
static NO_COLOR_SET: AtomicBool = AtomicBool::new(false);
/// Checks if `NO_COLOR` environment variable is set.
pub(crate) fn is_no_color() -> bool {
// Fast path: already checked
if NO_COLOR_CHECKED.load(Ordering::Acquire) {
return NO_COLOR_SET.load(Ordering::Relaxed);
}
// Slow path: check environment
let is_set = crate::env_exists("NO_COLOR");
NO_COLOR_SET.store(is_set, Ordering::Relaxed);
NO_COLOR_CHECKED.store(true, Ordering::Release);
is_set
}
#[must_use]
#[cfg_attr(feature = "hotpath", hotpath::measure)]
pub fn print_dots() -> String {
const GLYPH: &str = "";
let colors = if is_no_color() {
Colors::new(true)
} else {
Colors::new(false)
};
// Pre-calculate capacity: 6 color codes + " " (glyph + 2 spaces) per color
let capacity = colors.blue.len()
+ colors.cyan.len()
+ colors.green.len()
+ colors.yellow.len()
+ colors.red.len()
+ colors.magenta.len()
+ colors.reset.len()
+ (GLYPH.len() + 2) * 6;
let mut result = String::with_capacity(capacity);
result.push_str(colors.blue);
result.push_str(GLYPH);
result.push_str(" ");
result.push_str(colors.cyan);
result.push_str(GLYPH);
result.push_str(" ");
result.push_str(colors.green);
result.push_str(GLYPH);
result.push_str(" ");
result.push_str(colors.yellow);
result.push_str(GLYPH);
result.push_str(" ");
result.push_str(colors.red);
result.push_str(GLYPH);
result.push_str(" ");
result.push_str(colors.magenta);
result.push_str(GLYPH);
result.push_str(" ");
result.push_str(colors.reset);
result
}