anstyle_query/
lib.rs

1pub mod windows;
2
3/// Check [CLICOLOR] status
4///
5/// - When `true`, ANSI colors are supported and should be used when the program isn't piped,
6///   similar to [`term_supports_color`]
7/// - When `false`, don’t output ANSI color escape codes, similar to [`no_color`]
8///
9/// See also:
10/// - [terminfo](https://crates.io/crates/terminfo) or [term](https://crates.io/crates/term) for
11///   checking termcaps
12/// - [termbg](https://crates.io/crates/termbg) for detecting background color
13///
14/// [CLICOLOR]: https://bixense.com/clicolors/
15#[inline]
16pub fn clicolor() -> Option<bool> {
17    let value = std::env::var_os("CLICOLOR")?;
18    Some(value != "0")
19}
20
21/// Check [CLICOLOR_FORCE] status
22///
23/// ANSI colors should be enabled no matter what.
24///
25/// [CLICOLOR_FORCE]: https://bixense.com/clicolors/
26#[inline]
27pub fn clicolor_force() -> bool {
28    let value = std::env::var_os("CLICOLOR_FORCE");
29    value
30        .as_deref()
31        .unwrap_or_else(|| std::ffi::OsStr::new("0"))
32        != "0"
33}
34
35/// Check [NO_COLOR] status
36///
37/// When `true`, should prevent the addition of ANSI color.
38///
39/// User-level configuration files and per-instance command-line arguments should override
40/// [NO_COLOR]. A user should be able to export `$NO_COLOR` in their shell configuration file as a
41/// default, but configure a specific program in its configuration file to specifically enable
42/// color.
43///
44/// [NO_COLOR]: https://no-color.org/
45#[inline]
46pub fn no_color() -> bool {
47    let value = std::env::var_os("NO_COLOR");
48    value.as_deref().unwrap_or_else(|| std::ffi::OsStr::new("")) != ""
49}
50
51/// Check `TERM` for color support
52#[inline]
53#[cfg(not(windows))]
54pub fn term_supports_color() -> bool {
55    match std::env::var_os("TERM") {
56        // If TERM isn't set, then we are in a weird environment that
57        // probably doesn't support colors.
58        None => return false,
59        Some(k) => {
60            if k == "dumb" {
61                return false;
62            }
63        }
64    }
65    true
66}
67
68/// Check `TERM` for color support
69#[inline]
70#[cfg(windows)]
71pub fn term_supports_color() -> bool {
72    // On Windows, if TERM isn't set, then we shouldn't automatically
73    // assume that colors aren't allowed. This is unlike Unix environments
74    // where TERM is more rigorously set.
75    if let Some(k) = std::env::var_os("TERM") {
76        if k == "dumb" {
77            return false;
78        }
79    }
80    true
81}
82
83/// Check `TERM` for ANSI color support
84#[inline]
85#[cfg(not(windows))]
86pub fn term_supports_ansi_color() -> bool {
87    term_supports_color()
88}
89
90/// Check `TERM` for ANSI color support
91#[inline]
92#[cfg(windows)]
93pub fn term_supports_ansi_color() -> bool {
94    match std::env::var_os("TERM") {
95        // If TERM isn't set, then we are in a weird environment that
96        // probably doesn't support ansi.
97        None => return false,
98        Some(k) => {
99            // cygwin doesn't seem to support ANSI escape sequences
100            // and instead has its own variety. However, the Windows
101            // console API may be available.
102            if k == "dumb" || k == "cygwin" {
103                return false;
104            }
105        }
106    }
107    true
108}
109
110/// Check [COLORTERM] for truecolor support
111///
112/// [COLORTERM]: https://github.com/termstandard/colors
113#[inline]
114pub fn truecolor() -> bool {
115    let value = std::env::var_os("COLORTERM");
116    let value = value.as_deref().unwrap_or_default();
117    value == "truecolor" || value == "24bit"
118}
119
120/// Report whether this is running in CI
121///
122/// CI is a common environment where, despite being piped, ansi color codes are supported
123///
124/// This is not as exhaustive as you'd find in a crate like `is_ci` but it should work in enough
125/// cases.
126#[inline]
127pub fn is_ci() -> bool {
128    // Assuming its CI based on presence because who would be setting `CI=false`?
129    //
130    // This makes it easier to all of the potential values when considering our known values:
131    // - Gitlab and Github set it to `true`
132    // - Woodpecker sets it to `woodpecker`
133    std::env::var_os("CI").is_some()
134}