mi6_cli/display/
terminal.rs

1//! Terminal utilities for width detection and color support.
2
3use std::io::{IsTerminal, stdout};
4use std::process::Command;
5
6/// Default terminal width if detection fails.
7pub const DEFAULT_TERMINAL_WIDTH: usize = 120;
8
9/// Get terminal width using stty, falling back to default.
10pub fn get_terminal_width() -> usize {
11    Command::new("stty")
12        .args(["size"])
13        .stdin(std::process::Stdio::inherit())
14        .output()
15        .ok()
16        .and_then(|output| {
17            let stdout = String::from_utf8_lossy(&output.stdout);
18            // stty size returns "rows cols"
19            stdout.split_whitespace().nth(1)?.parse().ok()
20        })
21        .unwrap_or(DEFAULT_TERMINAL_WIDTH)
22}
23
24/// Check if we should use colors.
25///
26/// Returns true if:
27/// - stdout is a terminal, AND
28/// - the `NO_COLOR` environment variable is not set
29///
30/// Respects the [NO_COLOR spec](https://no-color.org/).
31pub fn use_colors() -> bool {
32    stdout().is_terminal() && std::env::var_os("NO_COLOR").is_none()
33}
34
35/// Check if we should use colors for stderr output.
36///
37/// Returns true if:
38/// - stderr is a terminal, AND
39/// - the `NO_COLOR` environment variable is not set
40pub fn use_colors_stderr() -> bool {
41    std::io::stderr().is_terminal() && std::env::var_os("NO_COLOR").is_none()
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn test_get_terminal_width_returns_positive() {
50        let width = get_terminal_width();
51        assert!(width > 0);
52    }
53}