Skip to content

Commit

Permalink
Support NO_COLOR.
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin-vigor committed Apr 13, 2023
1 parent 769b181 commit df81140
Showing 1 changed file with 57 additions and 6 deletions.
63 changes: 57 additions & 6 deletions src/style/types/colored.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use parking_lot::Once;
use std::fmt::{self, Formatter};
use std::sync::atomic::{AtomicBool, Ordering};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
Expand All @@ -21,6 +23,9 @@ pub enum Colored {
UnderlineColor(Color),
}

static ANSI_COLOR_DISABLED: AtomicBool = AtomicBool::new(false);
static INITIALIZER: Once = Once::new();

impl Colored {
/// Parse an ANSI foreground or background color.
/// This is the string that would appear within an `ESC [ <str> m` escape sequence, as found in
Expand Down Expand Up @@ -64,12 +69,39 @@ impl Colored {

Some(output)
}

/// Checks whether ansi color sequences are disabled by setting of NO_COLOR
/// in environment as per https://no-color.org/
pub fn ansi_color_disabled() -> bool {
!std::env::var("NO_COLOR")
.unwrap_or("".to_string())
.is_empty()
}

pub fn ansi_color_disabled_memoized() -> bool {
INITIALIZER.call_once(|| {
ANSI_COLOR_DISABLED.store(Self::ansi_color_disabled(), Ordering::SeqCst);
});

ANSI_COLOR_DISABLED.load(Ordering::SeqCst)
}

#[cfg(test)]
pub fn set_ansi_color_disabled(val: bool) {
// Force the one-time initializer to run.
_ = Self::ansi_color_disabled_memoized();
ANSI_COLOR_DISABLED.store(val, Ordering::SeqCst);
}
}

impl fmt::Display for Colored {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let color;

if Self::ansi_color_disabled_memoized() {
return Ok(());
}

match *self {
Colored::ForegroundColor(new_color) => {
if new_color == Color::Reset {
Expand Down Expand Up @@ -125,40 +157,47 @@ impl fmt::Display for Colored {
mod tests {
use crate::style::{Color, Colored};

fn check_format_color(colored: Colored, expected: &str) {
Colored::set_ansi_color_disabled(true);
assert_eq!(colored.to_string(), "");
Colored::set_ansi_color_disabled(false);
assert_eq!(colored.to_string(), expected);
}

#[test]
fn test_format_fg_color() {
let colored = Colored::ForegroundColor(Color::Red);
assert_eq!(colored.to_string(), "38;5;9");
check_format_color(colored, "38;5;9");
}

#[test]
fn test_format_bg_color() {
let colored = Colored::BackgroundColor(Color::Red);
assert_eq!(colored.to_string(), "48;5;9");
check_format_color(colored, "48;5;9");
}

#[test]
fn test_format_reset_fg_color() {
let colored = Colored::ForegroundColor(Color::Reset);
assert_eq!(colored.to_string(), "39");
check_format_color(colored, "39");
}

#[test]
fn test_format_reset_bg_color() {
let colored = Colored::BackgroundColor(Color::Reset);
assert_eq!(colored.to_string(), "49");
check_format_color(colored, "49");
}

#[test]
fn test_format_fg_rgb_color() {
let colored = Colored::BackgroundColor(Color::Rgb { r: 1, g: 2, b: 3 });
assert_eq!(colored.to_string(), "48;2;1;2;3");
check_format_color(colored, "48;2;1;2;3");
}

#[test]
fn test_format_fg_ansi_color() {
let colored = Colored::ForegroundColor(Color::AnsiValue(255));
assert_eq!(colored.to_string(), "38;5;255");
check_format_color(colored, "38;5;255");
}

#[test]
Expand Down Expand Up @@ -267,4 +306,16 @@ mod tests {
test("48;2;0;2;25;");
test("48;2;0;2;25;3");
}

#[test]
fn test_NO_COLOR() {
std::env::set_var("NO_COLOR", "1");
assert!(Colored::ansi_color_disabled());
std::env::set_var("NO_COLOR", "XXX");
assert!(Colored::ansi_color_disabled());
std::env::set_var("NO_COLOR", "");
assert!(!Colored::ansi_color_disabled());
std::env::remove_var("NO_COLOR");
assert!(!Colored::ansi_color_disabled());
}
}

0 comments on commit df81140

Please sign in to comment.