Skip to content

Commit b200c61

Browse files
committed
Tenative fix for #16
A theory from claude is that since we were fire-and-forget-ing `main`, the node process can die before flushing the full contents to stdout, leaving `less` in a different mode because of control characters. I'm not completely convinced because I/O should keep the process alive, but maybe there's still a race condition possible and this change seems harmless.
1 parent 715c33f commit b200c61

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

src/index.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ async function main() {
1919
terminalSize().columns
2020
);
2121
await transformContentsStreaming(context, process.stdin, process.stdout);
22+
23+
// Ensure stdout is fully flushed before exiting
24+
// This is critical when piping to `less` - if we exit before stdout is drained,
25+
// less may not receive all data or may receive it in a broken state
26+
if (process.stdout.writableNeedDrain) {
27+
await new Promise<void>((resolve) => {
28+
process.stdout.once('drain', resolve);
29+
});
30+
}
2231
}
2332

24-
main();
33+
main().catch((err) => {
34+
// Don't print errors if stdout pipe was closed (EPIPE)
35+
// This happens when less quits before we finish processing
36+
if (err.code !== 'EPIPE') {
37+
console.error(err);
38+
process.exit(1);
39+
}
40+
});

src/transformContentsStreaming.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ export function transformContentsStreaming(
3030
case 'EPIPE':
3131
// This can happen if the process exits while we are still
3232
// processing the input and writing to stdout.
33-
break;
33+
resolve();
34+
return;
3435
default:
3536
reject(err);
3637
return;

0 commit comments

Comments
 (0)