1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use crate::condition::{AtomicCondition, Condition};

static ENABLED: AtomicCondition = AtomicCondition::DEFAULT;

/// Unconditionally disables styling globally.
///
/// # Example
///
/// ```rust
/// use yansi::Paint;
///
/// // With styling enabled, ANSI color codes are emitted, thus `ne`.
/// assert_ne!("go".green().to_string(), "go".to_string());
///
/// // With styling disabled, ANSI color codes are _not_ emitted.
/// yansi::disable();
/// assert_eq!("go".green().to_string(), "go".to_string());
/// ```
pub fn disable() {
    ENABLED.store(Condition::NEVER);
}

/// Unconditionally enables styling globally.
///
/// By default, styling is enabled based on [`Condition::DEFAULT`], which checks
/// for operating system support.
///
/// # Example
///
/// ```rust
/// use yansi::Paint;
///
/// // With styling disabled, ANSI color codes are _not_ emitted.
/// yansi::disable();
/// assert_eq!("go".green().to_string(), "go".to_string());
///
/// // Reenabling causes color code to be emitted.
/// yansi::enable();
/// assert_ne!("go".green().to_string(), "go".to_string());
/// ```
pub fn enable() {
    ENABLED.store(Condition::ALWAYS);
}

/// Dynamically enables and disables styling globally based on `condition`.
///
/// `condition` is expected to be fast: it is checked dynamically, each time a
/// [`Painted`](crate::Painted) value is displayed.
///
/// # Example
///
/// ```rust
/// # #[cfg(all(feature = "detect-tty", feature = "detect-env"))] {
/// use yansi::Condition;
///
/// yansi::whenever(Condition::STDOUT_IS_TTY);
///
/// // On each styling, check if we have TTYs.
/// yansi::whenever(Condition::STDOUTERR_ARE_TTY_LIVE);
///
/// // Check `NO_COLOR`, `CLICOLOR`, and if we have TTYs.
/// const HAVE_COLOR: Condition = Condition(|| {
///     std::env::var_os("NO_COLOR").is_none()
///         && (Condition::CLICOLOR_LIVE)()
///         && Condition::stdouterr_are_tty_live()
/// });
///
/// // This will call `HAVE_COLOR` every time styling is needed. In this
/// // example, this means that env vars will be checked on each styling.
/// yansi::whenever(HAVE_COLOR);
///
/// // This instead caches the value (checking `env()` exactly once, now).
/// yansi::whenever(Condition::cached((HAVE_COLOR)()));
///
/// // Is identical to this:
/// match (HAVE_COLOR)() {
///     true => yansi::enable(),
///     false => yansi::disable(),
/// }
/// # }
/// ```
pub fn whenever(condition: Condition) {
    ENABLED.store(condition);
}

/// Returns `true` if styling is globally enabled and `false` otherwise.
///
/// By default, styling is enabled based on [`Condition::DEFAULT`], which checks
/// for operating system support. It can be enabled and disabled on-the-fly with
/// [`enable()`] and [`disable()`] and via a dynamic condition with
/// [`whenever()`].
///
/// # Example
///
/// ```rust
/// // Styling is enabled by default.
/// # yansi::enable();
/// assert!(yansi::is_enabled());
///
/// // Disable it with `Painted::disable()`.
/// yansi::disable();
/// assert!(!yansi::is_enabled());
///
/// // Reenable with `Painted::enable()`.
/// yansi::enable();
/// assert!(yansi::is_enabled());
/// ```
pub fn is_enabled() -> bool {
    ENABLED.read()
}