use ratatui::style::Color;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColorMode {
TrueColor,
Palette256,
Ansi16,
Monochrome,
}
#[derive(Debug, Clone, Copy)]
pub struct Capabilities {
pub color: ColorMode,
}
impl Capabilities {
pub fn accent(self) -> Color {
match self.color {
ColorMode::TrueColor => Color::Rgb(0xfb, 0x73, 0x85),
ColorMode::Palette256 => Color::Indexed(204),
ColorMode::Ansi16 => Color::LightMagenta,
ColorMode::Monochrome => Color::Reset,
}
}
pub fn muted(self) -> Color {
match self.color {
ColorMode::TrueColor => Color::Rgb(0x88, 0x88, 0x88),
ColorMode::Palette256 => Color::Indexed(244),
ColorMode::Ansi16 => Color::DarkGray,
ColorMode::Monochrome => Color::Reset,
}
}
}
pub fn detect_capabilities() -> Capabilities {
Capabilities {
color: detect_color_from_env(|k| std::env::var(k).ok()),
}
}
fn detect_color_from_env<F: Fn(&str) -> Option<String>>(get: F) -> ColorMode {
if get("NO_COLOR").is_some() {
return ColorMode::Monochrome;
}
let term = get("TERM").unwrap_or_default();
if term == "dumb" || term.is_empty() {
return ColorMode::Monochrome;
}
if let Some(ct) = get("COLORTERM") {
let lower = ct.to_ascii_lowercase();
if lower == "truecolor" || lower == "24bit" {
return ColorMode::TrueColor;
}
}
if term.contains("256color") {
return ColorMode::Palette256;
}
ColorMode::Ansi16
}
#[cfg(test)]
mod tests {
use super::*;
fn env<'a>(pairs: &'a [(&'a str, &'a str)]) -> impl Fn(&str) -> Option<String> + 'a {
move |k| {
pairs
.iter()
.find(|(name, _)| *name == k)
.map(|(_, v)| (*v).to_string())
}
}
#[test]
fn no_color_wins_over_everything() {
let mode = detect_color_from_env(env(&[
("NO_COLOR", "1"),
("COLORTERM", "truecolor"),
("TERM", "xterm-256color"),
]));
assert_eq!(mode, ColorMode::Monochrome);
}
#[test]
fn dumb_term_is_monochrome() {
assert_eq!(
detect_color_from_env(env(&[("TERM", "dumb")])),
ColorMode::Monochrome
);
}
#[test]
fn truecolor_when_colorterm_set() {
assert_eq!(
detect_color_from_env(env(&[
("COLORTERM", "truecolor"),
("TERM", "xterm-256color"),
])),
ColorMode::TrueColor
);
}
#[test]
fn palette256_when_term_says_so() {
assert_eq!(
detect_color_from_env(env(&[("TERM", "screen-256color")])),
ColorMode::Palette256
);
}
#[test]
fn ansi16_for_plain_term() {
assert_eq!(
detect_color_from_env(env(&[("TERM", "xterm")])),
ColorMode::Ansi16
);
}
#[test]
fn empty_term_is_monochrome() {
assert_eq!(detect_color_from_env(env(&[])), ColorMode::Monochrome);
}
}