├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── keycodes.js ├── package.json ├── parse-key.js └── test └── parse-key.js /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | node_modules 15 | npm-debug.log 16 | tmp 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.6 4 | - 0.8 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2013 Thorsten Lorenz. 2 | All rights reserved. 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # parse-key [![build status](https://secure.travis-ci.org/thlorenz/parse-key.png)](http://next.travis-ci.org/thlorenz/parse-key) 2 | 3 | Parses strings into key objects of the same format as the ones emitted by [nodejs readline](http://nodejs.org/api/readline.html). 4 | 5 | Counter part to [stringify-key](https://github.com/thlorenz/stringify-key). 6 | 7 | ## Installation 8 | 9 | npm i parse-key 10 | 11 | ## Usage 12 | 13 | ```js 14 | var parse = require('parse-key'); 15 | 16 | parse('ctrl-c') // returns { name: 'c', ctrl: true, meta: false, shift: false, alt: false, sequence: '\u0003' } 17 | 18 | parse('shift-ctrl-c') // returns { name: 'c', ctrl: true, meta: false, shift: true, alt: false, sequence: '\u0003' } 19 | 20 | parse('alt-c') // returns { name: 'c', ctrl: false, meta: false, shift: false, alt: true, sequence: 'c' } 21 | ``` 22 | 23 | ## Caveats 24 | 25 | For completeness' sake, the `alt` modifier is parsed and included with the returned `key` although the nodejs readline does not 26 | include it in its `key` object nor does it have any effect when the key is emitted. 27 | -------------------------------------------------------------------------------- /keycodes.js: -------------------------------------------------------------------------------- 1 | // Most of these are according to this table: http://www.ssicom.org/js/x171166.htm 2 | // However where nodejs readline diverges, they are adjusted to conform to it 3 | module.exports = { 4 | nomod: { 5 | escape: '\u001b' 6 | , space: ' ' // actually '\u0020' 7 | } 8 | , ctrl: { 9 | ' ': '\u0000' 10 | , 'a': '\u0001' 11 | , 'b': '\u0002' 12 | , 'c': '\u0003' 13 | , 'd': '\u0004' 14 | , 'e': '\u0005' 15 | , 'f': '\u0006' 16 | , 'g': '\u0007' 17 | , 'h': '\u0008' 18 | , 'i': '\u0009' 19 | , 'j': '\u000a' 20 | , 'k': '\u000b' 21 | , 'm': '\u000c' 22 | , 'n': '\u000d' 23 | , 'l': '\u000e' 24 | , 'o': '\u000f' 25 | , 'p': '\u0010' 26 | , 'q': '\u0011' 27 | , 'r': '\u0012' 28 | , 's': '\u0013' 29 | , 't': '\u0014' 30 | , 'u': '\u0015' 31 | , 'v': '\u0016' 32 | , 'w': '\u0017' 33 | , 'x': '\u0018' 34 | , 'y': '\u0019' 35 | , 'z': '\u001a' 36 | , '[': '\u001b' 37 | , '\\':'\u001c' 38 | , ']': '\u001d' 39 | , '^': '\u001e' 40 | , '_': '\u001f' 41 | 42 | , 'space': '\u0000' 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parse-key", 3 | "version": "0.2.1", 4 | "description": "Parses strings into key objects of the same format as the ones emitted by nodejs readline.", 5 | "main": "parse-key.js", 6 | "scripts": { 7 | "test": "node-trap test/*.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/thlorenz/parse-key.git" 12 | }, 13 | "keywords": [ 14 | "readline", 15 | "string", 16 | "print", 17 | "convert" 18 | ], 19 | "author": "Thorsten Lorenz (thlorenz.com)", 20 | "license": "MIT", 21 | "dependencies": {}, 22 | "devDependencies": { 23 | "trap": "~0.3.2" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /parse-key.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var keycodes = require('./keycodes'); 4 | 5 | function assertKeyString(s) { 6 | if (!/^(ctrl-|shift-|alt-|meta-){0,4}\w+$/.test(s)) 7 | throw new Error('The string to parse needs to be of the format "c", "ctrl-c", "shift-ctrl-c".'); 8 | } 9 | 10 | module.exports = function parse(s) { 11 | var keyString = s.trim().toLowerCase(); 12 | 13 | assertKeyString(keyString); 14 | 15 | var key = { 16 | name : undefined 17 | , ctrl : false 18 | , meta : false 19 | , shift : false 20 | , alt : false 21 | , sequence : undefined 22 | } 23 | , parts = keyString.split('-') 24 | , c; 25 | 26 | key.name = parts.pop(); 27 | while((c = parts.pop())) key[c] = true; 28 | key.sequence = key.ctrl 29 | ? keycodes.ctrl[key.name] || key.name 30 | : keycodes.nomod[key.name] || key.name; 31 | 32 | // uppercase sequence for single chars when shift was pressed 33 | if (key.shift && key.sequence && key.sequence.length === 1) 34 | key.sequence = key.sequence.toUpperCase(); 35 | 36 | return key; 37 | }; 38 | -------------------------------------------------------------------------------- /test/parse-key.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /*jshint asi:true */ 3 | 4 | var test = require('trap').test 5 | , parse = require('..') 6 | 7 | function inspect(obj, depth) { 8 | return require('util').inspect(obj, false, depth || 5, true); 9 | } 10 | 11 | function assert(t, s, key) { 12 | t.deepEqual(parse(s), key, 'parsing ' + s + ' returns ' + inspect(key)) 13 | } 14 | 15 | test('keys without modifiers', function (t) { 16 | assert(t , 's' , { name: 's' , ctrl: false , meta: false , shift: false , alt: false , sequence: 's'}) 17 | assert(t , 'c' , { name: 'c' , ctrl: false , meta: false , shift: false , alt: false , sequence: 'c'}) 18 | assert(t , 'space' , { name: 'space' , ctrl: false , meta: false , shift: false , alt: false , sequence: ' ' }) 19 | assert(t , 'escape' , { name: 'escape' , ctrl: false , meta: false , shift: false , alt: false , sequence: '\u001b' }) 20 | }) 21 | 22 | test('keys with one modifier', function (t) { 23 | assert(t, 'ctrl-c' , { name:'c' , ctrl: true , meta: false , shift: false , alt: false, sequence: '\u0003' }) 24 | assert(t, 'meta-c' , { name:'c' , ctrl: false , meta: true , shift: false , alt: false, sequence: 'c' }) 25 | assert(t, 'shift-c' , { name:'c' , ctrl: false , meta: false , shift: true , alt: false, sequence: 'C' }) 26 | assert(t, 'alt-c' , { name:'c' , ctrl: false , meta: false , shift: false , alt: true, sequence: 'c' }) 27 | 28 | assert(t, 'ctrl-space', { name: 'space', ctrl: true, meta: false, shift: false, alt: false, sequence: '\u0000' }) 29 | }) 30 | 31 | test('keys with one modifier with mixed casing', function (t) { 32 | assert(t , 'Ctrl-c' , { name:'c' , ctrl: true , meta: false , shift: false , alt: false , sequence: '\u0003' }) 33 | assert(t , 'meta-C' , { name:'c' , ctrl: false , meta: true , shift: false , alt: false , sequence: 'c' }) 34 | assert(t , 'Shift-c' , { name:'c' , ctrl: false , meta: false , shift: true , alt: false , sequence: 'C' }) 35 | assert(t , 'ALT-c' , { name:'c' , ctrl: false , meta: false , shift: false , alt: true , sequence: 'c' }) 36 | }) 37 | 38 | test('keys with multiple modifiers', function (t) { 39 | assert(t , 'shift-ctrl-c' , { name:'c' , ctrl: true , meta: false , shift: true , alt: false , sequence: '\u0003' }) 40 | assert(t , 'alt-meta-c' , { name:'c' , ctrl: false , meta: true , shift: false , alt: true , sequence: 'c' }) 41 | assert(t , 'shift-ctrl-meta-c' , { name:'c' , ctrl: true , meta: true , shift: true , alt: false , sequence: '\u0003' }) 42 | assert(t , 'alt-shift-ctrl-meta-c' , { name:'c' , ctrl: true , meta: true , shift: true , alt: true , sequence: '\u0003' }) 43 | assert(t , 'shift-ctrl-escape' , { name: 'escape' , ctrl: true , meta: false , shift: true , alt: false , sequence: 'escape' }) 44 | }) 45 | --------------------------------------------------------------------------------