#![cfg(feature = "colors")]
use nu_ansi_term::{Color, Style};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(docsrs, doc(cfg(feature = "colors")))]
pub enum ColorMode {
#[default]
Auto,
Always,
Never,
}
impl ColorMode {
pub(crate) fn resolve(self, is_terminal: bool, no_color_set: bool) -> bool {
match self {
Self::Always => true,
Self::Never => false,
Self::Auto => is_terminal && !no_color_set,
}
}
pub(crate) fn resolve_now(self, is_terminal: bool) -> bool {
self.resolve(is_terminal, std::env::var_os("NO_COLOR").is_some())
}
}
#[derive(Debug, Clone, Copy)]
#[cfg_attr(docsrs, doc(cfg(feature = "colors")))]
#[allow(missing_docs)] pub struct ColorTheme {
pub trace: Style,
pub debug: Style,
pub info: Style,
pub warn: Style,
pub error: Style,
pub span_name: Style,
pub field_name: Style,
pub field_value: Style,
pub target: Style,
pub thread_id: Style,
}
impl ColorTheme {
#[must_use]
pub fn monochrome() -> Self {
Self {
trace: Style::new(),
debug: Style::new(),
info: Style::new(),
warn: Style::new(),
error: Style::new(),
span_name: Style::new(),
field_name: Style::new(),
field_value: Style::new(),
target: Style::new(),
thread_id: Style::new(),
}
}
pub(crate) fn level_style(&self, level: tracing::Level) -> Style {
match level {
tracing::Level::TRACE => self.trace,
tracing::Level::DEBUG => self.debug,
tracing::Level::INFO => self.info,
tracing::Level::WARN => self.warn,
tracing::Level::ERROR => self.error,
}
}
}
impl Default for ColorTheme {
fn default() -> Self {
Self {
trace: Style::new().fg(Color::Magenta),
debug: Style::new().fg(Color::Blue),
info: Style::new().fg(Color::Green),
warn: Style::new().fg(Color::Yellow),
error: Style::new().fg(Color::Red),
span_name: Style::new(),
field_name: Style::new(),
field_value: Style::new(),
target: Style::new(),
thread_id: Style::new(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn auto_resolves_against_tty_and_no_color() {
assert!(ColorMode::Auto.resolve(true, false));
assert!(!ColorMode::Auto.resolve(true, true));
assert!(!ColorMode::Auto.resolve(false, false));
assert!(!ColorMode::Auto.resolve(false, true));
}
#[test]
fn always_overrides_tty_and_env() {
assert!(ColorMode::Always.resolve(false, true));
assert!(ColorMode::Always.resolve(true, true));
}
#[test]
fn never_overrides_tty_and_env() {
assert!(!ColorMode::Never.resolve(true, false));
}
#[test]
fn level_style_picks_correct_style() {
let theme = ColorTheme::default();
assert_eq!(theme.level_style(tracing::Level::INFO), theme.info);
assert_eq!(theme.level_style(tracing::Level::ERROR), theme.error);
}
#[test]
fn monochrome_has_empty_styles() {
let theme = ColorTheme::monochrome();
let plain = Style::new();
assert_eq!(theme.info, plain);
assert_eq!(theme.error, plain);
assert_eq!(theme.span_name, plain);
}
}