common/
color.rs

1use termcolor::{Color, ColorChoice, ColorSpec};
2
3pub const COLOR_CHOICES: &[&str] = &[AUTO, ALWAYS, ANSI, NEVER];
4
5const AUTO: &str = "auto";
6const ALWAYS: &str = "always";
7const ANSI: &str = "ansi";
8const NEVER: &str = "never";
9
10pub fn parse_color(string: &str) -> Result<ColorChoice, &'static str> {
11    match string {
12        AUTO => Ok(ColorChoice::Auto),
13        ALWAYS => Ok(ColorChoice::Always),
14        ANSI => Ok(ColorChoice::AlwaysAnsi),
15        NEVER => Ok(ColorChoice::Never),
16        _ => Err("invalid value"),
17    }
18}
19
20pub fn choose_color(color: Option<ColorChoice>) -> ColorChoice {
21    match color {
22        Some(ColorChoice::Auto) | None => detect_color(),
23        Some(other) => other,
24    }
25}
26
27fn detect_color() -> ColorChoice {
28    if atty::is(atty::Stream::Stdout) {
29        ColorChoice::Auto
30    } else {
31        ColorChoice::Never
32    }
33}
34
35pub fn spec_color(color: Color) -> ColorSpec {
36    let mut spec = ColorSpec::new();
37    spec.set_fg(Some(color));
38    spec
39}
40
41pub fn spec_bold_color(color: Color) -> ColorSpec {
42    let mut spec = spec_color(color);
43    spec.set_bold(true);
44    spec
45}
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50    use test_case::test_case;
51
52    #[test_case("",     Err("invalid value")        ; "empty")]
53    #[test_case("x",    Err("invalid value")        ; "invalid")]
54    #[test_case(ALWAYS, Ok(ColorChoice::Always)     ; "always")]
55    #[test_case(ANSI,   Ok(ColorChoice::AlwaysAnsi) ; "ansi")]
56    #[test_case(AUTO,   Ok(ColorChoice::Auto)       ; "auto")]
57    #[test_case(NEVER,  Ok(ColorChoice::Never)      ; "never")]
58    fn parse_color(input: &str, result: Result<ColorChoice, &'static str>) {
59        assert_eq!(super::parse_color(input), result);
60    }
61
62    #[test_case(None,                          detect_color()          ; "none")]
63    #[test_case(Some(ColorChoice::Auto),       detect_color()          ; "auto")]
64    #[test_case(Some(ColorChoice::Always),     ColorChoice::Always     ; "always")]
65    #[test_case(Some(ColorChoice::AlwaysAnsi), ColorChoice::AlwaysAnsi ; "ansi")]
66    #[test_case(Some(ColorChoice::Never),      ColorChoice::Never      ; "never")]
67    fn choose_color(value: Option<ColorChoice>, result: ColorChoice) {
68        assert_eq!(super::choose_color(value), result)
69    }
70
71    #[test]
72    fn spec_color() {
73        assert_eq!(
74            &super::spec_color(Color::Red),
75            ColorSpec::new().set_fg(Some(Color::Red))
76        );
77    }
78
79    #[test]
80    fn spec_bold_color() {
81        assert_eq!(
82            &super::spec_bold_color(Color::Red),
83            ColorSpec::new().set_fg(Some(Color::Red)).set_bold(true)
84        );
85    }
86}