sdml_errors/diagnostics/
color.rs

1/*!
2A common helper type to determine color output.
3 */
4
5use codespan_reporting::term::termcolor::ColorChoice;
6
7// ------------------------------------------------------------------------------------------------
8// Public Types
9// ------------------------------------------------------------------------------------------------
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
12pub enum UseColor {
13    Always,
14    Auto,
15    Never,
16}
17
18///
19/// A common environment variable for command-line tools, if set to any value color should not
20/// be used.
21///
22pub const COLOR_NO_COLOR_ENV: &str = "NO_COLOR";
23
24///
25/// A Rusty environment variable for command-line tools, if set to `0` color
26/// should not be used, if set to `1` color should be used, otherwise it's up to
27/// the tool to decide.
28///
29/// Note that the variable `NO_COLOR` overrides `CLI_COLOR`.
30///
31pub const COLOR_CLI_COLOR_ENV: &str = "CLI_COLOR";
32
33// ------------------------------------------------------------------------------------------------
34// Private Types
35// ------------------------------------------------------------------------------------------------
36
37const COLOR_CLI_COLOR_ON: &str = "1";
38
39const COLOR_CLI_COLOR_OFF: &str = "0";
40
41// ------------------------------------------------------------------------------------------------
42// Implementations
43// ------------------------------------------------------------------------------------------------
44
45impl Default for UseColor {
46    fn default() -> Self {
47        Self::Auto
48    }
49}
50
51impl From<UseColor> for ColorChoice {
52    fn from(value: UseColor) -> Self {
53        match value {
54            UseColor::Always => Self::Always,
55            UseColor::Auto => Self::Auto,
56            UseColor::Never => Self::Never,
57        }
58    }
59}
60
61impl UseColor {
62    pub fn from_env() -> Self {
63        match (Self::from_no_color_env(), Self::from_cli_color_env()) {
64            (Some(no_color), _) => no_color,
65            (None, Some(cli_color)) => cli_color,
66            (None, None) => Self::default(),
67        }
68    }
69
70    #[inline(always)]
71    pub fn use_color(&self) -> bool {
72        matches!(self, Self::Always | Self::Auto)
73    }
74
75    #[inline(always)]
76    pub fn from_no_color_env() -> Option<Self> {
77        std::env::var(COLOR_NO_COLOR_ENV).map(|_| Self::Never).ok()
78    }
79
80    #[inline(always)]
81    pub fn from_cli_color_env() -> Option<Self> {
82        std::env::var(COLOR_NO_COLOR_ENV)
83            .map(|v| {
84                if v == COLOR_CLI_COLOR_OFF {
85                    Self::Never
86                } else if v == COLOR_CLI_COLOR_ON {
87                    Self::Always
88                } else {
89                    Self::Auto
90                }
91            })
92            .ok()
93    }
94}