I did not see an encompassing answer yet. In particular, the answers using process.stdin.destroy()
preclude the functions being called twice if you need multiple key presses. The ones that do not call process.stdin.off(...)
keep processing key presses. The ones that do not call process.stdin.pause()
keep the process alive even after the program completes.
I believe the following function is pretty thorough. Called without parameters, it displays a "Press any key to continue..."
message and waits for the user to press any key. The message
parameter overrides the default message. The keys
parameter allows you to listen for particular keys, and the message will repeat if other keys are pressed. The accepted key pressed is not case-sensitive unless the keys
parameter is mixed-case.
The return value is a Promise
with the key the user pressed (case adjusted for non-case-sensitive keys
). The promise is rejected if they press CTRL-c
.
function keyPress(message, keys) {
const _message = message || "Press any key to continue...";
const _keys = keys || "";
return new Promise(function (resolve, reject) {
const caseSensitive = _keys.toLowerCase() !== _keys && _keys.toUpperCase() !== _keys;
process.stdout.write(_message);
function keyListener(buffer) {
let key = buffer.toString();
if (key.charCodeAt(0) === 3) {
process.stdin.setRawMode(false);
process.stdin.off('data', keyListener);
process.stdin.pause();
// process.exit(0); // Exit process if you prefer.
reject(key.charCodeAt(0));
}
const index = caseSensitive ? _keys.indexOf(key) : _keys.toLowerCase().indexOf(key.toLowerCase());
if (_keys && index < 0) {
process.stdout.write(key);
process.stdout.write("\n");
process.stdout.write(_message);
return;
}
process.stdin.setRawMode(false);
process.stdin.off('data', keyListener);
process.stdin.pause();
if (index >= 0) {
key = _keys.charAt(index);
process.stdout.write(key);
}
process.stdout.write("\n");
resolve(key);
}
process.stdin.resume();
process.stdin.setRawMode(true);
process.stdin.on('data', keyListener);
});
}
Example 1: Shows Press any key to continue...
message, waits for any key press.
await keyPress();
Example 2: Shows Process data? (Y|N):
message, waiting for the user to press y
, n
, Y
, or N
. Repeats the message if other key is pressed. answer
will be either 'y'
or 'n'
, regardless of case pressed.
const answer = await keyPress("Process data? (Y|N): ", "yn");