Comparing version 1.0.2 to 1.1.0
# node-dashdash changelog | ||
## 1.1.0 | ||
- Environment variable integration. Envvars can be associated with an option, | ||
then option processing will fallback to using that envvar if defined and | ||
if the option isn't specified in argv. See the "Environment variable | ||
integration" section in the README. | ||
- Change the `<parser>.parse()` signature to take a single object with keys | ||
for arguments. The old signature is still supported. | ||
- `dashdash.createParser(CONFIG)` alternative to `new dashdash.Parser(CONFIG)` | ||
a la many node-land APIs. | ||
## 1.0.2 | ||
@@ -22,2 +36,1 @@ | ||
First release. | ||
@@ -88,3 +88,2 @@ /** | ||
if (isNaN(num)) { | ||
optstr = (optstr.length > 1 ? '--'+optstr : '-'+optstr); | ||
throw new Error(format('arg for "%s" is not a number: "%s"', | ||
@@ -100,3 +99,2 @@ optstr, arg)); | ||
if (!/^[0-9-]+$/.test(arg) || isNaN(num)) { | ||
optstr = (optstr.length > 1 ? '--'+optstr : '-'+optstr); | ||
throw new Error(format('arg for "%s" is not an integer: "%s"', | ||
@@ -112,3 +110,2 @@ optstr, arg)); | ||
if (!/^[0-9]+$/.test(arg) || isNaN(num)) { | ||
optstr = (optstr.length > 1 ? '--'+optstr : '-'+optstr); | ||
throw new Error(format('arg for "%s" is not a positive integer: "%s"', | ||
@@ -180,2 +177,16 @@ optstr, arg)); | ||
/** | ||
* Parser constructor. | ||
* | ||
* @param config {Object} The parser configuration | ||
* - options {Array} Array of option specs. See the README for how to | ||
* specify each option spec. | ||
* - interspersed {Boolean} Default true. Whether to allow interspersed | ||
* arguments (non-options) and options. E.g.: | ||
* node tool.js arg1 arg2 -v | ||
* '-v' is after some args here. If `interspersed: false` then '-v' | ||
* would not be parsed out. Note that regardless of `interspersed` | ||
* the presence of '--' will stop option parsing, as all good | ||
* option parsers should. | ||
*/ | ||
function Parser(config) { | ||
@@ -193,2 +204,3 @@ assert.object(config, 'config'); | ||
this.optionFromName = {}; | ||
this.optionFromEnv = {}; | ||
for (var i = 0; i < this.options.length; i++) { | ||
@@ -205,2 +217,8 @@ var o = this.options[i]; | ||
assert.optionalString(o.help, format('config.options.%d.help', i)); | ||
var env = o.env || []; | ||
if (typeof (env) === 'string') { | ||
env = [env]; | ||
} | ||
assert.optionalArrayOfString(env, format('config.options.%d.env', i)); | ||
if (o.name) { | ||
@@ -213,3 +231,2 @@ o.names = [o.name]; | ||
} | ||
o.names.forEach(function (n) { | ||
@@ -223,2 +240,10 @@ if (self.optionFromName[n]) { | ||
}); | ||
env.forEach(function (n) { | ||
if (self.optionFromEnv[n]) { | ||
throw new Error(format( | ||
'option env collision: "%s" used in %j and %j', | ||
n, self.optionFromEnv[n], o)); | ||
} | ||
self.optionFromEnv[n] = o; | ||
}); | ||
} | ||
@@ -234,6 +259,9 @@ } | ||
* | ||
* @param argv {Array} Optional. The argv to process. Defaults to | ||
* `process.argv`. | ||
* @param slice {Number} The index into argv at which options/args begin. | ||
* Default is 2, as appropriate for `process.argv`. | ||
* @param inputs {Object} | ||
* - argv {Array} Optional. The argv to parse. Defaults to | ||
* `process.argv`. | ||
* - slice {Number} The index into argv at which options/args begin. | ||
* Default is 2, as appropriate for `process.argv`. | ||
* - env {Object} Optional. The env to use for 'env' entries in the | ||
* option specs. Defaults to `process.env`. | ||
* @returns {Object} Parsed `opts`. It has special keys `_args` (the | ||
@@ -243,8 +271,17 @@ * remaining args from `argv`) and `_order` (gives the order that | ||
*/ | ||
Parser.prototype.parse = function parse(argv, slice) { | ||
assert.optionalArrayOfString(argv, 'argv'); | ||
assert.optionalNumber(slice, 'slice'); | ||
var argv = argv || process.argv; | ||
var slice = slice || 2; | ||
Parser.prototype.parse = function parse(inputs) { | ||
var self = this; | ||
// Old API was `parse([argv, [slice]])` | ||
if (Array.isArray(arguments[0])) { | ||
inputs = {argv: arguments[0], slice: arguments[1]}; | ||
} | ||
assert.object(inputs, 'inputs'); | ||
assert.optionalArrayOfString(inputs.argv, 'inputs.argv'); | ||
//assert.optionalNumber(slice, 'slice'); | ||
var argv = inputs.argv || process.argv; | ||
var slice = inputs.slice !== undefined ? inputs.slice : 2; | ||
var args = argv.slice(slice); | ||
var env = inputs.env || process.env; | ||
@@ -260,3 +297,3 @@ // Setup default values | ||
function addOpt(option, optstr, name, val) { | ||
function addOpt(option, optstr, name, val, from) { | ||
var type = types[option.type]; | ||
@@ -272,4 +309,3 @@ var parsedVal = type.parseArg(option, optstr, val); | ||
} | ||
var item = {}; | ||
item[name] = parsedVal; | ||
var item = { name: name, value: parsedVal, from: from }; | ||
_order.push(item); | ||
@@ -308,5 +344,5 @@ } | ||
if (!takesArg) { | ||
addOpt(option, name, option.name, true); | ||
addOpt(option, '--'+name, option.name, true, 'argv'); | ||
} else if (val !== null) { | ||
addOpt(option, name, option.name, val); | ||
addOpt(option, '--'+name, option.name, val, 'argv'); | ||
} else if (i + 1 >= args.length) { | ||
@@ -316,3 +352,3 @@ throw new Error(format('do not have enough args for "--%s" ' | ||
} else { | ||
addOpt(option, name, option.name, args[i + 1]); | ||
addOpt(option, '--'+name, option.name, args[i + 1], 'argv'); | ||
i++; | ||
@@ -340,5 +376,5 @@ } | ||
if (!takesArg) { | ||
addOpt(option, name, option.name, true); | ||
addOpt(option, '-'+name, option.name, true, 'argv'); | ||
} else if (val) { | ||
addOpt(option, name, option.name, val); | ||
addOpt(option, '-'+name, option.name, val, 'argv'); | ||
break; | ||
@@ -350,3 +386,3 @@ } else { | ||
} | ||
addOpt(option, name, option.name, args[i + 1]); | ||
addOpt(option, '-'+name, option.name, args[i + 1], 'argv'); | ||
i++; | ||
@@ -370,2 +406,21 @@ break; | ||
// Parse environment. | ||
Object.keys(this.optionFromEnv).forEach(function (envname) { | ||
var val = env[envname]; | ||
if (val === undefined) | ||
return; | ||
var option = self.optionFromEnv[envname]; | ||
var name = option.name; | ||
if (opts[name] !== undefined) | ||
return; | ||
var takesArg = self.optionTakesArg(option); | ||
if (takesArg) { | ||
addOpt(option, envname, option.name, 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'); | ||
} | ||
}); | ||
opts._order = _order; | ||
@@ -385,3 +440,3 @@ opts._args = _args; | ||
* | ||
* @param options {Object} Options for controlling the option help output. | ||
* @param config {Object} Config for controlling the option help output. | ||
* - indent {Number|String} Default 4. An indent/prefix to use for | ||
@@ -399,29 +454,31 @@ * each option line. | ||
* - maxHelpCol {Number} Default 40. | ||
* - includeEnv {Boolean} Default false. | ||
* @returns {String} | ||
*/ | ||
Parser.prototype.help = function help(options) { | ||
options = options || {}; | ||
assert.object(options, 'options'); | ||
Parser.prototype.help = function help(config) { | ||
config = config || {}; | ||
assert.object(config, 'config'); | ||
var indent; | ||
if (options.indent === undefined) { | ||
if (config.indent === undefined) { | ||
indent = space(4); | ||
} else if (typeof (options.indent) === 'number') { | ||
indent = space(options.indent); | ||
} else if (typeof (options.indent) === 'string') { | ||
indent = options.indent; | ||
} else if (typeof (config.indent) === 'number') { | ||
indent = space(config.indent); | ||
} else if (typeof (config.indent) === 'string') { | ||
indent = config.indent; | ||
} else { | ||
assert.fail('invalid "options.indent": not a string or number: ' | ||
+ options.indent); | ||
assert.fail('invalid "config.indent": not a string or number: ' | ||
+ config.indent); | ||
} | ||
assert.optionalString(options.nameSort, 'options.nameSort'); | ||
var nameSort = options.nameSort || 'length'; | ||
assert.optionalString(config.nameSort, 'config.nameSort'); | ||
var nameSort = config.nameSort || 'length'; | ||
assert.ok(~['length', 'none'].indexOf(nameSort), | ||
'invalid "options.nameSort"'); | ||
assert.optionalNumber(options.maxCol, 'options.maxCol'); | ||
assert.optionalNumber(options.maxHelpCol, 'options.maxHelpCol'); | ||
assert.optionalNumber(options.minHelpCol, 'options.minHelpCol'); | ||
assert.optionalNumber(options.helpCol, 'options.helpCol'); | ||
var maxCol = options.maxCol || 80; | ||
var minHelpCol = options.minHelpCol || 20; | ||
var maxHelpCol = options.maxHelpCol || 40; | ||
'invalid "config.nameSort"'); | ||
assert.optionalNumber(config.maxCol, 'config.maxCol'); | ||
assert.optionalNumber(config.maxHelpCol, 'config.maxHelpCol'); | ||
assert.optionalNumber(config.minHelpCol, 'config.minHelpCol'); | ||
assert.optionalNumber(config.helpCol, 'config.helpCol'); | ||
assert.optionalBool(config.includeEnv, 'config.includeEnv'); | ||
var maxCol = config.maxCol || 80; | ||
var minHelpCol = config.minHelpCol || 20; | ||
var maxHelpCol = config.maxHelpCol || 40; | ||
@@ -463,3 +520,3 @@ var lines = []; | ||
// Add help strings. | ||
var helpCol = options.helpCol; | ||
var helpCol = config.helpCol; | ||
if (!helpCol) { | ||
@@ -480,3 +537,20 @@ helpCol = maxWidth + indent.length + 2; | ||
} | ||
line += textwrap(o.help, maxCol - helpCol).join( | ||
var help = o.help; | ||
if (o.env && o.env.length && config.includeEnv) { | ||
if (help.length && !~'.!?'.indexOf(help.slice(-1))) { | ||
help += '.'; | ||
} | ||
help += ' Environment: '; | ||
var type = types[o.type]; | ||
var arg = o.helpArg || type.helpArg || 'ARG'; | ||
var envs = (Array.isArray(o.env) ? o.env : [o.env]).map(function (e) { | ||
if (type.takesArg) { | ||
return e + '=' + arg; | ||
} else { | ||
return e + '=1'; | ||
} | ||
}); | ||
help += envs.join(', '); | ||
} | ||
line += textwrap(help, maxCol - helpCol).join( | ||
'\n' + space(helpCol)); | ||
@@ -497,16 +571,31 @@ lines[i] = line; | ||
function createParser(config) { | ||
return new Parser(config); | ||
} | ||
/** | ||
* Parse argv with the given options. | ||
* | ||
* @param config {Object} A merge of all the available fields from | ||
* `dashdash.Parser` and `dashdash.Parser.parse`: options, interspersed, | ||
* argv, env, slice. | ||
*/ | ||
function parse(config) { | ||
assert.object(config, 'config'); | ||
assert.optionalArrayOfString(config.argv, 'config.argv'); | ||
assert.optionalObject(config.env, 'config.env'); | ||
var config = shallowCopy(config); | ||
var argv = config.argv || process.ARGV; | ||
var argv = config.argv; | ||
delete config.argv; | ||
var env = config.env; | ||
delete config.env; | ||
var parser = new Parser(config); | ||
return parser.parse(argv); | ||
return parser.parse({argv: argv, env: env}); | ||
} | ||
module.exports = { | ||
createParser: createParser, | ||
Parser: Parser, | ||
parse: parse | ||
}; |
# This is the MIT license | ||
Copyright (c) 2013 Trent Mick | ||
Copyright (c) 2013 Joyent Inc. | ||
Copyright (c) 2013 Trent Mick. All rights reserved. | ||
Copyright (c) 2013 Joyent Inc. All rights reserved. | ||
@@ -6,0 +6,0 @@ Permission is hereby granted, free of charge, to any person obtaining a |
{ | ||
"name": "dashdash", | ||
"description": "Yet another node.js option parsing library", | ||
"version": "1.0.2", | ||
"description": "A light, featureful and explicit option parsing library.", | ||
"version": "1.1.0", | ||
"author": "Trent Mick (trentm.com)", | ||
@@ -6,0 +6,0 @@ "repository": { |
111
README.md
@@ -1,3 +0,4 @@ | ||
Yet another node.js option parsing library. | ||
[Why? See below](#why). tl;dr: The others I've tried are one of | ||
A light, featureful and explicit option parsing library for node.js. | ||
[Why another one? See below](#why). tl;dr: The others I've tried are one of | ||
too loosey goosey (not explicit), too big/too many deps, or ill specified. | ||
@@ -9,3 +10,7 @@ YMMV. | ||
# Install | ||
npm install dashdash | ||
# Usage | ||
@@ -37,4 +42,4 @@ | ||
A more realistic starter script is as follows. This also shows using | ||
`parser.help()` for formatted option help. | ||
A more realistic [starter script "foo.js"](./examples/foo.js) is as follows. | ||
This also shows using `parser.help()` for formatted option help. | ||
@@ -67,3 +72,3 @@ var dashdash = require('./lib/dashdash'); | ||
var parser = new dashdash.Parser({options: options}); | ||
var parser = dashdash.createParser({options: options}); | ||
try { | ||
@@ -81,5 +86,6 @@ var opts = parser.parse(process.argv); | ||
if (opts.help) { | ||
var help = parser.help({includeEnv: true}).trimRight(); | ||
console.log('usage: node foo.js [OPTIONS]\n' | ||
+ 'options:\n' | ||
+ parser.help().trimRight()); | ||
+ help); | ||
process.exit(0); | ||
@@ -94,3 +100,5 @@ } | ||
$ node foo.js -h | ||
# opts: { help: true, _order: [ { help: true } ], _args: [] } | ||
# opts: { help: true, | ||
_order: [ { name: 'help', value: true, from: 'argv' } ], | ||
_args: [] } | ||
# args: [] | ||
@@ -105,3 +113,5 @@ usage: node foo.js [OPTIONS] | ||
$ node foo.js -v | ||
# opts: { verbose: [ true ], _order: [ { verbose: true } ], _args: [] } | ||
# opts: { verbose: [ true ], | ||
_order: [ { name: 'verbose', value: true, from: 'argv' } ], | ||
_args: [] } | ||
# args: [] | ||
@@ -111,3 +121,3 @@ | ||
# opts: { version: true, | ||
_order: [ { version: true } ], | ||
_order: [ { name: 'version', value: true, from: 'argv' } ], | ||
_args: [ 'arg1' ] } | ||
@@ -117,3 +127,5 @@ # args: [ 'arg1' ] | ||
$ node foo.js -f bar.txt | ||
# opts: { file: 'bar.txt', _order: [ { file: 'bar.txt' } ], _args: [] } | ||
# opts: { file: 'bar.txt', | ||
_order: [ { name: 'file', value: 'bar.txt', from: 'argv' } ], | ||
_args: [] } | ||
# args: [] | ||
@@ -125,6 +137,6 @@ | ||
_order: | ||
[ { verbose: true }, | ||
{ verbose: true }, | ||
{ verbose: true }, | ||
{ file: 'blah' } ], | ||
[ { 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: [] } | ||
@@ -134,20 +146,58 @@ # args: [] | ||
# Environment variable integration | ||
If you want to allow environment variables to specify options to your tool, | ||
dashdash makes this easy. We can change the 'verbose' option in the example | ||
above to include an 'env' field: | ||
{ | ||
names: ['verbose', 'v'], | ||
type: 'arrayOfBool', | ||
env: 'FOO_VERBOSE', // <--- add this line | ||
help: 'Verbose output. Use multiple times for more verbose.' | ||
}, | ||
then the **"FOO_VERBOSE" environment variable** can be used to set this | ||
option: | ||
$ FOO_VERBOSE=1 node foo.js | ||
# opts: { verbose: [ true ], | ||
_order: [ { name: 'verbose', value: true, from: 'env' } ], | ||
_args: [] } | ||
# args: [] | ||
With the `includeEnv: true` config to `parser.help()` the environment | ||
variable can also be included in **help output**: | ||
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. | ||
Environment: FOO_VERBOSE=1 | ||
-f FILE, --file=FILE File to process | ||
# Parser config | ||
The `dashdash.Parser` supports some configuration parameters on: | ||
`dashdash.createParser` (a.k.a. `new dashdash.Parser`) supports the following | ||
configuration arguments: | ||
new dashdash.Parser({options: options, ...}); | ||
dashdash.createParser({options: options, [...]}); | ||
These are: | ||
- `interspersed` (Boolean). If true this allows interspersed arguments and | ||
options. I.e.: | ||
- `options` (Array of option specs). Required. See the | ||
[Option specs](#option-specs) section below. | ||
- `interspersed` (Boolean). Option. Default is true. If true this allows | ||
interspersed arguments and options. I.e.: | ||
node ./tool.js -v arg1 arg2 -h # '-h' is after interspersed args | ||
This is true by default. Set it to false to have '-h' **not** get parsed | ||
as an option in the above example. | ||
Set it to false to have '-h' **not** get parsed as an option in the above | ||
example. | ||
# Option config | ||
# Option specs | ||
@@ -176,2 +226,15 @@ Each option spec in the `options` array must/can have the following fields: | ||
- `env` (String or Array of String). Optional. An environment variable name | ||
(or names) that can be used as a fallback for this option. For example, | ||
given a "foo.js" like this: | ||
var options = [{names: ['dry-run', 'n'], env: 'FOO_DRY_RUN'}]; | ||
var opts = dashdash.parse({options: options}); | ||
Both `node foo.js --dry-run` and `FOO_DRY_RUN=1 node foo.js` would result | ||
in `opts.dry_run = true`. | ||
An environment variable is only used as a fallback, i.e. it is ignored if | ||
the associated option is given in `argv`. | ||
- `help` (String). Optional. Used for `parser.help()` output. | ||
@@ -203,2 +266,5 @@ | ||
spaces) or a string for the literal indent. | ||
- `nameSort` (String). Default is 'length'. By default the names are | ||
sorted to put the short opts first (i.e. '-h, --help' preferred | ||
to '--help, -h'). Set to 'none' to not do this sorting. | ||
- `maxCol` (Number). Default 80. Note that reflow is just done on whitespace | ||
@@ -210,2 +276,5 @@ so a long token in the option help can overflow maxCol. | ||
- `maxHelpCol` (Number). Default 40. | ||
- `includeEnv` (Boolean). Default false. If the option has associated | ||
environment variables (via the `env` option spec attribute), then | ||
append mentioned of those envvars to the help string. | ||
@@ -212,0 +281,0 @@ |
@@ -26,2 +26,7 @@ /* | ||
// ---- globals | ||
var TEST_FILTER = process.env.TEST_FILTER; | ||
// ---- tests | ||
@@ -34,2 +39,3 @@ | ||
test('exports', function (t) { | ||
t.ok(dashdash.createParser, 'dashdash.createParser'); | ||
t.ok(dashdash.parse, 'dashdash.parse'); | ||
@@ -40,2 +46,49 @@ t.ok(dashdash.Parser, 'dashdash.Parser'); | ||
test('createParser', function (t) { | ||
var options = [{name: 'help', type: 'bool'}]; | ||
var parser = dashdash.createParser({options: options}); | ||
t.ok(parser); | ||
t.end(); | ||
}); | ||
test('Parser', function (t) { | ||
var options = [{name: 'help', type: 'bool'}]; | ||
var parser = new dashdash.Parser({options: options}); | ||
t.ok(parser); | ||
t.end(); | ||
}); | ||
test('parse', function (t) { | ||
var options = [{name: 'help', type: 'bool'}]; | ||
var argv = 'node tool.js --help'.split(/\s+/g); | ||
var opts = dashdash.parse({options: options, argv: argv}); | ||
t.ok(opts); | ||
t.end(); | ||
}); | ||
test('old Parser.parse() API', function (t) { | ||
var options = [{name: 'v', type: 'bool'}]; | ||
var parser = new dashdash.Parser({options: options}); | ||
var opts = parser.parse('node tool.js -v'.split(/\s+/g)); | ||
t.ok(opts.v); | ||
opts = parser.parse('-v'.split(/\s+/g), 0); | ||
t.ok(opts.v); | ||
t.end(); | ||
}); | ||
test('slice', function (t) { | ||
var options = [{name: 'v', type: 'bool'}]; | ||
var parser = new dashdash.Parser({options: options}); | ||
var opts = parser.parse({argv: 'node tool.js -v'.split(/\s+/g)}); | ||
t.ok(opts.v); | ||
t.equal(opts._args.length, 0); | ||
var opts = parser.parse({argv: '-v'.split(/\s+/g), slice: 0}); | ||
t.ok(opts.v); | ||
t.equal(opts._args.length, 0); | ||
t.end(); | ||
}); | ||
var cases = [ | ||
@@ -209,3 +262,3 @@ // no opts | ||
all: true, | ||
_order: [ {l: true}, {all: true} ], | ||
_order: [ {from: 'argv', l: true}, {from: 'argv', all: true} ], | ||
_args: ['dir'] | ||
@@ -221,3 +274,3 @@ } | ||
all: true, | ||
_order: [ {l: true}, {all: true} ], | ||
_order: [ {from: 'argv', l: true}, {from: 'argv', all: true} ], | ||
_args: ['dir'] | ||
@@ -233,3 +286,3 @@ } | ||
l: true, | ||
_order: [ {l: true} ], | ||
_order: [ {from: 'argv', l: true} ], | ||
_args: ['dir', '-a'] | ||
@@ -430,2 +483,101 @@ } | ||
// env | ||
{ | ||
options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'bool'} ], | ||
argv: 'node foo.js -v', | ||
/* JSSTYLED */ | ||
expect: { v: true, _args: [], _order: [{from: 'argv', v: true}] } | ||
}, | ||
{ | ||
options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'bool'} ], | ||
argv: 'node foo.js -v', | ||
env: {FOO_VERBOSE: '1'}, | ||
/* JSSTYLED */ | ||
expect: { v: true, _args: [], _order: [{from: 'argv', v: true}] } | ||
}, | ||
{ | ||
options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'bool'} ], | ||
argv: 'node foo.js', | ||
env: {FOO_VERBOSE: '1'}, | ||
/* JSSTYLED */ | ||
expect: { v: true, _args: [], _order: [{from: 'env', v: true}] } | ||
}, | ||
{ | ||
options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'bool'} ], | ||
argv: 'node foo.js', | ||
// No '0' or 'false' interp, just empty string or not. | ||
// TODO: still debatable behaviour | ||
env: {FOO_VERBOSE: '0'}, | ||
/* JSSTYLED */ | ||
expect: { v: true, _args: [], _order: [{from: 'env', v: true}] } | ||
}, | ||
{ | ||
options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'bool'} ], | ||
argv: 'node foo.js', | ||
env: {FOO_VERBOSE: ''}, | ||
/* JSSTYLED */ | ||
expect: { _args: [] } | ||
}, | ||
// env (number) | ||
{ | ||
options: [ {names: ['timeout', 't'], env: 'FOO_TIMEOUT', type: 'number'} ], | ||
argv: 'node foo.js -t 42', | ||
env: {}, | ||
/* JSSTYLED */ | ||
expect: { timeout: 42, _args: [] } | ||
}, | ||
{ | ||
options: [ {names: ['timeout', 't'], env: 'FOO_TIMEOUT', type: 'number'} ], | ||
argv: 'node foo.js', | ||
env: {FOO_TIMEOUT: '32'}, | ||
/* JSSTYLED */ | ||
expect: { timeout: 32, _args: [] } | ||
}, | ||
{ | ||
options: [ {names: ['timeout', 't'], env: 'FOO_TIMEOUT', type: 'number'} ], | ||
argv: 'node foo.js -t 52', | ||
env: {FOO_TIMEOUT: '32'}, | ||
/* JSSTYLED */ | ||
expect: { timeout: 52, _args: [] } | ||
}, | ||
// Test that a validation fail in env throws, but NOT if a valid | ||
// value is given in CLI opts (i.e. when env is ignored). | ||
{ | ||
options: [ {names: ['timeout', 't'], env: 'FOO_TIMEOUT', type: 'number'} ], | ||
argv: 'node foo.js -t 52', | ||
env: {FOO_TIMEOUT: 'wallawalla'}, | ||
/* JSSTYLED */ | ||
expect: { timeout: 52, _args: [] } | ||
}, | ||
{ | ||
options: [ {names: ['timeout', 't'], env: 'FOO_TIMEOUT', type: 'number'} ], | ||
argv: 'node foo.js', | ||
env: {FOO_TIMEOUT: 'wallawalla'}, | ||
expect: /arg for "FOO_TIMEOUT" is not a number: "wallawalla"/ | ||
}, | ||
// env (arrayOfBool) | ||
{ | ||
options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'arrayOfBool'} ], | ||
argv: 'node foo.js', | ||
env: {FOO_VERBOSE: 'blah'}, | ||
/* JSSTYLED */ | ||
expect: { v: [true], _args: [] } | ||
}, | ||
{ | ||
options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'arrayOfBool'} ], | ||
argv: 'node foo.js -v', | ||
env: {FOO_VERBOSE: 'blah'}, | ||
/* JSSTYLED */ | ||
expect: { v: [true], _args: [] } | ||
}, | ||
{ | ||
options: [ {name: 'v', env: 'FOO_VERBOSE', type: 'arrayOfBool'} ], | ||
argv: 'node foo.js -vv', | ||
env: {FOO_VERBOSE: 'blah'}, | ||
/* JSSTYLED */ | ||
expect: { v: [true, true], _args: [] } | ||
}, | ||
]; | ||
@@ -445,3 +597,15 @@ cases.forEach(function (c, i) { | ||
} | ||
test(format('case %d: %s', i, argv.join(' ')), function (t) { | ||
var env = c.env; | ||
delete c.env; | ||
var envStr = ''; | ||
if (env) { | ||
Object.keys(env).forEach(function (e) { | ||
envStr += format('%s=%s ', e, env[e]); | ||
}); | ||
} | ||
var testName = format('case %d: %s%s', i, envStr, argv.join(' ')); | ||
if (TEST_FILTER && !~testName.indexOf(TEST_FILTER)) { | ||
return; | ||
} | ||
test(testName, function (t) { | ||
debug('--', i) | ||
@@ -454,3 +618,3 @@ debug('c: %j', c) | ||
try { | ||
opts = parser.parse(argv); | ||
opts = parser.parse({argv: argv, env: env}); | ||
} catch (e) { | ||
@@ -464,3 +628,3 @@ error = e; | ||
} else if (expect) { | ||
opts = parser.parse(argv); | ||
opts = parser.parse({argv: argv, env: env}); | ||
if (!expect._order) { | ||
@@ -467,0 +631,0 @@ delete opts._order; // don't test it, if not in case data |
39
TODO.txt
@@ -0,1 +1,2 @@ | ||
- --dry-run -> opts.dry_run | ||
@@ -5,2 +6,40 @@ # someday/maybe | ||
- being able to add types: i.e. a validator (easy to do, just haven't exposed) | ||
- Maybe this later: var opts = parser.parse({argv: process.argv}); | ||
# notes: supporting opts from env or from a file | ||
Say I have a 'foo' tool with a '-v' option for verbose. I also want | ||
FOO_VERBOSE envvar to set verbose: | ||
$ foo -v | ||
debug: blah blah | ||
... | ||
$ FOO_VERBOSE=1 foo | ||
debug: blah blah | ||
... | ||
foo.js: | ||
var dashdash = require('dashdash') | ||
var options = [{name: 'v', env: 'FOO_VERBOSE', type: 'bool'}]; | ||
var parser = new dashdash.Parser({options: options}); | ||
var opts = parser.parse(process.argv); | ||
Say, also a ~/.foorc file is supported (somewhat a la ~/.ackrc) where | ||
the file holds extra CLI opts: | ||
$ cat ~/.foorc | ||
-v -i | ||
--file=foo.txt | ||
Parsing that would look like: | ||
var options = [ | ||
{name: 'v', env: 'FOO_VERBOSE', type: 'bool'}, | ||
{name: 'i', type: 'bool'}, | ||
{name: 'file', env: 'FOO_FILE', type: 'string'} | ||
]; | ||
var parser = new dashdash.Parser({options: options}); | ||
var opts = parser.parse(process.argv); |
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
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances 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
98977
13
1223
291
2