Node's built-in readline
module is great for handling user input if you need something simple. But when using createInterface
, there are a number of built-in behaviors that are difficult or impossible to override when you need more control over the input stream.
Other keypress modules I found either did too much, or didn't allow for enough customization. This module is designed to be simple, flexible, easy to use, and easy to customize.
Create your own CLI interface
It's lightweight, no dependencies, easy to use, and easy to customize. It's designed to be used in a wide range of use-cases, from simple command-line utilities to complex terminal applications.
Powerful CLI applications can be built with this module.
import { emitKeypress } from '{%= name %}';
emitKeypress({ input: process.stdin });
process.stdin.on('keypress', (input, key) => {
console.log({ input, key });
if (input === '\x03' || input === '\r') {
process.stdin.pause();
}
});
Pass an onKeypress
function to emitKeypress
to handle keypress events.
// The "close" function is passed as the third argument
const onKeypress = async (input, key, close) => {
// do stuff with keypress events
console.log({ input, key });
// Close the stream if the user presses `Ctrl+C` or `Enter`
if (input === '\x03' || input === '\r') {
close();
}
};
emitKeypress({ onKeypress });
A close
function is also returned from emitKeypress
that can be called to close the stream.
const { close } = emitKeypress({ onKeypress });
// close the stream
setTimeout(() => {
close();
}, 10_000);
Pass a keymap
array to map keypress events to specific shortcuts.
emitKeypress({
keymap: [
{ sequence: '\x03', shortcut: 'ctrl+c' },
{ sequence: '\r', shortcut: 'return' }
],
onKeypress: async (input, key, close) => {
// do stuff with keypress events
console.log({ input, key });
if (key.shortcut === 'return' || key.shortcut === 'ctrl+c') {
close();
}
}
});
Note that you can add arbitrary properties the keymap objects. This is useful for mapping shortcuts to commands.
Example
emitKeypress({
keymap: [
{ sequence: '\x1B', shortcut: 'escape', command: 'cancel' },
{ sequence: '\x03', shortcut: 'ctrl+c', command: 'cancel' },
{ sequence: '\r', shortcut: 'return', command: 'submit' }
],
onKeypress: async (input, key, close) => {
// do stuff with keypress events
switch (key.command) {
case 'cancel':
console.log('canceled');
close();
break;
case 'submit':
console.log('submitted');
break;
}
}
});
Pass a ReadableStream
to input
to listen for keypress events on the stream.
emitKeypress({
input: process.stdin,
onKeypress: async (input, key, close) => {
// do stuff with keypress events
console.log({ input, key });
if (key.shortcut === 'return' || key.shortcut === 'ctrl+c') {
close();
}
}
});