-
Notifications
You must be signed in to change notification settings - Fork 761
/
Copy pathonKeyPress.ts
42 lines (36 loc) · 1.16 KB
/
onKeyPress.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import readline from "readline";
import { PassThrough } from "stream";
import isInteractive from "../is-interactive";
export type KeypressEvent = {
name: string;
sequence: string;
ctrl: boolean;
meta: boolean;
shift: boolean;
};
export function onKeyPress(callback: (key: KeypressEvent) => void) {
// Listening for events on process.stdin (eg .on('keypress')) causes it to go into 'old mode'
// which keeps this nodejs process alive even after calling .off('keypress')
// WORKAROUND: piping stdin via a transform stream allows us to call stream.destroy()
// which then allows this nodejs process to close cleanly
// https://nodejs.org/api/process.html#signal-events:~:text=be%20used%20in-,%22old%22%20mode,-that%20is%20compatible
const stream = new PassThrough();
process.stdin.pipe(stream);
if (isInteractive()) {
readline.emitKeypressEvents(stream);
process.stdin.setRawMode(true);
}
const handler = async (_char: string, key: KeypressEvent) => {
if (key) {
callback(key);
}
};
stream.on("keypress", handler);
return () => {
if (isInteractive()) {
process.stdin.setRawMode(false);
}
stream.off("keypress", handler);
stream.destroy();
};
}