# keyscan

> Simpler keyboard scanning for Node

Latest version **1.7.0** (published 2016-09-19) · MIT license · 0 weekly downloads

## Install

```sh
npm install keyscan
pnpm add keyscan
yarn add keyscan
bun add keyscan
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.7.0 |
| Published | 2016-09-19 |
| First published | 2016-09-17 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 0 |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 4 |
| Author | John Haugeland |
| Maintainers | stonecypher |
| Keywords | key, keyboard, getch, getc, getchar, rl, peek, scanf, sscanf, readkey, readln, yesno, prompt, yn, kbhit, keypress, getkey, get_key, read_ch, lastkey, read, getkeycode, keycode, receivechar, stdin, readline, readch, inkey, read_nonblock, keypressed |

## Links

- npm: https://www.npmjs.com/package/keyscan
- Repository: https://github.com/StoneCypher/keyscan
- Homepage: https://github.com/StoneCypher/keyscan#readme
- Issues: https://github.com/StoneCypher/keyscan/issues
- npm.io page: https://npm.io/package/keyscan

## Alternatives

- [localforage](https://npm.io/package/localforage.md) — 6.2M weekly downloads
- [localforage-observable](https://npm.io/package/localforage-observable.md) — 30.8K weekly downloads
- [@y/y](https://npm.io/package/@y/y.md) — 30.1K weekly downloads
- [@metaobjectsdev/render](https://npm.io/package/@metaobjectsdev/render.md) — 3.5K weekly downloads
- [@ledgerhq/coin-algorand](https://npm.io/package/@ledgerhq/coin-algorand.md) — 1.1K weekly downloads

## Recent versions

- 1.7.0 (latest) — 2016-09-19
- 0.6.0 — 2016-09-18
- 0.5.1 — 2016-09-18
- 0.5.0 — 2016-09-18
- 0.4.3 — 2016-09-18
- 0.4.2 — 2016-09-18
- 0.4.1 — 2016-09-18
- 0.3.0 — 2016-09-18
- 0.2.0 — 2016-09-18
- 0.0.1 — 2016-09-17

## README

# keyscan

Simple keyboard scanning for `node`

```javascript
require('keyscan').make_scanner( (ch) => console.log('Caught ' + ch.parsed) );
```





## Aren't there a thousand of these already?

Yep.  And none of them are what I wanted.

 * One-liner node keypress handling
 * No need to configure beyond saying "this is the handler"
 * Suppress echo by default
 * Configurable (and removable) kill key(s)
 * Special keys (eg arrow keys) interpreted down to common sense strings
 * `readline` various-field defect repaired





# Basic usage

Provide a function to `keyscan`.  That function will be called whenever a non-control keyboard input is detected, with an object describing the input.

The object passed back to your handler function is a single depth flat object with six fields - the five mimicing what is exposed by the [raw mode readline interface](https://nodejs.org/api/readline.html#readline_readline_emitkeypressevents_stream_interface), plus a new field named `parsed`.

Generally you should use `parsed`, which is just `(.name || .sequence)`.  In most cases `.parsed` will contain `.name`, but there are characters (such as `@`) which have no `.name`.  Checking for that and deferring to `.sequence` is a hassle, so, the `.parsed` property now reliably contains that behavior.

It's worth noting that `.name` frequently translates multiple keypresses to single keypresses (which is its purpose.)  As a result, you may get keys represented in `.parsed` as strings like `'pagedown'` and `'backspace'`.

## Example objects

This is the up arrow:
```javascript
{
  "sequence": "\u001b[A",
  "name": "up",
  "ctrl": false,
  "meta": false,
  "shift": false,
  "code": "[A",
  "parsed": "up"
}
```

This is page down:
```javascript
{
  "sequence": "\u001b[6~",
  "name": "pagedown",
  "ctrl": false,
  "meta": false,
  "shift": false,
  "code": "[6~",
  "parsed": "pagedown"
}
```

This is capital A produced with shift (note that only `.sequence` retains case)
```javascript
{
  "sequence": "A",
  "name": "a",
  "ctrl": false,
  "meta": false,
  "shift": true,
  "parsed": "a"
}
```

This is capital A produced with caps lock (note that `.shift` is false here, unlike above)
```javascript
{
  "sequence": "A",
  "name": "a",
  "ctrl": false,
  "meta": false,
  "shift": false,
  "parsed": "a"
}
```

This is `ctrl+z`
```javascript
{
  "sequence": "\u001a",
  "name": "z",
  "ctrl": true,
  "meta": false,
  "shift": false,
  "parsed": "z"
}
```

Because of the integrated approach to control keys, you will ***not*** get events when people hit, say, `shift` or `caps lock` on their own.  This is what most applications want and need, but it's not right for many action games, which may want to use control keys as weapon buttons.

On `Windows` and `Linux` platforms, `meta` is called `alt`.  On `Macintosh`es, `meta` is called `option`.

Code examples are often more readable.





## ES5 Example

For the most part, you'll want the `.parsed` property, which has the lower case character for letters, the symbol for symbols, and a string like 'down' for arrow keys.

If you're in an `es5` environment:

```javascript
console.log('Type ctrl+c to exit.\n-------------------\n');

var echo_ch = function(ks) { console.log('Caught ' + JSON.stringify(ks.parsed)); },

    keyscan = require('../dist/keyscan.js'),
    scanner = keyscan.make_scanner({ out: echo_ch });
```





### Result

You'll see something like this:

```
$ node demo/es5_demo.js

Type ctrl+c to exit.
-------------------

