Comparing version 1.1.0 to 1.2.0
# node-dashdash changelog | ||
## 1.2.0 | ||
- Transform the option key on the `opts` object returned from | ||
`<parser>.parse()` for convenience. Currently this is just | ||
`s/-/_/g`, e.g. '--dry-run' -> `opts.dry_run`. This allow one to use hyphen | ||
in option names (common) but not have to do silly things like | ||
`opt["dry-run"]` to access the parsed results. | ||
## 1.1.0 | ||
@@ -4,0 +13,0 @@ |
@@ -1,52 +0,52 @@ | ||
var dashdash = require('../lib/dashdash'); | ||
var dashdash = require('../lib/dashdash'); | ||
// Specify the options. Minimally `name` (or `names`) and `type` | ||
// must be given for each. | ||
var options = [ | ||
{ | ||
name: 'version', // `name` or `names` | ||
type: 'bool', | ||
help: 'Print tool version and exit.' | ||
}, | ||
{ | ||
names: ['help', 'h'], // first name is opts key | ||
type: 'bool', | ||
help: 'Print this help and exit.' | ||
}, | ||
{ | ||
names: ['verbose', 'v'], | ||
type: 'arrayOfBool', | ||
env: 'FOO_VERBOSE', | ||
help: 'Verbose output. Use multiple times for more verbose.' | ||
}, | ||
{ | ||
names: ['file', 'f'], | ||
type: 'string', | ||
help: 'File to process', | ||
helpArg: 'FILE' | ||
} | ||
]; | ||
var parser = dashdash.createParser({options: options}); | ||
try { | ||
var opts = parser.parse(process.argv); | ||
} catch (e) { | ||
console.error('foo: error: %s', e.message); | ||
process.exit(1); | ||
// Specify the options. Minimally `name` (or `names`) and `type` | ||
// must be given for each. | ||
var options = [ | ||
{ | ||
name: 'version', // `name` or `names` | ||
type: 'bool', | ||
help: 'Print tool version and exit.' | ||
}, | ||
{ | ||
names: ['help', 'h'], // first name is opts key | ||
type: 'bool', | ||
help: 'Print this help and exit.' | ||
}, | ||
{ | ||
names: ['verbose', 'v'], | ||
type: 'arrayOfBool', | ||
env: 'FOO_VERBOSE', | ||
help: 'Verbose output. Use multiple times for more verbose.' | ||
}, | ||
{ | ||
names: ['file', 'f'], | ||
type: 'string', | ||
help: 'File to process', | ||
helpArg: 'FILE' | ||
} | ||
// Or a shortcut: | ||
// var opts = dashdash.parse({options: options}); | ||
]; | ||
console.log("# opts:", opts); | ||
console.log("# args:", opts._args); | ||
var parser = dashdash.createParser({options: options}); | ||
try { | ||
var opts = parser.parse(process.argv); | ||
} catch (e) { | ||
console.error('foo: error: %s', e.message); | ||
process.exit(1); | ||
} | ||
// Or a shortcut: | ||
// var opts = dashdash.parse({options: options}); | ||
// Use `parser.help()` for formatted options help. | ||
if (opts.help) { | ||
var help = parser.help({includeEnv: true}).trimRight(); | ||
console.log('usage: node foo.js [OPTIONS]\n' | ||
+ 'options:\n' | ||
+ help); | ||
process.exit(0); | ||
} | ||
console.log("# opts:", opts); | ||
console.log("# args:", opts._args); | ||
// ... | ||
// Use `parser.help()` for formatted options help. | ||
if (opts.help) { | ||
var help = parser.help({includeEnv: true}).trimRight(); | ||
console.log('usage: node foo.js [OPTIONS]\n' | ||
+ 'options:\n' | ||
+ help); | ||
process.exit(0); | ||
} | ||
// ... |
@@ -71,4 +71,17 @@ /** | ||
/** | ||
* Transform an option name to a "key" that is used as the field | ||
* on the `opts` object returned from `<parser>.parse()`. | ||
* | ||
* Transformations: | ||
* - '-' -> '_': This allow one to use hyphen in option names (common) | ||
* but not have to do silly things like `opt["dry-run"]` to access the | ||
* parsed results. | ||
*/ | ||
function optionKeyFromName(name) { | ||
return name.replace(/-/g, '_'); | ||
} | ||
// ---- Option types | ||
@@ -224,4 +237,4 @@ | ||
format('config.options.%d.names is empty', i)); | ||
o.name = o.names[0]; | ||
} | ||
o.key = optionKeyFromName(o.names[0]); | ||
o.names.forEach(function (n) { | ||
@@ -285,18 +298,18 @@ if (self.optionFromName[n]) { | ||
if (o.default) { | ||
opts[o.name] = o.default; | ||
opts[o.key] = o.default; | ||
} | ||
}); | ||
function addOpt(option, optstr, name, val, from) { | ||
function addOpt(option, optstr, key, val, from) { | ||
var type = types[option.type]; | ||
var parsedVal = type.parseArg(option, optstr, val); | ||
if (type.array) { | ||
if (!opts[name]) { | ||
opts[name] = []; | ||
if (!opts[key]) { | ||
opts[key] = []; | ||
} | ||
opts[name].push(parsedVal); | ||
opts[key].push(parsedVal); | ||
} else { | ||
opts[name] = parsedVal; | ||
opts[key] = parsedVal; | ||
} | ||
var item = { name: name, value: parsedVal, from: from }; | ||
var item = { key: key, value: parsedVal, from: from }; | ||
_order.push(item); | ||
@@ -335,5 +348,5 @@ } | ||
if (!takesArg) { | ||
addOpt(option, '--'+name, option.name, true, 'argv'); | ||
addOpt(option, '--'+name, option.key, true, 'argv'); | ||
} else if (val !== null) { | ||
addOpt(option, '--'+name, option.name, val, 'argv'); | ||
addOpt(option, '--'+name, option.key, val, 'argv'); | ||
} else if (i + 1 >= args.length) { | ||
@@ -343,3 +356,3 @@ throw new Error(format('do not have enough args for "--%s" ' | ||
} else { | ||
addOpt(option, '--'+name, option.name, args[i + 1], 'argv'); | ||
addOpt(option, '--'+name, option.key, args[i + 1], 'argv'); | ||
i++; | ||
@@ -367,5 +380,5 @@ } | ||
if (!takesArg) { | ||
addOpt(option, '-'+name, option.name, true, 'argv'); | ||
addOpt(option, '-'+name, option.key, true, 'argv'); | ||
} else if (val) { | ||
addOpt(option, '-'+name, option.name, val, 'argv'); | ||
addOpt(option, '-'+name, option.key, val, 'argv'); | ||
break; | ||
@@ -377,3 +390,3 @@ } else { | ||
} | ||
addOpt(option, '-'+name, option.name, args[i + 1], 'argv'); | ||
addOpt(option, '-'+name, option.key, args[i + 1], 'argv'); | ||
i++; | ||
@@ -403,12 +416,11 @@ break; | ||
var option = self.optionFromEnv[envname]; | ||
var name = option.name; | ||
if (opts[name] !== undefined) | ||
if (opts[option.key] !== undefined) | ||
return; | ||
var takesArg = self.optionTakesArg(option); | ||
if (takesArg) { | ||
addOpt(option, envname, option.name, val, 'env'); | ||
addOpt(option, envname, option.key, val, 'env'); | ||
} else if (val) { | ||
// For now, we make VAR=<empty-string> NOT set the value | ||
// false. It is as if the VAR was not set. | ||
addOpt(option, envname, option.name, true, 'env'); | ||
addOpt(option, envname, option.key, true, 'env'); | ||
} | ||
@@ -415,0 +427,0 @@ }); |
{ | ||
"name": "dashdash", | ||
"description": "A light, featureful and explicit option parsing library.", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"author": "Trent Mick (trentm.com)", | ||
@@ -6,0 +6,0 @@ "repository": { |
264
README.md
@@ -17,22 +17,24 @@ A light, featureful and explicit option parsing library for node.js. | ||
var dashdash = require('dashdash'); | ||
```javascript | ||
var dashdash = require('dashdash'); | ||
// Specify the options. Minimally `name` (or `names`) and `type` | ||
// must be given for each. | ||
var options = [ | ||
{ | ||
// `names` or a single `name`. First element is the `opts.KEY`. | ||
names: ['help', 'h'], | ||
// See "Option config" below for types. | ||
type: 'bool', | ||
help: 'Print this help and exit.' | ||
} | ||
]; | ||
// Specify the options. Minimally `name` (or `names`) and `type` | ||
// must be given for each. | ||
var options = [ | ||
{ | ||
// `names` or a single `name`. First element is the `opts.KEY`. | ||
names: ['help', 'h'], | ||
// See "Option config" below for types. | ||
type: 'bool', | ||
help: 'Print this help and exit.' | ||
} | ||
]; | ||
// Shortcut form. As called it infers `process.argv`. See below for | ||
// the longer form to use methods like `.help()` on the Parser object. | ||
var opts = dashdash.parse({options: options}); | ||
// Shortcut form. As called it infers `process.argv`. See below for | ||
// the longer form to use methods like `.help()` on the Parser object. | ||
var opts = dashdash.parse({options: options}); | ||
console.log("opts:", opts); | ||
console.log("args:", opts._args); | ||
console.log("opts:", opts); | ||
console.log("args:", opts._args); | ||
``` | ||
@@ -45,93 +47,97 @@ | ||
var dashdash = require('./lib/dashdash'); | ||
```javascript | ||
var dashdash = require('./lib/dashdash'); | ||
var options = [ | ||
{ | ||
name: 'version', | ||
type: 'bool', | ||
help: 'Print tool version and exit.' | ||
}, | ||
{ | ||
names: ['help', 'h'], | ||
type: 'bool', | ||
help: 'Print this help and exit.' | ||
}, | ||
{ | ||
names: ['verbose', 'v'], | ||
type: 'arrayOfBool', | ||
help: 'Verbose output. Use multiple times for more verbose.' | ||
}, | ||
{ | ||
names: ['file', 'f'], | ||
type: 'string', | ||
help: 'File to process', | ||
helpArg: 'FILE' | ||
} | ||
]; | ||
var parser = dashdash.createParser({options: options}); | ||
try { | ||
var opts = parser.parse(process.argv); | ||
} catch (e) { | ||
console.error('foo: error: %s', e.message); | ||
process.exit(1); | ||
var options = [ | ||
{ | ||
name: 'version', | ||
type: 'bool', | ||
help: 'Print tool version and exit.' | ||
}, | ||
{ | ||
names: ['help', 'h'], | ||
type: 'bool', | ||
help: 'Print this help and exit.' | ||
}, | ||
{ | ||
names: ['verbose', 'v'], | ||
type: 'arrayOfBool', | ||
help: 'Verbose output. Use multiple times for more verbose.' | ||
}, | ||
{ | ||
names: ['file', 'f'], | ||
type: 'string', | ||
help: 'File to process', | ||
helpArg: 'FILE' | ||
} | ||
]; | ||
console.log("# opts:", opts); | ||
console.log("# args:", opts._args); | ||
var parser = dashdash.createParser({options: options}); | ||
try { | ||
var opts = parser.parse(process.argv); | ||
} catch (e) { | ||
console.error('foo: error: %s', e.message); | ||
process.exit(1); | ||
} | ||
// Use `parser.help()` for formatted options help. | ||
if (opts.help) { | ||
var help = parser.help({includeEnv: true}).trimRight(); | ||
console.log('usage: node foo.js [OPTIONS]\n' | ||
+ 'options:\n' | ||
+ help); | ||
process.exit(0); | ||
} | ||
console.log("# opts:", opts); | ||
console.log("# args:", opts._args); | ||
// ... | ||
// Use `parser.help()` for formatted options help. | ||
if (opts.help) { | ||
var help = parser.help({includeEnv: true}).trimRight(); | ||
console.log('usage: node foo.js [OPTIONS]\n' | ||
+ 'options:\n' | ||
+ help); | ||
process.exit(0); | ||
} | ||
// ... | ||
``` | ||
Some example output from this script (foo.js): | ||
$ node foo.js -h | ||
# opts: { help: true, | ||
_order: [ { name: 'help', value: true, from: 'argv' } ], | ||
_args: [] } | ||
# args: [] | ||
usage: node foo.js [OPTIONS] | ||
options: | ||
--version Print tool version and exit. | ||
-h, --help Print this help and exit. | ||
-v, --verbose Verbose output. Use multiple times for more verbose. | ||
-f FILE, --file=FILE File to process | ||
``` | ||
$ node foo.js -h | ||
# opts: { help: true, | ||
_order: [ { name: 'help', value: true, from: 'argv' } ], | ||
_args: [] } | ||
# args: [] | ||
usage: node foo.js [OPTIONS] | ||
options: | ||
--version Print tool version and exit. | ||
-h, --help Print this help and exit. | ||
-v, --verbose Verbose output. Use multiple times for more verbose. | ||
-f FILE, --file=FILE File to process | ||
$ node foo.js -v | ||
# opts: { verbose: [ true ], | ||
_order: [ { name: 'verbose', value: true, from: 'argv' } ], | ||
_args: [] } | ||
# args: [] | ||
$ node foo.js -v | ||
# opts: { verbose: [ true ], | ||
_order: [ { name: 'verbose', value: true, from: 'argv' } ], | ||
_args: [] } | ||
# args: [] | ||
$ node foo.js --version arg1 | ||
# opts: { version: true, | ||
_order: [ { name: 'version', value: true, from: 'argv' } ], | ||
_args: [ 'arg1' ] } | ||
# args: [ 'arg1' ] | ||
$ node foo.js --version arg1 | ||
# opts: { version: true, | ||
_order: [ { name: 'version', value: true, from: 'argv' } ], | ||
_args: [ 'arg1' ] } | ||
# args: [ 'arg1' ] | ||
$ node foo.js -f bar.txt | ||
# opts: { file: 'bar.txt', | ||
_order: [ { name: 'file', value: 'bar.txt', from: 'argv' } ], | ||
_args: [] } | ||
# args: [] | ||
$ node foo.js -f bar.txt | ||
# opts: { file: 'bar.txt', | ||
_order: [ { name: 'file', value: 'bar.txt', from: 'argv' } ], | ||
_args: [] } | ||
# args: [] | ||
$ node foo.js -vvv --file=blah | ||
# opts: { verbose: [ true, true, true ], | ||
file: 'blah', | ||
_order: | ||
[ { name: 'verbose', value: true, from: 'argv' }, | ||
{ name: 'verbose', value: true, from: 'argv' }, | ||
{ name: 'verbose', value: true, from: 'argv' }, | ||
{ name: 'file', value: 'blah', from: 'argv' } ], | ||
_args: [] } | ||
# args: [] | ||
$ node foo.js -vvv --file=blah | ||
# opts: { verbose: [ true, true, true ], | ||
file: 'blah', | ||
_order: | ||
[ { name: 'verbose', value: true, from: 'argv' }, | ||
{ name: 'verbose', value: true, from: 'argv' }, | ||
{ name: 'verbose', value: true, from: 'argv' }, | ||
{ name: 'file', value: 'blah', from: 'argv' } ], | ||
_args: [] } | ||
# args: [] | ||
``` | ||
@@ -145,8 +151,10 @@ | ||
{ | ||
names: ['verbose', 'v'], | ||
type: 'arrayOfBool', | ||
env: 'FOO_VERBOSE', // <--- add this line | ||
help: 'Verbose output. Use multiple times for more verbose.' | ||
}, | ||
```javascript | ||
{ | ||
names: ['verbose', 'v'], | ||
type: 'arrayOfBool', | ||
env: 'FOO_VERBOSE', // <--- add this line | ||
help: 'Verbose output. Use multiple times for more verbose.' | ||
}, | ||
``` | ||
@@ -156,7 +164,9 @@ then the **"FOO_VERBOSE" environment variable** can be used to set this | ||
$ FOO_VERBOSE=1 node foo.js | ||
# opts: { verbose: [ true ], | ||
_order: [ { name: 'verbose', value: true, from: 'env' } ], | ||
_args: [] } | ||
# args: [] | ||
```shell | ||
$ FOO_VERBOSE=1 node foo.js | ||
# opts: { verbose: [ true ], | ||
_order: [ { name: 'verbose', value: true, from: 'env' } ], | ||
_args: [] } | ||
# args: [] | ||
``` | ||
@@ -177,9 +187,5 @@ With the `includeEnv: true` config to `parser.help()` the environment | ||
`dashdash.createParser` (a.k.a. `new dashdash.Parser`) supports the following | ||
configuration arguments: | ||
Parser construction (i.e. `dashdash.createParser(CONFIG)`) takes the | ||
following fields: | ||
dashdash.createParser({options: options, [...]}); | ||
These are: | ||
- `options` (Array of option specs). Required. See the | ||
@@ -199,2 +205,15 @@ [Option specs](#option-specs) section below. | ||
Example using all fields: | ||
```javascript | ||
{ | ||
names: ['file', 'f'], // Required (or `name`). | ||
type: 'string', // Required. | ||
env: 'MYTOOL_FILE', | ||
help: 'Config file to load before running "mytool"', | ||
helpArg: 'PATH', | ||
default: path.resolve(process.env.HOME, '.mytoolrc') | ||
} | ||
``` | ||
Each option spec in the `options` array must/can have the following fields: | ||
@@ -279,19 +298,24 @@ | ||
`nopt` really is just for "tools like npm". Implicit opts (e.g. '--no-foo' | ||
- `nopt` really is just for "tools like npm". Implicit opts (e.g. '--no-foo' | ||
works for every '--foo'). Can't disable abbreviated opts. Can't do multiple | ||
usages of same opt, e.g. '-vvv' (I think). Can't do grouped short opts. | ||
`optimist` surprises. Implicit opts. `process.exit` calls. | ||
- `optimist` has surprise interpretation of options (at least to me). | ||
Implicit opts mean ambiguities and poor error handling for fat-fingering. | ||
`process.exit` calls makes it hard to use as a libary. | ||
`optparse` Incomplete docs. Is this an attempted clone of Python's `optparse`. | ||
Not clear. Some divergence. `parser.on("name", ...)` API is weird. | ||
- `optparse` Incomplete docs. Is this an attempted clone of Python's `optparse`. | ||
Not clear. Some divergence. `parser.on("name", ...)` API is weird. | ||
`argparse` Dep on underscore. No thanks. `find lib | wc -l` -> `26`. Overkill. | ||
Argparse is a bit different anyway. Not sure I want that. | ||
- `argparse` Dep on underscore. No thanks just for option processing. | ||
`find lib | wc -l` -> `26`. Overkill. | ||
Argparse is a bit different anyway. Not sure I want that. | ||
`posix-getopt` No type validation. Though that isn't a killer. AFAIK can't | ||
have a long opt without a short alias. I.e. not `getopt_long` semantics. | ||
- `posix-getopt` No type validation. Though that isn't a killer. AFAIK can't | ||
have a long opt without a short alias. I.e. no `getopt_long` semantics. | ||
Also, no whizbang features like generated help output. | ||
# License | ||
MIT. See LICENSE.txt. |
@@ -259,3 +259,4 @@ /* | ||
all: true, | ||
_order: [ {from: 'argv', l: true}, {from: 'argv', all: true} ], | ||
_order: [ {key: 'l', value: true, from: 'argv'}, | ||
{key: 'all', value: true, from: 'argv'} ], | ||
_args: ['dir'] | ||
@@ -271,3 +272,4 @@ } | ||
all: true, | ||
_order: [ {from: 'argv', l: true}, {from: 'argv', all: true} ], | ||
_order: [ {key: 'l', value: true, from: 'argv'}, | ||
{key: 'all', value: true, from: 'argv'} ], | ||
_args: ['dir'] | ||
@@ -283,3 +285,3 @@ } | ||
l: true, | ||
_order: [ {from: 'argv', l: true} ], | ||
_order: [ {key: 'l', value: true, from: 'argv'} ], | ||
_args: ['dir', '-a'] | ||
@@ -485,3 +487,7 @@ } | ||
/* JSSTYLED */ | ||
expect: { v: true, _args: [], _order: [{from: 'argv', v: true}] } | ||
expect: { | ||
v: true, | ||
_args: [], | ||
_order: [ {key: 'v', value: true, from: 'argv'} ] | ||
} | ||
}, | ||
@@ -493,3 +499,7 @@ { | ||
/* JSSTYLED */ | ||
expect: { v: true, _args: [], _order: [{from: 'argv', v: true}] } | ||
expect: { | ||
v: true, | ||
_args: [], | ||
_order: [ {key: 'v', value: true, from: 'argv'} ] | ||
} | ||
}, | ||
@@ -500,4 +510,7 @@ { | ||
env: {FOO_VERBOSE: '1'}, | ||
/* JSSTYLED */ | ||
expect: { v: true, _args: [], _order: [{from: 'env', v: true}] } | ||
expect: { | ||
v: true, | ||
_args: [], | ||
_order: [ {key: 'v', value: true, from: 'env'} ] | ||
} | ||
}, | ||
@@ -510,4 +523,7 @@ { | ||
env: {FOO_VERBOSE: '0'}, | ||
/* JSSTYLED */ | ||
expect: { v: true, _args: [], _order: [{from: 'env', v: true}] } | ||
expect: { | ||
v: true, | ||
_args: [], | ||
_order: [ {key: 'v', value: true, from: 'env'} ] | ||
} | ||
}, | ||
@@ -583,2 +599,16 @@ { | ||
}, | ||
// key name transformation | ||
{ | ||
options: [ {names: ['dry-run', 'n'], type: 'bool'} ], | ||
argv: 'node foo.js --dry-run', | ||
/* JSSTYLED */ | ||
expect: { dry_run: true, _args: [] } | ||
}, | ||
{ | ||
options: [ {name: 'foo-bar-', type: 'bool'} ], | ||
argv: 'node foo.js --foo-bar-', | ||
/* JSSTYLED */ | ||
expect: { foo_bar_: true, _args: [] } | ||
}, | ||
]; | ||
@@ -585,0 +615,0 @@ cases.forEach(function (c, i) { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
100290
1263
315