diff --git a/cspell.config.yaml b/cspell.config.yaml index 01eb5c3b..4554be33 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -57,6 +57,7 @@ words: - ints - iokit - iphoneos + - isatty - keyalg # From .github/workflows/e2e.yaml - keypass # From .github/workflows/e2e.yaml - keysize # From .github/workflows/e2e.yaml @@ -154,6 +155,7 @@ words: - VCRUNTIME - Verdana - vmcode + - winsize - worktrees - writeln - WRONGPASS diff --git a/packages/shorebird_cli/lib/src/interactive_mode.dart b/packages/shorebird_cli/lib/src/interactive_mode.dart index c6787328..4742819d 100644 --- a/packages/shorebird_cli/lib/src/interactive_mode.dart +++ b/packages/shorebird_cli/lib/src/interactive_mode.dart @@ -9,9 +9,17 @@ import 'package:shorebird_cli/src/json_output.dart'; /// (`chooseOne`/`confirm`/`prompt`). /// /// Returns `false` when any of the following is true: -/// * stdout is not connected to a terminal (`!stdout.hasTerminal`). +/// * stdout is not connected to a terminal. /// * `--json` was passed (machine-readable output expected). -bool get isInteractive => io.stdout.hasTerminal && !isJsonMode; +/// +/// `Stdout.hasTerminal` is winsize-based, not isatty-based, so PTYs with +/// default 0x0 winsize fail it. `stdioType(stdout) == StdioType.terminal` +/// uses isatty semantics and catches them. +bool get isInteractive { + if (isJsonMode) return false; + if (io.stdout.hasTerminal) return true; + return io.stdioType(io.stdout) == io.StdioType.terminal; +} /// The default hint emitted when an interactive prompt is reached in a /// non-interactive context and no per-site hint was provided.