ito_config/output/
mod.rs

1//! UI-related option resolution.
2//!
3//! These helpers translate CLI flags + environment variables into a single
4//! `UiOptions` struct used by higher-level crates.
5
6use std::io::IsTerminal;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9/// UI behavior flags.
10pub struct UiOptions {
11    /// Disable ANSI color output.
12    pub no_color: bool,
13    /// Whether interactive prompts are allowed.
14    pub interactive: bool,
15}
16
17/// Return `true` if stdout is a TTY.
18pub fn stdout_is_tty() -> bool {
19    std::io::stdout().is_terminal()
20}
21
22/// Resolve UI options from CLI flags and environment variables.
23pub fn resolve_ui_options(
24    cli_no_color: bool,
25    no_color_env: Option<&str>,
26    cli_no_interactive: bool,
27    ito_interactive_env: Option<&str>,
28) -> UiOptions {
29    resolve_ui_options_with_tty(
30        cli_no_color,
31        no_color_env,
32        cli_no_interactive,
33        ito_interactive_env,
34        stdout_is_tty(),
35    )
36}
37
38/// Resolve UI options, allowing tests to inject TTY detection.
39pub fn resolve_ui_options_with_tty(
40    cli_no_color: bool,
41    no_color_env: Option<&str>,
42    cli_no_interactive: bool,
43    ito_interactive_env: Option<&str>,
44    stdout_is_tty: bool,
45) -> UiOptions {
46    let interactive = resolve_interactive(cli_no_interactive, ito_interactive_env, stdout_is_tty);
47    UiOptions {
48        no_color: cli_no_color || no_color_env_set(no_color_env),
49        interactive,
50    }
51}
52
53/// Interpret the `NO_COLOR` env var value.
54pub fn no_color_env_set(value: Option<&str>) -> bool {
55    match value {
56        Some("1") => true,
57        Some("true") => true,
58        Some(_) => false,
59        None => false,
60    }
61}
62
63/// Resolve whether prompts should run interactively.
64pub fn resolve_interactive(
65    cli_no_interactive: bool,
66    env: Option<&str>,
67    stdout_is_tty: bool,
68) -> bool {
69    if cli_no_interactive {
70        return false;
71    }
72
73    match env {
74        Some("1") => true,
75        Some("0") => false,
76        Some(_) => true,
77        None => stdout_is_tty,
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn no_color_env_set_matches_ts_values() {
87        assert!(!no_color_env_set(None));
88        assert!(!no_color_env_set(Some("0")));
89        assert!(no_color_env_set(Some("1")));
90        assert!(no_color_env_set(Some("true")));
91        assert!(!no_color_env_set(Some("TRUE")));
92    }
93
94    #[test]
95    fn resolve_interactive_respects_cli_and_env() {
96        assert!(resolve_interactive(false, None, true));
97        assert!(!resolve_interactive(false, None, false));
98        assert!(resolve_interactive(false, Some("1"), false));
99        assert!(!resolve_interactive(false, Some("0"), true));
100        assert!(!resolve_interactive(true, None, true));
101        assert!(!resolve_interactive(true, Some("1"), true));
102    }
103
104    #[test]
105    fn resolve_ui_options_combines_sources() {
106        assert_eq!(
107            resolve_ui_options_with_tty(false, None, false, None, false),
108            UiOptions {
109                no_color: false,
110                interactive: false
111            }
112        );
113        assert_eq!(
114            resolve_ui_options_with_tty(true, None, false, None, true),
115            UiOptions {
116                no_color: true,
117                interactive: true
118            }
119        );
120        assert_eq!(
121            resolve_ui_options_with_tty(false, Some("1"), false, Some("0"), true),
122            UiOptions {
123                no_color: true,
124                interactive: false
125            }
126        );
127    }
128}