Skip to content

Commit ae6496f

Browse files
committed
fix(git_chain): restore terminal modes before settling input
1 parent d8beebf commit ae6496f

1 file changed

Lines changed: 19 additions & 2 deletions

File tree

git_chain/lib/src/util/terminal_input.dart

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,28 @@ void drainTerminalInput() {
4242
}
4343
}
4444

45+
/// Restores sane terminal modes (echo, canonical input, and crucially output
46+
/// post-processing / `ONLCR`).
47+
///
48+
/// nocterm and `git mergetool` can leave the terminal with output processing
49+
/// disabled, which makes subsequent shell output "stairstep" (line feeds with
50+
/// no carriage return). Dart's stdin API only restores input flags, so we shell
51+
/// out to `stty sane` against the controlling terminal.
52+
Future<void> restoreTerminalModes() async {
53+
if (!(Platform.isMacOS || Platform.isLinux)) return;
54+
try {
55+
await Process.run('sh', ['-c', 'stty sane < /dev/tty']);
56+
} catch (_) {
57+
// Best-effort.
58+
}
59+
}
60+
4561
/// Flushes stdout (so any queued terminal query is actually sent), waits for the
46-
/// reply to travel back, then drains the controlling terminal's input so the
47-
/// reply can't leak into the shell as stray characters.
62+
/// reply to travel back, drains the controlling terminal's input so the reply
63+
/// can't leak into the shell, and restores sane terminal modes.
4864
Future<void> settleTerminalInput() async {
4965
if (!(Platform.isMacOS || Platform.isLinux)) return;
66+
await restoreTerminalModes();
5067
try {
5168
await stdout.flush();
5269
} catch (_) {}

0 commit comments

Comments
 (0)