Comparing version
var program = require('./')() | ||
, minimist = require('minimist') | ||
, result | ||
var minimist = require('minimist') | ||
var result | ||
result = program | ||
.register('abcd', function(args) { | ||
.register('abcd', function (args) { | ||
console.log('just do', args) | ||
}) | ||
.register('args', function(args) { | ||
.register({ command: 'restore', strict: true }, function (args) { | ||
console.log('restore', args) | ||
}) | ||
.register('args', function (args) { | ||
args = minimist(args) | ||
console.log('just do', args) | ||
}) | ||
.register('abcde code', function(args) { | ||
.register('abcde code', function (args) { | ||
console.log('doing something', args) | ||
}) | ||
.register('another command', function(args) { | ||
.register('another command', function (args) { | ||
console.log('anothering', args) | ||
@@ -19,0 +22,0 @@ }) |
92
index.js
@@ -25,27 +25,23 @@ /* | ||
'use strict'; | ||
'use strict' | ||
var leven = require('leven') | ||
function commist() { | ||
function commist () { | ||
var commands = [] | ||
function lookup(array) { | ||
if (typeof array === 'string') | ||
array = array.split(' ') | ||
function lookup (array) { | ||
if (typeof array === 'string') { array = array.split(' ') } | ||
return commands.map(function(cmd) { | ||
return commands.map(function (cmd) { | ||
return cmd.match(array) | ||
}).filter(function(match) { | ||
}).filter(function (match) { | ||
return match.partsNotMatched === 0 | ||
}).sort(function(a, b) { | ||
if (a.inputNotMatched > b.inputNotMatched) | ||
return 1 | ||
}).sort(function (a, b) { | ||
if (a.inputNotMatched > b.inputNotMatched) { return 1 } | ||
if (a.inputNotMatched === b.inputNotMatched && a.totalDistance > b.totalDistance) | ||
return 1 | ||
if (a.inputNotMatched === b.inputNotMatched && a.totalDistance > b.totalDistance) { return 1 } | ||
return -1 | ||
}).map(function(match) { | ||
}).map(function (match) { | ||
return match.cmd | ||
@@ -55,3 +51,3 @@ }) | ||
function parse(args) { | ||
function parse (args) { | ||
var matching = lookup(args) | ||
@@ -69,11 +65,20 @@ | ||
function register(command, func) { | ||
var matching = lookup(command) | ||
function register (inputCommand, func) { | ||
var commandOptions = { | ||
command: inputCommand, | ||
strict: false, | ||
func: func | ||
} | ||
matching.forEach(function(match) { | ||
if (match.string === command) | ||
throw new Error('command already registered: ' + command) | ||
if (typeof inputCommand === 'object') { | ||
commandOptions = Object.assign(commandOptions, inputCommand) | ||
} | ||
var matching = lookup(commandOptions.command) | ||
matching.forEach(function (match) { | ||
if (match.string === commandOptions.command) { throw new Error('command already registered: ' + commandOptions.command) } | ||
}) | ||
commands.push(new Command(command, func)) | ||
commands.push(new Command(commandOptions)) | ||
@@ -84,36 +89,39 @@ return this | ||
return { | ||
register: register | ||
, parse: parse | ||
, lookup: lookup | ||
register: register, | ||
parse: parse, | ||
lookup: lookup | ||
} | ||
} | ||
function Command(string, func) { | ||
this.string = string | ||
this.parts = string.split(' ') | ||
this.length = this.parts.length | ||
this.func = func | ||
function Command (options) { | ||
this.string = options.command | ||
this.strict = options.strict | ||
this.parts = this.string.split(' ') | ||
this.length = this.parts.length | ||
this.func = options.func | ||
this.parts.forEach(function(part) { | ||
if (part.length < 3) | ||
throw new Error('command words must be at least 3 chars: ' + command) | ||
this.parts.forEach(function (part) { | ||
if (part.length < 3) { throw new Error('command words must be at least 3 chars: ' + options.command) } | ||
}) | ||
} | ||
Command.prototype.call = function call(argv) { | ||
Command.prototype.call = function call (argv) { | ||
this.func(argv.slice(this.length)) | ||
} | ||
Command.prototype.match = function match(string) { | ||
Command.prototype.match = function match (string) { | ||
return new CommandMatch(this, string) | ||
} | ||
function CommandMatch(cmd, array) { | ||
function CommandMatch (cmd, array) { | ||
this.cmd = cmd | ||
this.distances = cmd.parts.map(function(elem, i) { | ||
if (array[i] !== undefined) | ||
return leven(elem, array[i]) | ||
else | ||
return undefined | ||
}).filter(function(distance, i) { | ||
this.distances = cmd.parts.map(function (elem, i) { | ||
if (array[i] !== undefined) { | ||
if (cmd.strict) { | ||
return elem === array[i] ? 0 : undefined | ||
} else { | ||
return leven(elem, array[i]) | ||
} | ||
} else { return undefined } | ||
}).filter(function (distance, i) { | ||
return distance !== undefined && distance < cmd.parts[i].length - 2 | ||
@@ -124,5 +132,5 @@ }) | ||
this.inputNotMatched = array.length - this.distances.length | ||
this.totalDistance = this.distances.reduce(function(acc, i) { return acc + i }, 0) | ||
this.totalDistance = this.distances.reduce(function (acc, i) { return acc + i }, 0) | ||
} | ||
module.exports = commist |
{ | ||
"name": "commist", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Build your commands on minimist!", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "tap test.js" | ||
"test": "standard && tape test.js" | ||
}, | ||
@@ -21,3 +21,3 @@ "pre-commit": "test", | ||
"dependencies": { | ||
"leven": "^1.0.0", | ||
"leven": "^2.1.0", | ||
"minimist": "^1.1.0" | ||
@@ -27,5 +27,6 @@ }, | ||
"minimist": "^1.1.0", | ||
"pre-commit": "0.0.9", | ||
"tape": "^3.0.3" | ||
"pre-commit": "^1.0.0", | ||
"standard": "^12.0.1", | ||
"tape": "^4.0.0" | ||
} | ||
} |
commist | ||
======= | ||
[](https://travis-ci.com/mcollina/commist) | ||
Build command line application with multiple commands the easy way. | ||
@@ -16,2 +18,5 @@ To be used with [minimist](http://npm.im/minimist). | ||
}) | ||
.register({ command: 'restore', equals: true }, function(args) { | ||
console.log('restore', args) | ||
}) | ||
.register('args', function(args) { | ||
@@ -49,2 +54,11 @@ args = minimist(args) | ||
If you want that the command must be strict equals, you can register the | ||
command with the json configuration: | ||
```js | ||
program.register({ command: 'restore', strict: true }, function(args) { | ||
console.log('restore', args) | ||
}) | ||
``` | ||
Acknowledgements | ||
@@ -51,0 +65,0 @@ ---------------- |
103
test.js
var test = require('tape').test | ||
, commist = require('./') | ||
, minimist = require('minimist') | ||
var test = require('tape').test | ||
test('registering a command', function(t) { | ||
var commist = require('./') | ||
test('registering a command', function (t) { | ||
t.plan(2) | ||
var program = commist() | ||
, result | ||
program.register('hello', function(args) { | ||
var result | ||
program.register('hello', function (args) { | ||
t.deepEqual(args, ['a', '-x', '23']) | ||
@@ -21,13 +22,12 @@ }) | ||
test('registering two commands', function(t) { | ||
test('registering two commands', function (t) { | ||
t.plan(1) | ||
var program = commist() | ||
, result | ||
program.register('hello', function(args) { | ||
program.register('hello', function (args) { | ||
t.ok(false, 'must pick the right command') | ||
}) | ||
program.register('world', function(args) { | ||
program.register('world', function (args) { | ||
t.deepEqual(args, ['a', '-x', '23']) | ||
@@ -39,13 +39,12 @@ }) | ||
test('registering two commands (bis)', function(t) { | ||
test('registering two commands (bis)', function (t) { | ||
t.plan(1) | ||
var program = commist() | ||
, result | ||
program.register('hello', function(args) { | ||
program.register('hello', function (args) { | ||
t.deepEqual(args, ['a', '-x', '23']) | ||
}) | ||
program.register('world', function(args) { | ||
program.register('world', function (args) { | ||
t.ok(false, 'must pick the right command') | ||
@@ -57,13 +56,12 @@ }) | ||
test('registering two words commands', function(t) { | ||
test('registering two words commands', function (t) { | ||
t.plan(1) | ||
var program = commist() | ||
, result | ||
program.register('hello', function(args) { | ||
program.register('hello', function (args) { | ||
t.ok(false, 'must pick the right command') | ||
}) | ||
program.register('hello world', function(args) { | ||
program.register('hello world', function (args) { | ||
t.deepEqual(args, ['a', '-x', '23']) | ||
@@ -75,13 +73,12 @@ }) | ||
test('registering two words commands (bis)', function(t) { | ||
test('registering two words commands (bis)', function (t) { | ||
t.plan(1) | ||
var program = commist() | ||
, result | ||
program.register('hello', function(args) { | ||
program.register('hello', function (args) { | ||
t.deepEqual(args, ['a', '-x', '23']) | ||
}) | ||
program.register('hello world', function(args) { | ||
program.register('hello world', function (args) { | ||
t.ok(false, 'must pick the right command') | ||
@@ -93,7 +90,6 @@ }) | ||
test('registering ambiguous commands throws exception', function(t) { | ||
test('registering ambiguous commands throws exception', function (t) { | ||
var program = commist() | ||
, result | ||
function noop() {} | ||
function noop () {} | ||
@@ -107,3 +103,3 @@ program.register('hello', noop) | ||
t.ok(false, 'must throw if double-registering the same command') | ||
} catch(err) { | ||
} catch (err) { | ||
} | ||
@@ -114,9 +110,8 @@ | ||
test('looking up commands', function(t) { | ||
test('looking up commands', function (t) { | ||
var program = commist() | ||
, result | ||
function noop1() {} | ||
function noop2() {} | ||
function noop3() {} | ||
function noop1 () {} | ||
function noop2 () {} | ||
function noop3 () {} | ||
@@ -134,9 +129,8 @@ program.register('hello', noop1) | ||
test('looking up commands with abbreviations', function(t) { | ||
test('looking up commands with abbreviations', function (t) { | ||
var program = commist() | ||
, result | ||
function noop1() {} | ||
function noop2() {} | ||
function noop3() {} | ||
function noop1 () {} | ||
function noop2 () {} | ||
function noop3 () {} | ||
@@ -154,13 +148,28 @@ program.register('hello', noop1) | ||
test('executing commands from abbreviations', function(t) { | ||
test('looking up strict commands', function (t) { | ||
var program = commist() | ||
function noop1 () {} | ||
function noop2 () {} | ||
program.register({ command: 'restore', strict: true }, noop1) | ||
program.register({ command: 'rest', strict: true }, noop2) | ||
t.equal(program.lookup('restore')[0].func, noop1) | ||
t.equal(program.lookup('rest')[0].func, noop2) | ||
t.equal(program.lookup('remove')[0], undefined) | ||
t.end() | ||
}) | ||
test('executing commands from abbreviations', function (t) { | ||
t.plan(1) | ||
var program = commist() | ||
, result | ||
program.register('hello', function(args) { | ||
program.register('hello', function (args) { | ||
t.deepEqual(args, ['a', '-x', '23']) | ||
}) | ||
program.register('hello world', function(args) { | ||
program.register('hello world', function (args) { | ||
t.ok(false, 'must pick the right command') | ||
@@ -172,7 +181,6 @@ }) | ||
test('a command must be at least 3 chars', function(t) { | ||
test('a command must be at least 3 chars', function (t) { | ||
var program = commist() | ||
, result | ||
function noop1() {} | ||
function noop1 () {} | ||
@@ -182,3 +190,3 @@ try { | ||
t.ok(false, 'not thrown') | ||
} catch(err) { | ||
} catch (err) { | ||
} | ||
@@ -189,7 +197,6 @@ | ||
test('a command part must be at least 3 chars', function(t) { | ||
test('a command part must be at least 3 chars', function (t) { | ||
var program = commist() | ||
, result | ||
function noop1() {} | ||
function noop1 () {} | ||
@@ -199,3 +206,3 @@ try { | ||
t.ok(false, 'not thrown') | ||
} catch(err) { | ||
} catch (err) { | ||
} | ||
@@ -202,0 +209,0 @@ |
12045
7.2%263
3.95%71
24.56%4
33.33%+ Added
- Removed
Updated