use std::env;
use std::io::IsTerminal;
#[must_use]
pub fn use_color_stdout() -> bool {
use_color(std::io::stdout().is_terminal())
}
#[must_use]
pub fn use_color_stderr() -> bool {
use_color(std::io::stderr().is_terminal())
}
fn use_color(is_tty: bool) -> bool {
use_color_with(
env::var_os("NO_COLOR").is_some(),
matches!(env::var("CLICOLOR_FORCE").ok().as_deref(), Some("1")),
is_tty,
)
}
fn use_color_with(no_color: bool, force: bool, is_tty: bool) -> bool {
if no_color {
return false;
}
if force {
return true;
}
is_tty
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColorChoice {
Always,
Auto,
Never,
}
impl ColorChoice {
#[must_use]
pub fn parse(s: Option<&str>) -> Option<Self> {
match s {
None | Some("" | "auto") => Some(Self::Auto),
Some("always") => Some(Self::Always),
Some("never") => Some(Self::Never),
Some(_) => None,
}
}
#[must_use]
pub fn resolve(self, is_tty: bool) -> bool {
match self {
Self::Always => true,
Self::Never => false,
Self::Auto => use_color(is_tty),
}
}
}
#[must_use]
pub fn getenv_nonempty(key: &str) -> Option<String> {
match env::var(key) {
Ok(v) if !v.is_empty() => Some(v),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn use_color_with_matrix_honours_precedence_and_tty() {
assert!(!use_color_with(true, true, true));
assert!(!use_color_with(true, true, false));
assert!(!use_color_with(true, false, true));
assert!(!use_color_with(true, false, false));
assert!(use_color_with(false, true, true));
assert!(use_color_with(false, true, false));
assert!(use_color_with(false, false, true));
assert!(!use_color_with(false, false, false));
}
}