use lazy_static::lazy_static;
use supports_color::Stream;
lazy_static! {
pub static ref COLOR_PALETTE: ColorPalette = {
CliColorConfig::get_supported_color_palette(Stream::Stdout)
};
pub static ref ENABLE_COLOR: bool = {
let conf = CliColorConfig::default();
conf.should_enable_color()
};
}
#[derive(PartialEq, Debug)]
pub enum ColorPalette {
None,
Palette16,
Palette256,
Truecolor,
}
#[derive(Debug, PartialEq)]
enum ColorOption {
Always,
Auto,
Never,
}
struct CliColorConfig {
color_option: ColorOption,
color_palette: ColorPalette,
}
impl Default for CliColorConfig {
fn default() -> Self {
let args: Vec<String> = std::env::args().collect();
let color_option = CliColorConfig::parse_arguments(&args);
let color_palette = CliColorConfig::get_supported_color_palette(Stream::Stdout);
CliColorConfig::new(color_option, color_palette)
}
}
impl CliColorConfig {
fn new(color_option: ColorOption, color_palette: ColorPalette) -> Self {
Self {
color_option,
color_palette,
}
}
pub fn should_enable_color(&self) -> bool {
match self.color_option {
ColorOption::Never => false,
ColorOption::Always => true,
ColorOption::Auto => self.color_palette != ColorPalette::None,
}
}
fn parse_arguments(args: &[String]) -> ColorOption {
for arg in args.iter() {
if arg.starts_with("--color=") {
return match arg.split('=').nth(1) {
Some("always") => ColorOption::Always,
Some("auto") => ColorOption::Auto,
Some("never") => ColorOption::Never,
_ => {
ColorOption::Auto }
};
}
}
ColorOption::Auto
}
fn get_supported_color_palette(stream: Stream) -> ColorPalette {
match supports_color::on(stream) {
Some(support) => {
if support.has_16m {
ColorPalette::Truecolor
} else if support.has_256 {
ColorPalette::Palette256
} else {
ColorPalette::Palette16
}
}
None => {
ColorPalette::None }
}
}
}
#[cfg(test)]
mod tests {
use crate::style::*;
use super::*;
#[derive(Debug, PartialEq)]
enum MockStream {
Supports16m,
Supports256,
Supports16,
Unknown,
}
#[test]
fn test_new() {
let config = CliColorConfig::new(ColorOption::Always, ColorPalette::Palette256);
assert_eq!(config.color_option, ColorOption::Always);
assert_eq!(config.color_palette, ColorPalette::Palette256);
}
#[test]
fn test_should_enable_color_never() {
let settings = CliColorConfig::new(ColorOption::Never, ColorPalette::Palette256);
assert!(!settings.should_enable_color());
}
#[test]
fn test_should_enable_color_always() {
let settings = CliColorConfig::new(ColorOption::Always, ColorPalette::None);
assert!(settings.should_enable_color());
}
#[test]
fn test_should_enable_color_auto_with_palette() {
let settings = CliColorConfig {
color_option: ColorOption::Auto,
color_palette: ColorPalette::Palette16,
};
assert!(settings.should_enable_color());
}
#[test]
fn test_should_enable_color_auto_without_palette() {
let settings = CliColorConfig {
color_option: ColorOption::Auto,
color_palette: ColorPalette::None,
};
assert!(!settings.should_enable_color());
}
fn get_supported_color_palette_mock(stream: MockStream) -> ColorPalette {
match stream {
MockStream::Supports16m => ColorPalette::Truecolor,
MockStream::Supports256 => ColorPalette::Palette256,
MockStream::Supports16 => ColorPalette::Palette16,
MockStream::Unknown => ColorPalette::None,
}
}
#[test]
fn test_get_supported_color_palette_truecolor() {
let result = get_supported_color_palette_mock(MockStream::Supports16m);
assert_eq!(result, ColorPalette::Truecolor);
}
#[test]
fn test_get_supported_color_palette_palette256() {
let result = get_supported_color_palette_mock(MockStream::Supports256);
assert_eq!(result, ColorPalette::Palette256);
}
#[test]
fn test_get_supported_color_palette_palette16() {
let result = get_supported_color_palette_mock(MockStream::Supports16);
assert_eq!(result, ColorPalette::Palette16);
}
#[test]
fn test_get_supported_color_palette_none() {
let result = get_supported_color_palette_mock(MockStream::Unknown);
assert_eq!(result, ColorPalette::None);
}
#[test]
fn test_valid_arguments() {
let args = vec!["my_program".to_string(), "--color=always".to_string()];
let config = CliColorConfig::parse_arguments(&args);
assert_eq!(config, ColorOption::Always);
}
#[test]
fn test_invalid_arguments() {
let args = vec!["my_program".to_string(), "--invalid-option".to_string()];
let result = CliColorConfig::parse_arguments(&args);
assert_eq!(result, ColorOption::Auto);
}
#[test]
fn test_combine_attributes() {
let attributes =
combine_attributes(&[&Attribute::Bold, &Attribute::Underlined, &Attribute::Italic]);
assert_eq!(
attributes,
Attributes::default() | Attribute::Bold | Attribute::Underlined | Attribute::Italic
);
}
}