Skip to content

Latest commit

 

History

History
129 lines (95 loc) · 3.06 KB

.verb.md

File metadata and controls

129 lines (95 loc) · 3.06 KB

Why another keypress module?

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.

Why use this?

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.

Usage

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();
  }
});

API

onKeypress

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);

keymap

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;
    }
  }
});

input

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();
    }
  }
});