Support NO_COLOR. (#782)
This commit is contained in:
parent
dfc67e54c8
commit
2c534fc69e
@ -1,4 +1,6 @@
|
|||||||
|
use parking_lot::Once;
|
||||||
use std::fmt::{self, Formatter};
|
use std::fmt::{self, Formatter};
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -21,6 +23,9 @@ pub enum Colored {
|
|||||||
UnderlineColor(Color),
|
UnderlineColor(Color),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ANSI_COLOR_DISABLED: AtomicBool = AtomicBool::new(false);
|
||||||
|
static INITIALIZER: Once = Once::new();
|
||||||
|
|
||||||
impl Colored {
|
impl Colored {
|
||||||
/// Parse an ANSI foreground or background color.
|
/// Parse an ANSI foreground or background color.
|
||||||
/// This is the string that would appear within an `ESC [ <str> m` escape sequence, as found in
|
/// This is the string that would appear within an `ESC [ <str> m` escape sequence, as found in
|
||||||
@ -64,12 +69,39 @@ impl Colored {
|
|||||||
|
|
||||||
Some(output)
|
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 {
|
impl fmt::Display for Colored {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
let color;
|
let color;
|
||||||
|
|
||||||
|
if Self::ansi_color_disabled_memoized() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Colored::ForegroundColor(new_color) => {
|
Colored::ForegroundColor(new_color) => {
|
||||||
if new_color == Color::Reset {
|
if new_color == Color::Reset {
|
||||||
@ -125,40 +157,47 @@ impl fmt::Display for Colored {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::style::{Color, Colored};
|
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]
|
#[test]
|
||||||
fn test_format_fg_color() {
|
fn test_format_fg_color() {
|
||||||
let colored = Colored::ForegroundColor(Color::Red);
|
let colored = Colored::ForegroundColor(Color::Red);
|
||||||
assert_eq!(colored.to_string(), "38;5;9");
|
check_format_color(colored, "38;5;9");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_format_bg_color() {
|
fn test_format_bg_color() {
|
||||||
let colored = Colored::BackgroundColor(Color::Red);
|
let colored = Colored::BackgroundColor(Color::Red);
|
||||||
assert_eq!(colored.to_string(), "48;5;9");
|
check_format_color(colored, "48;5;9");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_format_reset_fg_color() {
|
fn test_format_reset_fg_color() {
|
||||||
let colored = Colored::ForegroundColor(Color::Reset);
|
let colored = Colored::ForegroundColor(Color::Reset);
|
||||||
assert_eq!(colored.to_string(), "39");
|
check_format_color(colored, "39");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_format_reset_bg_color() {
|
fn test_format_reset_bg_color() {
|
||||||
let colored = Colored::BackgroundColor(Color::Reset);
|
let colored = Colored::BackgroundColor(Color::Reset);
|
||||||
assert_eq!(colored.to_string(), "49");
|
check_format_color(colored, "49");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_format_fg_rgb_color() {
|
fn test_format_fg_rgb_color() {
|
||||||
let colored = Colored::BackgroundColor(Color::Rgb { r: 1, g: 2, b: 3 });
|
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]
|
#[test]
|
||||||
fn test_format_fg_ansi_color() {
|
fn test_format_fg_ansi_color() {
|
||||||
let colored = Colored::ForegroundColor(Color::AnsiValue(255));
|
let colored = Colored::ForegroundColor(Color::AnsiValue(255));
|
||||||
assert_eq!(colored.to_string(), "38;5;255");
|
check_format_color(colored, "38;5;255");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -267,4 +306,16 @@ mod tests {
|
|||||||
test("48;2;0;2;25;");
|
test("48;2;0;2;25;");
|
||||||
test("48;2;0;2;25;3");
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user