Skip to main content

callisto_cli/
tty.rs

1/// Returns `true` when stdin is connected to a terminal (i.e. the process is
2/// running interactively), `false` otherwise (e.g. stdin is a pipe or
3/// redirected file, which is the common case in CI environments).
4///
5/// This centralises the TTY check so that `add` and `init` both branch on the
6/// same predicate rather than each duplicating the `IsTerminal` import and
7/// call site. The function is a thin wrapper over
8/// [`std::io::IsTerminal::is_terminal`] and carries no additional state; it
9/// can be replaced with a test double by injecting a `bool` at the call site
10/// when unit testing the *callers*.
11///
12/// # Why a dedicated module instead of an inline call?
13///
14/// `std::io::IsTerminal` cannot be meaningfully unit-tested without spawning a
15/// real subprocess with a controlled stdin (the trait's return value is
16/// determined by the OS, not by Rust code). The integration-test coverage for
17/// the non-interactive path lives in
18/// `crates/callisto-cli/tests/cli_tests.rs` — specifically
19/// `test_add_non_interactive_via_pipe` — which pipes stdin and asserts that
20/// `callisto add` selects the non-interactive code path rather than trying to
21/// drive a TTY wizard.
22pub fn is_interactive() -> bool {
23    use std::io::IsTerminal as _;
24    std::io::stdin().is_terminal()
25}
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30
31    /// Verifies the function compiles and returns a `bool`. In a standard test
32    /// environment stdin is typically *not* a terminal (tests are invoked by
33    /// `cargo test`, which redirects stdin), so the expected value is `false`.
34    /// This test is deliberately lightweight: the real coverage is provided by
35    /// the binary-level integration test `test_add_non_interactive_via_pipe`.
36    #[test]
37    fn is_interactive_returns_bool_in_test_environment() {
38        // `cargo test` does not allocate a TTY for stdin, so this must be false.
39        let result = is_interactive();
40        assert!(
41            !result,
42            "is_interactive() should return false in a non-TTY test environment"
43        );
44    }
45}