Caught a
Caught b
Caught c
Caught 1
Caught 2
Caught %
Caught ^
Caught up
Caught right
Caught delete
Caught pagedown
Caught end
Caught home
```





## Premades

There are also some convenience pre-made filters, such as

* `scanner.yn(opts)` - for yes/no - pre-configured to filter for `['y','n']`
  * `scanner.ync(opts)` - for yes/no/cancel - pre-configured to filter for `['y','n','c']`
* `scanner.abc(opts)` - for abc multiple choice - pre-configured to filter for `['a','b','c']`
  * `scanner.abcd(opts)` - for abcd multiple choice - pre-configured to filter for `['a','b','c','d']`
* `scanner.d09(opts)` - for star ratings - pre-configured to filter for digits `['0','1','2','3','4','5','6','7','8','9']`
  * `scanner.d14(opts)` - for star ratings - like `.d09()` but only accepts 1-4
  * `scanner.d15(opts)` - for star ratings - like `.d14()` but 1-5
  * `scanner.d19(opts)` - for 1-9 ratings - like `.d09()` but excludes zeroes
* `scanner.d09c(opts)` - for digits - also accepts `'c'`, for cancellation
  * `scanner.d14c(opts)`
  * `scanner.d15c(opts)`
  * `scanner.d19c(opts)`




## ES5 Full-Show Example

If you'd like to see the full keypress data instead, letting you see control modes and the raw character sequence, try this instead:

```javascript
console.log('Type ctrl+c to exit.\n-------------------\n');

var echo_ch = function(ch) { console.log('Caught ' + JSON.stringify(ch)); },

    keyscan = require('../dist/keyscan.js'),
    scanner = keyscan.make_scanner({ out: echo_ch });
```





### Result

You'll see something like this:

```
$ node demo/es5_demo.js

Type ctrl+c to exit.
-------------------

Caught {"sequence":"a","name":"a","ctrl":false,"meta":false,"shift":false,"parsed":"a"}
Caught {"sequence":"s","name":"s","ctrl":false,"meta":false,"shift":false,"parsed":"s"}
Caught {"sequence":"d","name":"d","ctrl":false,"meta":false,"shift":false,"parsed":"d"}
Caught {"sequence":"!","ctrl":false,"meta":false,"shift":false,"parsed":"!"}
Caught {"sequence":"@","ctrl":false,"meta":false,"shift":false,"parsed":"@"}
Caught {"sequence":"\u001b[A","name":"up","ctrl":false,"meta":false,"shift":false,"code":"[A","parsed":"up"}
Caught {"sequence":"\u001b[D","name":"left","ctrl":false,"meta":false,"shift":false,"code":"[D","parsed":"left"}
Caught {"sequence":"\u001b[C","name":"right","ctrl":false,"meta":false,"shift":false,"code":"[C","parsed":"right"}
Caught {"sequence":"\u001b[B","name":"down","ctrl":false,"meta":false,"shift":false,"code":"[B","parsed":"down"}
Caught {"sequence":"\u001b[6~","name":"pagedown","ctrl":false,"meta":false,"shift":false,"code":"[6~","parsed":"pagedown"}
Caught {"sequence":"\u001b[5~","name":"pageup","ctrl":false,"meta":false,"shift":false,"code":"[5~","parsed":"pageup"}
Caught {"sequence":"\u0003","name":"c","ctrl":true,"meta":false,"shift":false,"parsed":"c"}
```




## ES6 Module Example

In an `es6` environment with `module` support (ie, not `node` yet,)

```javascript
console.log('Type ctrl+c to exit.\n-------------------\n');

import { make_scanner } from 'keyscan';

const keyscan = make_scanner({ out: function(ch) { console.log('Caught ' + JSON.stringify(ch)); } });
```





### Result

You'll see something like this:

```
$ node demo/es5_demo.js

Type ctrl+c to exit.
-------------------

Caught {"sequence":"a","name":"a","ctrl":false,"meta":false,"shift":false,"parsed":"a"}
```





# Other features

The key scanner offers other features as well.





## Manually releasing the key scanner

If you want to release the scanning process without requiring the user to abort with `ctrl+c`, just `.release` the scanner.

```javascript
console.log('\nType three things, then this will exit.\n---------------------------------------\n');

var count   = 0,

    keyscan = require('../dist/keyscan.js'),
    scanner,

    echo_3x = function(ch) {
        console.log('Caught ' + JSON.stringify(ch.parsed));
        ++count;
        if (count >= 3) {
            console.log('Three items reached.  Releasing.');
            scanner.release();
        }
    },

    scanner = keyscan.make_scanner({ out: echo_3x });
```





### Result

You'll see something like this:

```
$ node demo/manual_release.js

Type three things, then this will exit.
---------------------------------------

Caught "1"
Caught "2"
Caught "3"
Three items reached.  Releasing.
```





## Replacing the kill keys with `isAbort`

If you want to keep the termination character behavior, but want it to be something other than `ctrl+c` (or multiple things,) write a function, and pass it in as `.isAbort`:

```javascript
console.log('\nType ctrl+x to exit.\n-------------------\n');

var echo_ch = function(ch) { console.log('Caught ' + JSON.stringify(ch.parsed)); },
    use_c_x = function(ch) { return (ch && (ch.ctrl) && (ch.name == 'x')); },

    keyscan = require('../dist/keyscan.js'),
    scanner = keyscan.make_scanner({ out: echo_ch, isAbort: use_c_x });
```




Todo:

* read once only
* unicode symbolic name representations
* prompt (? may not make sense, deciding)
* echo enable (wants unicode)
* map keys to outputs (eg 's' echoes 'save')
* make yn and ync show labels aftwerwards
* `.sync` (inherently `once`)

---
_Source: https://npm.io/package/keyscan · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
