use std::borrow::Cow;
use std::env;
use std::sync::LazyLock;
#[allow(unreachable_code)]
pub static NO_COLOR: LazyLock<bool> = LazyLock::new(|| {
#[cfg(test)]
{
return false;
}
env::var_os("NO_COLOR").is_some_and(|v| !v.is_empty())
});
pub const ERROR: &str = "\x1b[0;91m";
pub const HIGHLIGHT: &str = "\x1b[0;92m";
pub const ATTENUATE: &str = "\x1b[0;90m";
pub const TITLE: &str = "\x1b[1;4m";
pub const RESET: &str = "\x1b[0m";
pub struct Color;
impl Color {
#[must_use]
pub fn error(string: &str) -> Cow<str> {
Self::color(ERROR, string)
}
#[must_use]
pub fn highlight(string: &str) -> Cow<str> {
Self::color(HIGHLIGHT, string)
}
#[must_use]
pub fn attenuate(string: &str) -> Cow<str> {
Self::color(ATTENUATE, string)
}
#[must_use]
pub fn title(string: &str) -> Cow<str> {
Self::color(TITLE, string)
}
#[must_use]
fn color<'a>(color: &str, string: &'a str) -> Cow<'a, str> {
if *NO_COLOR {
#[cfg(not(tarpaulin_include))] return Cow::Borrowed(string);
}
Cow::Owned(format!("{color}{string}{RESET}"))
}
#[must_use]
pub fn maybe_color(color: &str) -> &str {
if *NO_COLOR {
#[cfg(not(tarpaulin_include))] return "";
}
color
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn color_error_is_red() {
assert_eq!(
Color::error("this is marked as error"),
"\x1b[0;91mthis is marked as error\x1b[0m"
);
}
#[test]
fn color_highlight_is_green() {
assert_eq!(
Color::highlight("this is highlighted"),
"\x1b[0;92mthis is highlighted\x1b[0m"
);
}
#[test]
fn color_attenuate_is_grey() {
assert_eq!(
Color::attenuate("this is attenuated"),
"\x1b[0;90mthis is attenuated\x1b[0m"
);
}
#[test]
fn color_title_is_bold_underlined() {
assert_eq!(
Color::title("this is bold, and underlined"),
"\x1b[1;4mthis is bold, and underlined\x1b[0m"
);
}
}