pax_global_header 0000666 0000000 0000000 00000000064 13165347466 0014531 g ustar 00root root 0000000 0000000 52 comment=c7eee910d73ad24970f3addbf884cfa47092b3f8
yargs-parser-8.0.0/ 0000775 0000000 0000000 00000000000 13165347466 0014155 5 ustar 00root root 0000000 0000000 yargs-parser-8.0.0/.gitignore 0000664 0000000 0000000 00000000100 13165347466 0016134 0 ustar 00root root 0000000 0000000 .nyc_output
node_modules
.DS_Store
./test/fixtures/package.json
yargs-parser-8.0.0/.travis.yml 0000664 0000000 0000000 00000000275 13165347466 0016272 0 ustar 00root root 0000000 0000000 language: node_js
os:
- linux
node_js:
- "4"
- "6"
- "node"
after_script: npm run coverage
deploy:
provider: npm
email: ben@npmjs.com
api_key: $NPM_TOKEN
on:
tags: true
yargs-parser-8.0.0/CHANGELOG.md 0000664 0000000 0000000 00000022066 13165347466 0015774 0 ustar 00root root 0000000 0000000 # Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
# [8.0.0](https://github.com/yargs/yargs-parser/compare/v7.0.0...v8.0.0) (2017-10-05)
### Bug Fixes
* Ignore multiple spaces between arguments. ([#100](https://github.com/yargs/yargs-parser/issues/100)) ([d137227](https://github.com/yargs/yargs-parser/commit/d137227))
### Features
* allow configuration of prefix for boolean negation ([#94](https://github.com/yargs/yargs-parser/issues/94)) ([00bde7d](https://github.com/yargs/yargs-parser/commit/00bde7d))
* reworking how numbers are parsed ([#104](https://github.com/yargs/yargs-parser/issues/104)) ([fba00eb](https://github.com/yargs/yargs-parser/commit/fba00eb))
### BREAKING CHANGES
* strings that fail `Number.isSafeInteger()` are no longer coerced into numbers.
# [7.0.0](https://github.com/yargs/yargs-parser/compare/v6.0.1...v7.0.0) (2017-05-02)
### Chores
* revert populate-- logic ([#91](https://github.com/yargs/yargs-parser/issues/91)) ([6003e6d](https://github.com/yargs/yargs-parser/commit/6003e6d))
### BREAKING CHANGES
* populate-- now defaults to false.
## [6.0.1](https://github.com/yargs/yargs-parser/compare/v6.0.0...v6.0.1) (2017-05-01)
### Bug Fixes
* default '--' to undefined when not provided; this is closer to the array API ([#90](https://github.com/yargs/yargs-parser/issues/90)) ([4e739cc](https://github.com/yargs/yargs-parser/commit/4e739cc))
# [6.0.0](https://github.com/yargs/yargs-parser/compare/v4.2.1...v6.0.0) (2017-05-01)
### Bug Fixes
* environment variables should take precedence over config file ([#81](https://github.com/yargs/yargs-parser/issues/81)) ([76cee1f](https://github.com/yargs/yargs-parser/commit/76cee1f))
* parsing hints should apply for dot notation keys ([#86](https://github.com/yargs/yargs-parser/issues/86)) ([3e47d62](https://github.com/yargs/yargs-parser/commit/3e47d62))
### Chores
* upgrade to newest version of camelcase ([#87](https://github.com/yargs/yargs-parser/issues/87)) ([f1903aa](https://github.com/yargs/yargs-parser/commit/f1903aa))
### Features
* add -- option which allows arguments after the -- flag to be returned separated from positional arguments ([#84](https://github.com/yargs/yargs-parser/issues/84)) ([2572ca8](https://github.com/yargs/yargs-parser/commit/2572ca8))
* when parsing stops, we now populate "--" by default ([#88](https://github.com/yargs/yargs-parser/issues/88)) ([cd666db](https://github.com/yargs/yargs-parser/commit/cd666db))
### BREAKING CHANGES
* rather than placing arguments in "_", when parsing is stopped via "--"; we now populate an array called "--" by default.
* camelcase now requires Node 4+.
* environment variables will now override config files (args, env, config-file, config-object)
# [5.0.0](https://github.com/yargs/yargs-parser/compare/v4.2.1...v5.0.0) (2017-02-18)
### Bug Fixes
* environment variables should take precedence over config file ([#81](https://github.com/yargs/yargs-parser/issues/81)) ([76cee1f](https://github.com/yargs/yargs-parser/commit/76cee1f))
### BREAKING CHANGES
* environment variables will now override config files (args, env, config-file, config-object)
## [4.2.1](https://github.com/yargs/yargs-parser/compare/v4.2.0...v4.2.1) (2017-01-02)
### Bug Fixes
* flatten/duplicate regression ([#75](https://github.com/yargs/yargs-parser/issues/75)) ([68d68a0](https://github.com/yargs/yargs-parser/commit/68d68a0))
# [4.2.0](https://github.com/yargs/yargs-parser/compare/v4.1.0...v4.2.0) (2016-12-01)
### Bug Fixes
* inner objects in configs had their keys appended to top-level key when dot-notation was disabled ([#72](https://github.com/yargs/yargs-parser/issues/72)) ([0b1b5f9](https://github.com/yargs/yargs-parser/commit/0b1b5f9))
### Features
* allow multiple arrays to be provided, rather than always combining ([#71](https://github.com/yargs/yargs-parser/issues/71)) ([0f0fb2d](https://github.com/yargs/yargs-parser/commit/0f0fb2d))
# [4.1.0](https://github.com/yargs/yargs-parser/compare/v4.0.2...v4.1.0) (2016-11-07)
### Features
* apply coercions to default options ([#65](https://github.com/yargs/yargs-parser/issues/65)) ([c79052b](https://github.com/yargs/yargs-parser/commit/c79052b))
* handle dot notation boolean options ([#63](https://github.com/yargs/yargs-parser/issues/63)) ([02c3545](https://github.com/yargs/yargs-parser/commit/02c3545))
## [4.0.2](https://github.com/yargs/yargs-parser/compare/v4.0.1...v4.0.2) (2016-09-30)
### Bug Fixes
* whoops, let's make the assign not change the Object key order ([29d069a](https://github.com/yargs/yargs-parser/commit/29d069a))
## [4.0.1](https://github.com/yargs/yargs-parser/compare/v4.0.0...v4.0.1) (2016-09-30)
### Bug Fixes
* lodash.assign was deprecated ([#59](https://github.com/yargs/yargs-parser/issues/59)) ([5e7eb11](https://github.com/yargs/yargs-parser/commit/5e7eb11))
# [4.0.0](https://github.com/yargs/yargs-parser/compare/v3.2.0...v4.0.0) (2016-09-26)
### Bug Fixes
* coerce should be applied to the final objects and arrays created ([#57](https://github.com/yargs/yargs-parser/issues/57)) ([4ca69da](https://github.com/yargs/yargs-parser/commit/4ca69da))
### BREAKING CHANGES
* coerce is no longer applied to individual arguments in an implicit array.
# [3.2.0](https://github.com/yargs/yargs-parser/compare/v3.1.0...v3.2.0) (2016-08-13)
### Features
* coerce full array instead of each element ([#51](https://github.com/yargs/yargs-parser/issues/51)) ([cc4dc56](https://github.com/yargs/yargs-parser/commit/cc4dc56))
# [3.1.0](https://github.com/yargs/yargs-parser/compare/v3.0.0...v3.1.0) (2016-08-09)
### Bug Fixes
* address pkgConf parsing bug outlined in [#37](https://github.com/yargs/yargs-parser/issues/37) ([#45](https://github.com/yargs/yargs-parser/issues/45)) ([be76ee6](https://github.com/yargs/yargs-parser/commit/be76ee6))
* better parsing of negative values ([#44](https://github.com/yargs/yargs-parser/issues/44)) ([2e43692](https://github.com/yargs/yargs-parser/commit/2e43692))
* check aliases when guessing defaults for arguments fixes [#41](https://github.com/yargs/yargs-parser/issues/41) ([#43](https://github.com/yargs/yargs-parser/issues/43)) ([f3e4616](https://github.com/yargs/yargs-parser/commit/f3e4616))
### Features
* added coerce option, for providing specialized argument parsing ([#42](https://github.com/yargs/yargs-parser/issues/42)) ([7b49cd2](https://github.com/yargs/yargs-parser/commit/7b49cd2))
# [3.0.0](https://github.com/yargs/yargs-parser/compare/v2.4.1...v3.0.0) (2016-08-07)
### Bug Fixes
* parsing issue with numeric character in group of options ([#19](https://github.com/yargs/yargs-parser/issues/19)) ([f743236](https://github.com/yargs/yargs-parser/commit/f743236))
* upgraded lodash.assign ([5d7fdf4](https://github.com/yargs/yargs-parser/commit/5d7fdf4))
### BREAKING CHANGES
* subtle change to how values are parsed in a group of single-character arguments.
* _first released in 3.1.0, better handling of negative values should be considered a breaking change._
## [2.4.1](https://github.com/yargs/yargs-parser/compare/v2.4.0...v2.4.1) (2016-07-16)
### Bug Fixes
* **count:** do not increment a default value ([#39](https://github.com/yargs/yargs-parser/issues/39)) ([b04a189](https://github.com/yargs/yargs-parser/commit/b04a189))
# [2.4.0](https://github.com/yargs/yargs-parser/compare/v2.3.0...v2.4.0) (2016-04-11)
### Features
* **environment:** Support nested options in environment variables ([#26](https://github.com/yargs/yargs-parser/issues/26)) thanks [@elas7](https://github.com/elas7) \o/ ([020778b](https://github.com/yargs/yargs-parser/commit/020778b))
# [2.3.0](https://github.com/yargs/yargs-parser/compare/v2.2.0...v2.3.0) (2016-04-09)
### Bug Fixes
* **boolean:** fix for boolean options with non boolean defaults (#20) ([2dbe86b](https://github.com/yargs/yargs-parser/commit/2dbe86b)), closes [(#20](https://github.com/(/issues/20)
* **package:** remove tests from tarball ([0353c0d](https://github.com/yargs/yargs-parser/commit/0353c0d))
* **parsing:** handle calling short option with an empty string as the next value. ([a867165](https://github.com/yargs/yargs-parser/commit/a867165))
* boolean flag when next value contains the strings 'true' or 'false'. ([69941a6](https://github.com/yargs/yargs-parser/commit/69941a6))
* update dependencies; add standard-version bin for next release (#24) ([822d9d5](https://github.com/yargs/yargs-parser/commit/822d9d5))
### Features
* **configuration:** Allow to pass configuration objects to yargs-parser ([0780900](https://github.com/yargs/yargs-parser/commit/0780900))
* **normalize:** allow normalize to work with arrays ([e0eaa1a](https://github.com/yargs/yargs-parser/commit/e0eaa1a))
yargs-parser-8.0.0/LICENSE.txt 0000664 0000000 0000000 00000001333 13165347466 0016000 0 ustar 00root root 0000000 0000000 Copyright (c) 2016, Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice
appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
yargs-parser-8.0.0/README.md 0000664 0000000 0000000 00000016514 13165347466 0015443 0 ustar 00root root 0000000 0000000 # yargs-parser
[](https://travis-ci.org/yargs/yargs-parser)
[](https://coveralls.io/r/yargs/yargs-parser?branch=master)
[](https://www.npmjs.com/package/yargs-parser)
[](https://ci.appveyor.com/project/bcoe/yargs-parser)
[](https://github.com/conventional-changelog/standard-version)
The mighty option parser used by [yargs](https://github.com/yargs/yargs).
visit the [yargs website](http://yargs.js.org/) for more examples, and thorough usage instructions.
## Example
```sh
npm i yargs-parser --save
```
```js
var argv = require('yargs-parser')(process.argv.slice(2))
console.log(argv)
```
```sh
node example.js --foo=33 --bar hello
{ _: [], foo: 33, bar: 'hello' }
```
_or parse a string!_
```js
var argv = require('./')('--foo=99 --bar=33')
console.log(argv)
```
```sh
{ _: [], foo: 99, bar: 33 }
```
Convert an array of mixed types before passing to `yargs-parser`:
```js
var parse = require('yargs-parser')
parse(['-f', 11, '--zoom', 55].join(' ')) // <-- array to string
parse(['-f', 11, '--zoom', 55].map(String)) // <-- array of strings
```
## API
### require('yargs-parser')(args, opts={})
Parses command line arguments returning a simple mapping of keys and values.
**expects:**
* `args`: a string or array of strings representing the options to parse.
* `opts`: provide a set of hints indicating how `args` should be parsed:
* `opts.alias`: an object representing the set of aliases for a key: `{alias: {foo: ['f']}}`.
* `opts.array`: indicate that keys should be parsed as an array: `{array: ['foo', 'bar']}`.
* `opts.boolean`: arguments should be parsed as booleans: `{boolean: ['x', 'y']}`.
* `opts.config`: indicate a key that represents a path to a configuration file (this file will be loaded and parsed).
* `opts.coerce`: provide a custom synchronous function that returns a coerced value from the argument provided
(or throws an error), e.g. `{coerce: {foo: function (arg) {return modifiedArg}}}`.
* `opts.count`: indicate a key that should be used as a counter, e.g., `-vvv` = `{v: 3}`.
* `opts.default`: provide default values for keys: `{default: {x: 33, y: 'hello world!'}}`.
* `opts.envPrefix`: environment variables (`process.env`) with the prefix provided should be parsed.
* `opts.narg`: specify that a key requires `n` arguments: `{narg: {x: 2}}`.
* `opts.normalize`: `path.normalize()` will be applied to values set to this key.
* `opts.string`: keys should be treated as strings (even if they resemble a number `-x 33`).
* `opts.configuration`: provide configuration options to the yargs-parser (see: [configuration](#configuration)).
* `opts.number`: keys should be treated as numbers.
* `opts['--']`: arguments after the end-of-options flag `--` will be set to the `argv.['--']` array instead of being set to the `argv._` array.
**returns:**
* `obj`: an object representing the parsed value of `args`
* `key/value`: key value pairs for each argument and their aliases.
* `_`: an array representing the positional arguments.
* [optional] `--`: an array with arguments after the end-of-options flag `--`.
### require('yargs-parser').detailed(args, opts={})
Parses a command line string, returning detailed information required by the
yargs engine.
**expects:**
* `args`: a string or array of strings representing options to parse.
* `opts`: provide a set of hints indicating how `args`, inputs are identical to `require('yargs-parser')(args, opts={})`.
**returns:**
* `argv`: an object representing the parsed value of `args`
* `key/value`: key value pairs for each argument and their aliases.
* `_`: an array representing the positional arguments.
* `error`: populated with an error object if an exception occurred during parsing.
* `aliases`: the inferred list of aliases built by combining lists in `opts.alias`.
* `newAliases`: any new aliases added via camel-case expansion.
* `configuration`: the configuration loaded from the `yargs` stanza in package.json.
### Configuration
The yargs-parser applies several automated transformations on the keys provided
in `args`. These features can be turned on and off using the `configuration` field
of `opts`.
```js
var parsed = parser(['--no-dice'], {
configuration: {
'boolean-negation': false
}
})
```
### short option groups
* default: `true`.
* key: `short-option-groups`.
Should a group of short-options be treated as boolean flags?
```sh
node example.js -abc
{ _: [], a: true, b: true, c: true }
```
_if disabled:_
```sh
node example.js -abc
{ _: [], abc: true }
```
### camel-case expansion
* default: `true`.
* key: `camel-case-expansion`.
Should hyphenated arguments be expanded into camel-case aliases?
```sh
node example.js --foo-bar
{ _: [], 'foo-bar': true, fooBar: true }
```
_if disabled:_
```sh
node example.js --foo-bar
{ _: [], 'foo-bar': true }
```
### dot-notation
* default: `true`
* key: `dot-notation`
Should keys that contain `.` be treated as objects?
```sh
node example.js --foo.bar
{ _: [], foo: { bar: true } }
```
_if disabled:_
```sh
node example.js --foo.bar
{ _: [], "foo.bar": true }
```
### parse numbers
* default: `true`
* key: `parse-numbers`
Should keys that look like numbers be treated as such?
```sh
node example.js --foo=99.3
{ _: [], foo: 99.3 }
```
_if disabled:_
```sh
node example.js --foo=99.3
{ _: [], foo: "99.3" }
```
### boolean negation
* default: `true`
* key: `boolean-negation`
Should variables prefixed with `--no` be treated as negations?
```sh
node example.js --no-foo
{ _: [], foo: false }
```
_if disabled:_
```sh
node example.js --no-foo
{ _: [], "no-foo": true }
```
### duplicate arguments array
* default: `true`
* key: `duplicate-arguments-array`
Should arguments be coerced into an array when duplicated:
```sh
node example.js -x 1 -x 2
{ _: [], x: [1, 2] }
```
_if disabled:_
```sh
node example.js -x 1 -x 2
{ _: [], x: 2 }
```
### flatten duplicate arrays
* default: `true`
* key: `flatten-duplicate-arrays`
Should array arguments be coerced into a single array when duplicated:
```sh
node example.js -x 1 2 -x 3 4
{ _: [], x: [1, 2, 3, 4] }
```
_if disabled:_
```sh
node example.js -x 1 2 -x 3 4
{ _: [], x: [[1, 2], [3, 4]] }
```
### negation prefix
* default: `no-`
* key: `negation-prefix`
The prefix to use for negated boolean variables.
```sh
node example.js --no-foo
{ _: [], foo: false }
```
_if set to `quux`:_
```sh
node example.js --quuxfoo
{ _: [], foo: false }
```
### populate --
* default: `false`.
* key: `populate--`
Should unparsed flags be stored in `--` or `_`.
_If disabled:_
```sh
node example.js a -b -- x y
{ _: [ 'a', 'x', 'y' ], b: true }
```
_If enabled:_
```sh
node example.js a -b -- x y
{ _: [ 'a' ], '--': [ 'x', 'y' ], b: true }
```
## Special Thanks
The yargs project evolves from optimist and minimist. It owes its
existence to a lot of James Halliday's hard work. Thanks [substack](https://github.com/substack) **beep** **boop** \o/
## License
ISC
yargs-parser-8.0.0/appveyor.yml 0000664 0000000 0000000 00000000633 13165347466 0016547 0 ustar 00root root 0000000 0000000 environment:
matrix:
- nodejs_version: '5'
- nodejs_version: '4'
- nodejs_version: '7'
install:
- ps: Install-Product node $env:nodejs_version
- set CI=true
- npm -g install npm@latest
- set PATH=%APPDATA%\npm;%PATH%
- npm install
matrix:
fast_finish: true
build: off
version: '{build}'
shallow_clone: true
clone_depth: 1
test_script:
- node --version
- npm --version
- npm test
yargs-parser-8.0.0/example.js 0000775 0000000 0000000 00000000124 13165347466 0016146 0 ustar 00root root 0000000 0000000 var parser = require('./')
var parse = parser(['-cats', 'meow'])
console.log(parse)
yargs-parser-8.0.0/index.js 0000664 0000000 0000000 00000055035 13165347466 0015632 0 ustar 00root root 0000000 0000000 var camelCase = require('camelcase')
var path = require('path')
var tokenizeArgString = require('./lib/tokenize-arg-string')
var util = require('util')
function parse (args, opts) {
if (!opts) opts = {}
// allow a string argument to be passed in rather
// than an argv array.
args = tokenizeArgString(args)
// aliases might have transitive relationships, normalize this.
var aliases = combineAliases(opts.alias || {})
var configuration = assign({
'short-option-groups': true,
'camel-case-expansion': true,
'dot-notation': true,
'parse-numbers': true,
'boolean-negation': true,
'negation-prefix': 'no-',
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': true,
'populate--': false
}, opts.configuration)
var defaults = opts.default || {}
var configObjects = opts.configObjects || []
var envPrefix = opts.envPrefix
var notFlagsOption = configuration['populate--']
var notFlagsArgv = notFlagsOption ? '--' : '_'
var newAliases = {}
// allow a i18n handler to be passed in, default to a fake one (util.format).
var __ = opts.__ || function (str) {
return util.format.apply(util, Array.prototype.slice.call(arguments))
}
var error = null
var flags = {
aliases: {},
arrays: {},
bools: {},
strings: {},
numbers: {},
counts: {},
normalize: {},
configs: {},
defaulted: {},
nargs: {},
coercions: {}
}
var negative = /^-[0-9]+(\.[0-9]+)?/
var negatedBoolean = new RegExp('^--' + configuration['negation-prefix'] + '(.+)')
;[].concat(opts.array).filter(Boolean).forEach(function (key) {
flags.arrays[key] = true
})
;[].concat(opts.boolean).filter(Boolean).forEach(function (key) {
flags.bools[key] = true
})
;[].concat(opts.string).filter(Boolean).forEach(function (key) {
flags.strings[key] = true
})
;[].concat(opts.number).filter(Boolean).forEach(function (key) {
flags.numbers[key] = true
})
;[].concat(opts.count).filter(Boolean).forEach(function (key) {
flags.counts[key] = true
})
;[].concat(opts.normalize).filter(Boolean).forEach(function (key) {
flags.normalize[key] = true
})
Object.keys(opts.narg || {}).forEach(function (k) {
flags.nargs[k] = opts.narg[k]
})
Object.keys(opts.coerce || {}).forEach(function (k) {
flags.coercions[k] = opts.coerce[k]
})
if (Array.isArray(opts.config) || typeof opts.config === 'string') {
;[].concat(opts.config).filter(Boolean).forEach(function (key) {
flags.configs[key] = true
})
} else {
Object.keys(opts.config || {}).forEach(function (k) {
flags.configs[k] = opts.config[k]
})
}
// create a lookup table that takes into account all
// combinations of aliases: {f: ['foo'], foo: ['f']}
extendAliases(opts.key, aliases, opts.default, flags.arrays)
// apply default values to all aliases.
Object.keys(defaults).forEach(function (key) {
(flags.aliases[key] || []).forEach(function (alias) {
defaults[alias] = defaults[key]
})
})
var argv = { _: [] }
Object.keys(flags.bools).forEach(function (key) {
setArg(key, !(key in defaults) ? false : defaults[key])
setDefaulted(key)
})
var notFlags = []
if (args.indexOf('--') !== -1) {
notFlags = args.slice(args.indexOf('--') + 1)
args = args.slice(0, args.indexOf('--'))
}
for (var i = 0; i < args.length; i++) {
var arg = args[i]
var broken
var key
var letters
var m
var next
var value
// -- seperated by =
if (arg.match(/^--.+=/) || (
!configuration['short-option-groups'] && arg.match(/^-.+=/)
)) {
// Using [\s\S] instead of . because js doesn't support the
// 'dotall' regex modifier. See:
// http://stackoverflow.com/a/1068308/13216
m = arg.match(/^--?([^=]+)=([\s\S]*)$/)
// nargs format = '--f=monkey washing cat'
if (checkAllAliases(m[1], flags.nargs)) {
args.splice(i + 1, 0, m[2])
i = eatNargs(i, m[1], args)
// arrays format = '--f=a b c'
} else if (checkAllAliases(m[1], flags.arrays) && args.length > i + 1) {
args.splice(i + 1, 0, m[2])
i = eatArray(i, m[1], args)
} else {
setArg(m[1], m[2])
}
} else if (arg.match(negatedBoolean) && configuration['boolean-negation']) {
key = arg.match(negatedBoolean)[1]
setArg(key, false)
// -- seperated by space.
} else if (arg.match(/^--.+/) || (
!configuration['short-option-groups'] && arg.match(/^-.+/)
)) {
key = arg.match(/^--?(.+)/)[1]
// nargs format = '--foo a b c'
if (checkAllAliases(key, flags.nargs)) {
i = eatNargs(i, key, args)
// array format = '--foo a b c'
} else if (checkAllAliases(key, flags.arrays) && args.length > i + 1) {
i = eatArray(i, key, args)
} else {
next = args[i + 1]
if (next !== undefined && (!next.match(/^-/) ||
next.match(negative)) &&
!checkAllAliases(key, flags.bools) &&
!checkAllAliases(key, flags.counts)) {
setArg(key, next)
i++
} else if (/^(true|false)$/.test(next)) {
setArg(key, next)
i++
} else {
setArg(key, defaultForType(guessType(key, flags)))
}
}
// dot-notation flag seperated by '='.
} else if (arg.match(/^-.\..+=/)) {
m = arg.match(/^-([^=]+)=([\s\S]*)$/)
setArg(m[1], m[2])
// dot-notation flag seperated by space.
} else if (arg.match(/^-.\..+/)) {
next = args[i + 1]
key = arg.match(/^-(.\..+)/)[1]
if (next !== undefined && !next.match(/^-/) &&
!checkAllAliases(key, flags.bools) &&
!checkAllAliases(key, flags.counts)) {
setArg(key, next)
i++
} else {
setArg(key, defaultForType(guessType(key, flags)))
}
} else if (arg.match(/^-[^-]+/) && !arg.match(negative)) {
letters = arg.slice(1, -1).split('')
broken = false
for (var j = 0; j < letters.length; j++) {
next = arg.slice(j + 2)
if (letters[j + 1] && letters[j + 1] === '=') {
value = arg.slice(j + 3)
key = letters[j]
// nargs format = '-f=monkey washing cat'
if (checkAllAliases(key, flags.nargs)) {
args.splice(i + 1, 0, value)
i = eatNargs(i, key, args)
// array format = '-f=a b c'
} else if (checkAllAliases(key, flags.arrays) && args.length > i + 1) {
args.splice(i + 1, 0, value)
i = eatArray(i, key, args)
} else {
setArg(key, value)
}
broken = true
break
}
if (next === '-') {
setArg(letters[j], next)
continue
}
// current letter is an alphabetic character and next value is a number
if (/[A-Za-z]/.test(letters[j]) &&
/^-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
setArg(letters[j], next)
broken = true
break
}
if (letters[j + 1] && letters[j + 1].match(/\W/)) {
setArg(letters[j], next)
broken = true
break
} else {
setArg(letters[j], defaultForType(guessType(letters[j], flags)))
}
}
key = arg.slice(-1)[0]
if (!broken && key !== '-') {
// nargs format = '-f a b c'
if (checkAllAliases(key, flags.nargs)) {
i = eatNargs(i, key, args)
// array format = '-f a b c'
} else if (checkAllAliases(key, flags.arrays) && args.length > i + 1) {
i = eatArray(i, key, args)
} else {
next = args[i + 1]
if (next !== undefined && (!/^(-|--)[^-]/.test(next) ||
next.match(negative)) &&
!checkAllAliases(key, flags.bools) &&
!checkAllAliases(key, flags.counts)) {
setArg(key, next)
i++
} else if (/^(true|false)$/.test(next)) {
setArg(key, next)
i++
} else {
setArg(key, defaultForType(guessType(key, flags)))
}
}
}
} else {
argv._.push(maybeCoerceNumber('_', arg))
}
}
// order of precedence:
// 1. command line arg
// 2. value from env var
// 3. value from config file
// 4. value from config objects
// 5. configured default value
applyEnvVars(argv, true) // special case: check env vars that point to config file
applyEnvVars(argv, false)
setConfig(argv)
setConfigObjects()
applyDefaultsAndAliases(argv, flags.aliases, defaults)
applyCoercions(argv)
// for any counts either not in args or without an explicit default, set to 0
Object.keys(flags.counts).forEach(function (key) {
if (!hasKey(argv, key.split('.'))) setArg(key, 0)
})
// '--' defaults to undefined.
if (notFlagsOption && notFlags.length) argv[notFlagsArgv] = []
notFlags.forEach(function (key) {
argv[notFlagsArgv].push(key)
})
// how many arguments should we consume, based
// on the nargs option?
function eatNargs (i, key, args) {
var toEat = checkAllAliases(key, flags.nargs)
if (args.length - (i + 1) < toEat) error = Error(__('Not enough arguments following: %s', key))
for (var ii = i + 1; ii < (toEat + i + 1); ii++) {
setArg(key, args[ii])
}
return (i + toEat)
}
// if an option is an array, eat all non-hyphenated arguments
// following it... YUM!
// e.g., --foo apple banana cat becomes ["apple", "banana", "cat"]
function eatArray (i, key, args) {
var start = i + 1
var argsToSet = []
var multipleArrayFlag = i > 0
for (var ii = i + 1; ii < args.length; ii++) {
if (/^-/.test(args[ii]) && !negative.test(args[ii])) {
if (ii === start) {
setArg(key, defaultForType('array'))
}
multipleArrayFlag = true
break
}
i = ii
argsToSet.push(args[ii])
}
if (multipleArrayFlag) {
setArg(key, argsToSet.map(function (arg) {
return processValue(key, arg)
}))
} else {
argsToSet.forEach(function (arg) {
setArg(key, arg)
})
}
return i
}
function setArg (key, val) {
unsetDefaulted(key)
if (/-/.test(key) && configuration['camel-case-expansion']) {
addNewAlias(key, camelCase(key))
}
var value = processValue(key, val)
var splitKey = key.split('.')
setKey(argv, splitKey, value)
// handle populating aliases of the full key
if (flags.aliases[key]) {
flags.aliases[key].forEach(function (x) {
x = x.split('.')
setKey(argv, x, value)
})
}
// handle populating aliases of the first element of the dot-notation key
if (splitKey.length > 1 && configuration['dot-notation']) {
;(flags.aliases[splitKey[0]] || []).forEach(function (x) {
x = x.split('.')
// expand alias with nested objects in key
var a = [].concat(splitKey)
a.shift() // nuke the old key.
x = x.concat(a)
setKey(argv, x, value)
})
}
// Set normalize getter and setter when key is in 'normalize' but isn't an array
if (checkAllAliases(key, flags.normalize) && !checkAllAliases(key, flags.arrays)) {
var keys = [key].concat(flags.aliases[key] || [])
keys.forEach(function (key) {
argv.__defineSetter__(key, function (v) {
val = path.normalize(v)
})
argv.__defineGetter__(key, function () {
return typeof val === 'string' ? path.normalize(val) : val
})
})
}
}
function addNewAlias (key, alias) {
if (!(flags.aliases[key] && flags.aliases[key].length)) {
flags.aliases[key] = [alias]
newAliases[alias] = true
}
if (!(flags.aliases[alias] && flags.aliases[alias].length)) {
addNewAlias(alias, key)
}
}
function processValue (key, val) {
// handle parsing boolean arguments --foo=true --bar false.
if (checkAllAliases(key, flags.bools) || checkAllAliases(key, flags.counts)) {
if (typeof val === 'string') val = val === 'true'
}
var value = maybeCoerceNumber(key, val)
// increment a count given as arg (either no value or value parsed as boolean)
if (checkAllAliases(key, flags.counts) && (isUndefined(value) || typeof value === 'boolean')) {
value = increment
}
// Set normalized value when key is in 'normalize' and in 'arrays'
if (checkAllAliases(key, flags.normalize) && checkAllAliases(key, flags.arrays)) {
if (Array.isArray(val)) value = val.map(path.normalize)
else value = path.normalize(val)
}
return value
}
function maybeCoerceNumber (key, value) {
if (!checkAllAliases(key, flags.strings) && !checkAllAliases(key, flags.coercions)) {
const shouldCoerceNumber = isNumber(value) && configuration['parse-numbers'] && (Number.isSafeInteger(parseInt(value)))
if (shouldCoerceNumber || (!isUndefined(value) && checkAllAliases(key, flags.numbers))) value = Number(value)
}
return value
}
// set args from config.json file, this should be
// applied last so that defaults can be applied.
function setConfig (argv) {
var configLookup = {}
// expand defaults/aliases, in-case any happen to reference
// the config.json file.
applyDefaultsAndAliases(configLookup, flags.aliases, defaults)
Object.keys(flags.configs).forEach(function (configKey) {
var configPath = argv[configKey] || configLookup[configKey]
if (configPath) {
try {
var config = null
var resolvedConfigPath = path.resolve(process.cwd(), configPath)
if (typeof flags.configs[configKey] === 'function') {
try {
config = flags.configs[configKey](resolvedConfigPath)
} catch (e) {
config = e
}
if (config instanceof Error) {
error = config
return
}
} else {
config = require(resolvedConfigPath)
}
setConfigObject(config)
} catch (ex) {
if (argv[configKey]) error = Error(__('Invalid JSON config file: %s', configPath))
}
}
})
}
// set args from config object.
// it recursively checks nested objects.
function setConfigObject (config, prev) {
Object.keys(config).forEach(function (key) {
var value = config[key]
var fullKey = prev ? prev + '.' + key : key
// if the value is an inner object and we have dot-notation
// enabled, treat inner objects in config the same as
// heavily nested dot notations (foo.bar.apple).
if (typeof value === 'object' && !Array.isArray(value) && configuration['dot-notation']) {
// if the value is an object but not an array, check nested object
setConfigObject(value, fullKey)
} else {
// setting arguments via CLI takes precedence over
// values within the config file.
if (!hasKey(argv, fullKey.split('.')) || (flags.defaulted[fullKey])) {
setArg(fullKey, value)
}
}
})
}
// set all config objects passed in opts
function setConfigObjects () {
if (typeof configObjects === 'undefined') return
configObjects.forEach(function (configObject) {
setConfigObject(configObject)
})
}
function applyEnvVars (argv, configOnly) {
if (typeof envPrefix === 'undefined') return
var prefix = typeof envPrefix === 'string' ? envPrefix : ''
Object.keys(process.env).forEach(function (envVar) {
if (prefix === '' || envVar.lastIndexOf(prefix, 0) === 0) {
// get array of nested keys and convert them to camel case
var keys = envVar.split('__').map(function (key, i) {
if (i === 0) {
key = key.substring(prefix.length)
}
return camelCase(key)
})
if (((configOnly && flags.configs[keys.join('.')]) || !configOnly) && (!hasKey(argv, keys) || flags.defaulted[keys.join('.')])) {
setArg(keys.join('.'), process.env[envVar])
}
}
})
}
function applyCoercions (argv) {
var coerce
Object.keys(argv).forEach(function (key) {
coerce = checkAllAliases(key, flags.coercions)
if (typeof coerce === 'function') {
try {
argv[key] = coerce(argv[key])
} catch (err) {
error = err
}
}
})
}
function applyDefaultsAndAliases (obj, aliases, defaults) {
Object.keys(defaults).forEach(function (key) {
if (!hasKey(obj, key.split('.'))) {
setKey(obj, key.split('.'), defaults[key])
;(aliases[key] || []).forEach(function (x) {
if (hasKey(obj, x.split('.'))) return
setKey(obj, x.split('.'), defaults[key])
})
}
})
}
function hasKey (obj, keys) {
var o = obj
if (!configuration['dot-notation']) keys = [keys.join('.')]
keys.slice(0, -1).forEach(function (key) {
o = (o[key] || {})
})
var key = keys[keys.length - 1]
if (typeof o !== 'object') return false
else return key in o
}
function setKey (obj, keys, value) {
var o = obj
if (!configuration['dot-notation']) keys = [keys.join('.')]
keys.slice(0, -1).forEach(function (key) {
if (o[key] === undefined) o[key] = {}
o = o[key]
})
var key = keys[keys.length - 1]
var isTypeArray = checkAllAliases(keys.join('.'), flags.arrays)
var isValueArray = Array.isArray(value)
var duplicate = configuration['duplicate-arguments-array']
if (value === increment) {
o[key] = increment(o[key])
} else if (Array.isArray(o[key])) {
if (duplicate && isTypeArray && isValueArray) {
o[key] = configuration['flatten-duplicate-arrays'] ? o[key].concat(value) : [o[key]].concat([value])
} else if (!duplicate && Boolean(isTypeArray) === Boolean(isValueArray)) {
o[key] = value
} else {
o[key] = o[key].concat([value])
}
} else if (o[key] === undefined && isTypeArray) {
o[key] = isValueArray ? value : [value]
} else if (duplicate && !(o[key] === undefined || checkAllAliases(key, flags.bools) || checkAllAliases(keys.join('.'), flags.bools) || checkAllAliases(key, flags.counts))) {
o[key] = [ o[key], value ]
} else {
o[key] = value
}
}
// extend the aliases list with inferred aliases.
function extendAliases () {
Array.prototype.slice.call(arguments).forEach(function (obj) {
Object.keys(obj || {}).forEach(function (key) {
// short-circuit if we've already added a key
// to the aliases array, for example it might
// exist in both 'opts.default' and 'opts.key'.
if (flags.aliases[key]) return
flags.aliases[key] = [].concat(aliases[key] || [])
// For "--option-name", also set argv.optionName
flags.aliases[key].concat(key).forEach(function (x) {
if (/-/.test(x) && configuration['camel-case-expansion']) {
var c = camelCase(x)
if (flags.aliases[key].indexOf(c) === -1) {
flags.aliases[key].push(c)
}
newAliases[c] = true
}
})
flags.aliases[key].forEach(function (x) {
flags.aliases[x] = [key].concat(flags.aliases[key].filter(function (y) {
return x !== y
}))
})
})
})
}
// check if a flag is set for any of a key's aliases.
function checkAllAliases (key, flag) {
var isSet = false
var toCheck = [].concat(flags.aliases[key] || [], key)
toCheck.forEach(function (key) {
if (flag[key]) isSet = flag[key]
})
return isSet
}
function setDefaulted (key) {
[].concat(flags.aliases[key] || [], key).forEach(function (k) {
flags.defaulted[k] = true
})
}
function unsetDefaulted (key) {
[].concat(flags.aliases[key] || [], key).forEach(function (k) {
delete flags.defaulted[k]
})
}
// return a default value, given the type of a flag.,
// e.g., key of type 'string' will default to '', rather than 'true'.
function defaultForType (type) {
var def = {
boolean: true,
string: '',
number: undefined,
array: []
}
return def[type]
}
// given a flag, enforce a default type.
function guessType (key, flags) {
var type = 'boolean'
if (checkAllAliases(key, flags.strings)) type = 'string'
else if (checkAllAliases(key, flags.numbers)) type = 'number'
else if (checkAllAliases(key, flags.arrays)) type = 'array'
return type
}
function isNumber (x) {
if (typeof x === 'number') return true
if (/^0x[0-9a-f]+$/i.test(x)) return true
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x)
}
function isUndefined (num) {
return num === undefined
}
return {
argv: argv,
error: error,
aliases: flags.aliases,
newAliases: newAliases,
configuration: configuration
}
}
// if any aliases reference each other, we should
// merge them together.
function combineAliases (aliases) {
var aliasArrays = []
var change = true
var combined = {}
// turn alias lookup hash {key: ['alias1', 'alias2']} into
// a simple array ['key', 'alias1', 'alias2']
Object.keys(aliases).forEach(function (key) {
aliasArrays.push(
[].concat(aliases[key], key)
)
})
// combine arrays until zero changes are
// made in an iteration.
while (change) {
change = false
for (var i = 0; i < aliasArrays.length; i++) {
for (var ii = i + 1; ii < aliasArrays.length; ii++) {
var intersect = aliasArrays[i].filter(function (v) {
return aliasArrays[ii].indexOf(v) !== -1
})
if (intersect.length) {
aliasArrays[i] = aliasArrays[i].concat(aliasArrays[ii])
aliasArrays.splice(ii, 1)
change = true
break
}
}
}
}
// map arrays back to the hash-lookup (de-dupe while
// we're at it).
aliasArrays.forEach(function (aliasArray) {
aliasArray = aliasArray.filter(function (v, i, self) {
return self.indexOf(v) === i
})
combined[aliasArray.pop()] = aliasArray
})
return combined
}
function assign (defaults, configuration) {
var o = {}
configuration = configuration || {}
Object.keys(defaults).forEach(function (k) {
o[k] = defaults[k]
})
Object.keys(configuration).forEach(function (k) {
o[k] = configuration[k]
})
return o
}
// this function should only be called when a count is given as an arg
// it is NOT called to set a default value
// thus we can start the count at 1 instead of 0
function increment (orig) {
return orig !== undefined ? orig + 1 : 1
}
function Parser (args, opts) {
var result = parse(args.slice(), opts)
return result.argv
}
// parse arguments and return detailed
// meta information, aliases, etc.
Parser.detailed = function (args, opts) {
return parse(args.slice(), opts)
}
module.exports = Parser
yargs-parser-8.0.0/lib/ 0000775 0000000 0000000 00000000000 13165347466 0014723 5 ustar 00root root 0000000 0000000 yargs-parser-8.0.0/lib/tokenize-arg-string.js 0000664 0000000 0000000 00000001435 13165347466 0021167 0 ustar 00root root 0000000 0000000 // take an un-split argv string and tokenize it.
module.exports = function (argString) {
if (Array.isArray(argString)) return argString
var i = 0
var prevC = null
var c = null
var opening = null
var args = []
for (var ii = 0; ii < argString.length; ii++) {
prevC = c
c = argString.charAt(ii)
// split on spaces unless we're in quotes.
if (c === ' ' && !opening) {
if (!(prevC === ' ')) {
i++
}
continue
}
// don't split the string if we're in matching
// opening or closing single and double quotes.
if (c === opening) {
opening = null
continue
} else if ((c === "'" || c === '"') && !opening) {
opening = c
continue
}
if (!args[i]) args[i] = ''
args[i] += c
}
return args
}
yargs-parser-8.0.0/package.json 0000664 0000000 0000000 00000001545 13165347466 0016450 0 ustar 00root root 0000000 0000000 {
"name": "yargs-parser",
"version": "8.0.0",
"description": "the mighty option parser used by yargs",
"main": "index.js",
"scripts": {
"pretest": "standard",
"test": "nyc mocha test/*.js",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"release": "standard-version"
},
"repository": {
"url": "git@github.com:yargs/yargs-parser.git"
},
"keywords": [
"argument",
"parser",
"yargs",
"command",
"cli",
"parsing",
"option",
"args",
"argument"
],
"author": "Ben Coe ",
"license": "ISC",
"devDependencies": {
"chai": "^3.5.0",
"coveralls": "^2.11.12",
"mocha": "^3.0.1",
"nyc": "^11.2.1",
"standard": "^10.0.2",
"standard-version": "^4.0.0"
},
"dependencies": {
"camelcase": "^4.1.0"
},
"files": [
"lib",
"index.js"
]
}
yargs-parser-8.0.0/test/ 0000775 0000000 0000000 00000000000 13165347466 0015134 5 ustar 00root root 0000000 0000000 yargs-parser-8.0.0/test/fixtures/ 0000775 0000000 0000000 00000000000 13165347466 0017005 5 ustar 00root root 0000000 0000000 yargs-parser-8.0.0/test/fixtures/config.json 0000664 0000000 0000000 00000000142 13165347466 0021142 0 ustar 00root root 0000000 0000000 {
"herp": "derp",
"z": 55,
"foo": "baz",
"version": "1.0.2",
"truthy": true
}
yargs-parser-8.0.0/test/fixtures/config.txt 0000664 0000000 0000000 00000000035 13165347466 0021011 0 ustar 00root root 0000000 0000000 AWESOME=banana
BATMAN=grumpy
yargs-parser-8.0.0/test/fixtures/nested_config.json 0000664 0000000 0000000 00000000120 13165347466 0022500 0 ustar 00root root 0000000 0000000 {
"a": "a",
"nested": {
"foo": "baz",
"bar": "bar"
},
"b": "b"
} yargs-parser-8.0.0/test/fixtures/settings.js 0000664 0000000 0000000 00000000127 13165347466 0021203 0 ustar 00root root 0000000 0000000 module.exports = {
calculate: function (a) {
return a + 55
},
herp: 'derp'
}
yargs-parser-8.0.0/test/tokenize-arg-string.js 0000664 0000000 0000000 00000003024 13165347466 0021374 0 ustar 00root root 0000000 0000000 /* global describe, it */
var tokenizeArgString = require('../lib/tokenize-arg-string')
require('chai').should()
var expect = require('chai').expect
describe('TokenizeArgString', function () {
it('handles unquoted string', function () {
var args = tokenizeArgString('--foo 99')
args[0].should.equal('--foo')
args[1].should.equal('99')
})
it('handles quoted string with no spaces', function () {
var args = tokenizeArgString("--foo 'hello'")
args[0].should.equal('--foo')
args[1].should.equal('hello')
})
it('handles single quoted string with spaces', function () {
var args = tokenizeArgString("--foo 'hello world' --bar='foo bar'")
args[0].should.equal('--foo')
args[1].should.equal('hello world')
args[2].should.equal('--bar=foo bar')
})
it('handles double quoted string with spaces', function () {
var args = tokenizeArgString('--foo "hello world" --bar="foo bar"')
args[0].should.equal('--foo')
args[1].should.equal('hello world')
args[2].should.equal('--bar=foo bar')
})
it('handles quoted string with embeded quotes', function () {
var args = tokenizeArgString('--foo "hello \'world\'" --bar=\'foo "bar"\'')
args[0].should.equal('--foo')
args[1].should.equal('hello \'world\'')
args[2].should.equal('--bar=foo "bar"')
})
it('multiple spaces only counted in quotes', function () {
var args = tokenizeArgString('foo bar "foo bar"')
args[0].should.equal('foo')
expect(args[1]).equal('bar')
expect(args[2]).equal('foo bar')
})
})
yargs-parser-8.0.0/test/yargs-parser.js 0000664 0000000 0000000 00000222421 13165347466 0020114 0 ustar 00root root 0000000 0000000 /* global beforeEach, describe, it */
require('chai').should()
var expect = require('chai').expect
var fs = require('fs')
var parser = require('../')
var path = require('path')
describe('yargs-parser', function () {
it('should parse a "short boolean"', function () {
var parse = parser([ '-b' ])
parse.should.not.have.property('--')
parse.should.have.property('b').to.be.ok.and.be.a('boolean')
parse.should.have.property('_').with.length(0)
})
it('should parse a "long boolean"', function () {
var parse = parser('--bool')
parse.should.not.have.property('--')
parse.should.have.property('bool', true)
parse.should.have.property('_').with.length(0)
})
it('should place bare options in the _ array', function () {
var parse = parser('foo bar baz')
parse.should.have.property('_').and.deep.equal(['foo', 'bar', 'baz'])
})
it('should set the value of the final option in a group to the next supplied value', function () {
var parse = parser(['-cats', 'meow'])
parse.should.have.property('c', true)
parse.should.have.property('a', true)
parse.should.have.property('t', true)
parse.should.have.property('s', 'meow')
parse.should.have.property('_').with.length(0)
})
it('should set the value of a single long option to the next supplied value', function () {
var parse = parser(['--pow', 'xixxle'])
parse.should.have.property('pow', 'xixxle')
parse.should.have.property('_').with.length(0)
})
it('should set the value of a single long option to the next supplied value, even if the value is empty', function () {
var parse = parser(['--pow', ''])
parse.should.have.property('pow', '')
parse.should.have.property('_').with.length(0)
})
it('should set the value of a single long option if an = was used', function () {
var parse = parser(['--pow=xixxle'])
parse.should.have.property('pow', 'xixxle')
parse.should.have.property('_').with.length(0)
})
it('should set the value of multiple long options to the next supplied values relative to each', function () {
var parse = parser(['--host', 'localhost', '--port', '555'])
parse.should.have.property('host', 'localhost')
parse.should.have.property('port', 555)
parse.should.have.property('_').with.length(0)
})
it('should set the value of multiple long options if = signs were used', function () {
var parse = parser(['--host=localhost', '--port=555'])
parse.should.have.property('host', 'localhost')
parse.should.have.property('port', 555)
parse.should.have.property('_').with.length(0)
})
it('should still set values appropriately if a mix of short, long, and grouped short options are specified', function () {
var parse = parser(['-h', 'localhost', '-fp', '555', 'script.js'])
parse.should.have.property('f', true)
parse.should.have.property('p', 555)
parse.should.have.property('h', 'localhost')
parse.should.have.property('_').and.deep.equal(['script.js'])
})
it('should still set values appropriately if a mix of short and long options are specified', function () {
var parse = parser(['-h', 'localhost', '--port', '555'])
parse.should.have.property('h', 'localhost')
parse.should.have.property('port', 555)
parse.should.have.property('_').with.length(0)
})
it('should explicitly set a boolean option to false if preceeded by "--no-"', function () {
var parse = parser(['--no-moo'])
parse.should.have.property('moo', false)
parse.should.have.property('_').with.length(0)
})
it('should still set values appropriately if we supply a comprehensive list of various types of options', function () {
var parse = parser([
'--name=meowmers', 'bare', '-cats', 'woo',
'-h', 'awesome', '--multi=quux',
'--key', 'value',
'-b', '--bool', '--no-meep', '--multi=baz',
'--', '--not-a-flag', '-', '-h', '-multi', '--', 'eek'
], {
configuration: {
'populate--': false
}
})
parse.should.have.property('c', true)
parse.should.have.property('a', true)
parse.should.have.property('t', true)
parse.should.have.property('s', 'woo')
parse.should.have.property('h', 'awesome')
parse.should.have.property('b', true)
parse.should.have.property('bool', true)
parse.should.have.property('key', 'value')
parse.should.have.property('multi').and.deep.equal(['quux', 'baz'])
parse.should.have.property('meep', false)
parse.should.have.property('name', 'meowmers')
parse.should.have.property('_').and.deep.equal(['bare', '--not-a-flag', '-', '-h', '-multi', '--', 'eek'])
})
it('should parse numbers appropriately', function () {
var argv = parser([
'-x', '1234',
'-y', '5.67',
'-z', '1e7',
'-w', '10f',
'--hex', '0xdeadbeef',
'789'
])
argv.should.have.property('x', 1234).and.be.a('number')
argv.should.have.property('y', 5.67).and.be.a('number')
argv.should.have.property('z', 1e7).and.be.a('number')
argv.should.have.property('w', '10f').and.be.a('string')
argv.should.have.property('hex', 0xdeadbeef).and.be.a('number')
argv.should.have.property('_').and.deep.equal([789])
argv._[0].should.be.a('number')
})
// addresses: https://github.com/yargs/yargs-parser/issues/33
it('should handle parsing negative #s', function () {
var argv = parser([
'-33', '-177', '33',
'--n1', '-33',
'-n', '-44',
'--n2=-55',
'--foo.bar', '-33',
'-o=-55',
'--bounds', '-180', '99', '-180', '90',
'--other', '-99', '-220'
], {
array: 'bounds',
narg: {'other': 2}
})
argv._.should.deep.equal([-33, -177, 33])
argv.n1.should.equal(-33)
argv.n.should.equal(-44)
argv.n2.should.equal(-55)
argv.foo.bar.should.equal(-33)
argv.o.should.equal(-55)
argv.bounds.should.deep.equal([-180, 99, -180, 90])
argv.other.should.deep.equal([-99, -220])
})
it('should set the value of a single short option to the next supplied value, even if the value is empty', function () {
var parse = parser(['-p', ''])
parse.should.have.property('p', '')
parse.should.have.property('_').with.length(0)
})
it('should not set the next value as the value of a short option if that option is explicitly defined as a boolean', function () {
var parse = parser([ '-t', 'moo' ], {
boolean: 't'
})
parse.should.have.property('t', true).and.be.a('boolean')
parse.should.have.property('_').and.deep.equal(['moo'])
})
it('should set boolean options values if the next value is "true" or "false"', function () {
var parse = parser(['--verbose', 'false', 'moo', '-t', 'true'], {
boolean: ['t', 'verbose'],
default: {
verbose: true
}
})
parse.should.have.property('verbose', false).and.be.a('boolean')
parse.should.have.property('t', true).and.be.a('boolean')
parse.should.have.property('_').and.deep.equal(['moo'])
})
it('should not set boolean options values if the next value only contains the words "true" or "false"', function () {
var parse = parser(['--verbose', 'aaatrueaaa', 'moo', '-t', 'aaafalseaaa'], {
boolean: ['t', 'verbose']
})
parse.should.have.property('verbose', true).and.be.a('boolean')
parse.should.have.property('t', true).and.be.a('boolean')
parse.should.have.property('_').and.deep.equal(['aaatrueaaa', 'moo', 'aaafalseaaa'])
})
it('should allow defining options as boolean in groups', function () {
var parse = parser([ '-x', '-z', 'one', 'two', 'three' ], {
boolean: ['x', 'y', 'z']
})
parse.should.have.property('x', true).and.be.a('boolean')
parse.should.have.property('y', false).and.be.a('boolean')
parse.should.have.property('z', true).and.be.a('boolean')
parse.should.have.property('_').and.deep.equal(['one', 'two', 'three'])
})
it('should correctly parse dot-notation boolean flags', function () {
var parse = parser(['--nested', '--n.v', '--n.y', 'foo'], {
boolean: ['nested', 'n.v']
})
parse.should.have.property('nested', true).and.be.a('boolean')
parse.should.have.property('n').and.deep.equal({
v: true,
y: 'foo'
})
})
it('should preserve newlines in option values', function () {
var args = parser(['-s', 'X\nX'])
args.should.have.property('_').with.length(0)
args.should.have.property('s', 'X\nX')
// reproduce in bash:
// VALUE="new
// line"
// node program.js --s="$VALUE"
args = parser(['--s=X\nX'])
args.should.have.property('_').with.length(0)
args.should.have.property('s', 'X\nX')
})
it('should not convert numbers to type number if explicitly defined as strings', function () {
var s = parser([ '-s', '0001234' ], {
string: 's'
}).s
s.should.be.a('string').and.equal('0001234')
var x = parser([ '-x', '56' ], {
string: ['x']
}).x
x.should.be.a('string').and.equal('56')
})
it('should default numbers to undefined', function () {
var n = parser([ '-n' ], {
number: ['n']
}).n
expect(n).to.equal(undefined)
})
it('should default number to NaN if value is not a valid number', function () {
var n = parser([ '-n', 'string' ], {
number: ['n']
}).n
expect(n).to.deep.equal(NaN)
})
// Fixes: https://github.com/bcoe/yargs/issues/68
it('should parse flag arguments with no right-hand-value as strings, if defined as strings', function () {
var s = parser([ '-s' ], {
string: ['s']
}).s
s.should.be.a('string').and.equal('')
s = parser([ '-sf' ], {
string: ['s']
}).s
s.should.be.a('string').and.equal('')
s = parser([ '--string' ], {
string: ['string']
}).string
s.should.be.a('string').and.equal('')
})
it('should leave all non-hyphenated values as strings if _ is defined as a string', function () {
var s = parser([ ' ', ' ' ], {
string: ['_']
})._
s.should.have.length(2)
s[0].should.be.a('string').and.equal(' ')
s[1].should.be.a('string').and.equal(' ')
})
describe('normalize', function () {
it('should normalize redundant paths', function () {
var a = parser([ '-s', ['', 'tmp', '..', ''].join(path.sep) ], {
alias: {
s: ['save']
},
normalize: 's'
})
a.should.have.property('s', path.sep)
a.should.have.property('save', path.sep)
})
it('should normalize redundant paths when a value is later assigned', function () {
var a = parser(['-s'], {
normalize: ['s']
})
a.should.have.property('s', true)
a.s = ['', 'path', 'to', 'new', 'dir', '..', '..', ''].join(path.sep)
a.s.should.equal(['', 'path', 'to', ''].join(path.sep))
})
it('should normalize when key is also an array', function () {
var a = parser([ '-s', ['', 'tmp', '..', ''].join(path.sep), ['', 'path', 'to', 'new', 'dir', '..', '..', ''].join(path.sep) ], {
alias: {
s: ['save']
},
normalize: 's',
array: 's'
})
var expected = [path.sep, ['', 'path', 'to', ''].join(path.sep)]
a.should.have.property('s').and.deep.equal(expected)
a.should.have.property('save').and.deep.equal(expected)
})
})
describe('alias', function () {
it('should set alias value to the same value as the full option', function () {
var argv = parser([ '-f', '11', '--zoom', '55' ], {
alias: {
z: ['zoom']
}
})
argv.should.have.property('zoom', 55)
argv.should.have.property('z', 55)
argv.should.have.property('f', 11)
})
it('should allow multiple aliases to be specified', function () {
var argv = parser([ '-f', '11', '--zoom', '55' ], {
alias: {
z: ['zm', 'zoom']
}
})
argv.should.have.property('zoom', 55)
argv.should.have.property('z', 55)
argv.should.have.property('zm', 55)
argv.should.have.property('f', 11)
})
// regression, see https://github.com/chevex/yargs/issues/63
it('should not add the same key to argv multiple times, when creating camel-case aliases', function () {
var argv = parser(['--health-check=banana', '--second-key', 'apple', '-t=blarg'], {
alias: {
h: ['health-check'],
'second-key': ['s'],
'third-key': ['t']
},
default: {
h: 'apple',
'second-key': 'banana',
'third-key': 'third'
}
})
// before this fix, yargs failed parsing
// one but not all forms of an arg.
argv.secondKey.should.eql('apple')
argv.s.should.eql('apple')
argv['second-key'].should.eql('apple')
argv.healthCheck.should.eql('banana')
argv.h.should.eql('banana')
argv['health-check'].should.eql('banana')
argv.thirdKey.should.eql('blarg')
argv.t.should.eql('blarg')
argv['third-key'].should.eql('blarg')
})
it('should allow transitive aliases to be specified', function () {
var argv = parser([ '-f', '11', '--zoom', '55' ], {
alias: {
z: 'zm',
zm: 'zoom'
}
})
argv.should.have.property('zoom', 55)
argv.should.have.property('z', 55)
argv.should.have.property('zm', 55)
argv.should.have.property('f', 11)
})
it('should merge two lists of aliases if they collide', function () {
var argv = parser(['-f', '11', '--zoom', '55'], {
alias: {
z: 'zm',
zoom: 'zoop',
zm: 'zoom'
}
})
argv.should.have.property('zoom', 55)
argv.should.have.property('zoop', 55)
argv.should.have.property('z', 55)
argv.should.have.property('zm', 55)
argv.should.have.property('f', 11)
})
})
it('should assign data after forward slash to the option before the slash', function () {
var parse = parser(['-I/foo/bar/baz'])
parse.should.have.property('_').with.length(0)
parse.should.have.property('I', '/foo/bar/baz')
parse = parser(['-xyz/foo/bar/baz'])
parse.should.have.property('x', true)
parse.should.have.property('y', true)
parse.should.have.property('z', '/foo/bar/baz')
parse.should.have.property('_').with.length(0)
})
describe('config', function () {
var jsonPath = path.resolve(__dirname, './fixtures/config.json')
// See: https://github.com/chevex/yargs/issues/12
it('should load options and values from default config if specified', function () {
var argv = parser([ '--foo', 'bar' ], {
alias: {
z: 'zoom'
},
default: {
settings: jsonPath
},
config: 'settings'
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('zoom', 55)
argv.should.have.property('foo').and.deep.equal('bar')
})
it('should use value from config file, if argv value is using default value', function () {
var argv = parser([], {
alias: {
z: 'zoom'
},
config: ['settings'],
default: {
settings: jsonPath,
foo: 'banana'
}
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('zoom', 55)
argv.should.have.property('foo').and.deep.equal('baz')
})
it('should use value from config file, if argv key is a boolean', function () {
var argv = parser([], {
config: ['settings'],
default: {
settings: jsonPath
},
boolean: ['truthy']
})
argv.should.have.property('truthy', true)
})
it('should use value from cli, if cli overrides boolean argv key', function () {
var argv = parser(['--no-truthy'], {
config: ['settings'],
default: {
settings: jsonPath
},
boolean: ['truthy']
})
argv.should.have.property('truthy', false)
})
it('should use cli value, if cli value is set and both cli and default value match', function () {
var argv = parser(['--foo', 'banana'], {
alias: {
z: 'zoom'
},
config: ['settings'],
default: {
settings: jsonPath,
foo: 'banana'
}
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('zoom', 55)
argv.should.have.property('foo').and.deep.equal('banana')
})
it("should allow config to be set as flag in 'option'", function () {
var argv = parser([ '--settings', jsonPath, '--foo', 'bar' ], {
alias: {
z: 'zoom'
},
config: ['settings']
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('zoom', 55)
argv.should.have.property('foo').and.deep.equal('bar')
})
it('should load options and values from a JS file when config has .js extention', function () {
var jsPath = path.resolve(__dirname, './fixtures/settings.js')
var argv = parser([ '--settings', jsPath, '--foo', 'bar' ], {
config: ['settings']
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('foo', 'bar')
argv.should.have.property('calculate').and.be.a('function')
})
it('should raise an appropriate error if JSON file is not found', function () {
var argv = parser.detailed(['--settings', 'fake.json', '--foo', 'bar'], {
alias: {
z: 'zoom'
},
config: ['settings']
})
argv.error.message.should.equal('Invalid JSON config file: fake.json')
})
// see: https://github.com/bcoe/yargs/issues/172
it('should not raise an exception if config file is set as default argument value', function () {
var argv = parser.detailed([], {
default: {
config: 'foo.json'
},
config: ['config']
})
expect(argv.error).to.equal(null)
})
it('should load nested options from config file', function () {
var jsonPath = path.resolve(__dirname, './fixtures/nested_config.json')
var argv = parser(['--settings', jsonPath, '--nested.foo', 'bar'], {
config: ['settings']
})
argv.should.have.property('a', 'a')
argv.should.have.property('b', 'b')
argv.should.have.property('nested').and.deep.equal({
foo: 'bar',
bar: 'bar'
})
})
it('should use nested value from config file, if argv value is using default value', function () {
var jsonPath = path.resolve(__dirname, './fixtures/nested_config.json')
var argv = parser(['--settings', jsonPath], {
config: ['settings'],
default: {
'nested.foo': 'banana'
}
})
argv.should.have.property('a', 'a')
argv.should.have.property('b', 'b')
argv.should.have.property('nested').and.deep.equal({
foo: 'baz',
bar: 'bar'
})
})
it('allows a custom parsing function to be provided', function () {
var jsPath = path.resolve(__dirname, './fixtures/config.txt')
var argv = parser([ '--settings', jsPath, '--foo', 'bar' ], {
config: {
settings: function (configPath) {
// as an example, parse an environment
// variable style config:
// FOO=99
// BATMAN=grumpy
var config = {}
var txt = fs.readFileSync(configPath, 'utf-8')
txt.split(/\r?\n/).forEach(function (l) {
var kv = l.split('=')
config[kv[0].toLowerCase()] = kv[1]
})
return config
}
}
})
argv.batman.should.equal('grumpy')
argv.awesome.should.equal('banana')
argv.foo.should.equal('bar')
})
it('allows a custom parsing function to be provided as an alias', function () {
var jsPath = path.resolve(__dirname, './fixtures/config.json')
var argv = parser([ '--settings', jsPath, '--foo', 'bar' ], {
config: {
s: function (configPath) {
return JSON.parse(fs.readFileSync(configPath, 'utf-8'))
}
},
alias: {
s: ['settings']
}
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('foo', 'bar')
})
it('outputs an error returned by the parsing function', function () {
var argv = parser.detailed(['--settings=./package.json'], {
config: {
settings: function (configPath) {
return Error('someone set us up the bomb')
}
}
})
argv.error.message.should.equal('someone set us up the bomb')
})
it('outputs an error if thrown by the parsing function', function () {
var argv = parser.detailed(['--settings=./package.json'], {
config: {
settings: function (configPath) {
throw Error('someone set us up the bomb')
}
}
})
argv.error.message.should.equal('someone set us up the bomb')
})
})
describe('config objects', function () {
it('should load options from config object', function () {
var argv = parser([ '--foo', 'bar' ], {
configObjects: [{
apple: 'apple',
banana: 42,
foo: 'baz'
}]
})
argv.should.have.property('apple', 'apple')
argv.should.have.property('banana', 42)
argv.should.have.property('foo', 'bar')
})
it('should use value from config object, if argv value is using default value', function () {
var argv = parser([], {
configObjects: [{
apple: 'apple',
banana: 42,
foo: 'baz'
}],
default: {
foo: 'banana'
}
})
argv.should.have.property('apple', 'apple')
argv.should.have.property('banana', 42)
argv.should.have.property('foo', 'baz')
})
it('should use value from config object to all aliases', function () {
var argv = parser([], {
configObjects: [{
apple: 'apple',
banana: 42,
foo: 'baz'
}],
alias: {
a: ['apple'],
banana: ['b']
}
})
argv.should.have.property('apple', 'apple')
argv.should.have.property('a', 'apple')
argv.should.have.property('banana', 42)
argv.should.have.property('b', 42)
argv.should.have.property('foo', 'baz')
})
it('should load nested options from config object', function () {
var argv = parser(['--nested.foo', 'bar'], {
configObjects: [{
a: 'a',
nested: {
foo: 'baz',
bar: 'bar'
},
b: 'b'
}]
})
argv.should.have.property('a', 'a')
argv.should.have.property('b', 'b')
argv.should.have.property('nested').and.deep.equal({
foo: 'bar',
bar: 'bar'
})
})
it('should use nested value from config object, if argv value is using default value', function () {
var argv = parser([], {
configObjects: [{
a: 'a',
nested: {
foo: 'baz',
bar: 'bar'
},
b: 'b'
}],
default: {
'nested.foo': 'banana'
}
})
argv.should.have.property('a', 'a')
argv.should.have.property('b', 'b')
argv.should.have.property('nested').and.deep.equal({
foo: 'baz',
bar: 'bar'
})
})
})
describe('dot notation', function () {
it('should allow object graph traversal via dot notation', function () {
var argv = parser([
'--foo.bar', '3', '--foo.baz', '4',
'--foo.quux.quibble', '5', '--foo.quux.o_O',
'--beep.boop'
])
argv.should.have.property('foo').and.deep.equal({
bar: 3,
baz: 4,
quux: {
quibble: 5,
o_O: true
}
})
argv.should.have.property('beep').and.deep.equal({ boop: true })
})
it('should apply defaults to dot notation arguments', function () {
var argv = parser([], {
default: {
'foo.bar': 99
}
})
argv.foo.bar.should.eql(99)
})
// see #279
it('should allow default to be overridden when an alias is provided', function () {
var argv = parser(['--foo.bar', '200'], {
default: {
'foo.bar': 99
}
})
argv.foo.bar.should.eql(200)
})
// see #279
it('should also override alias', function () {
var argv = parser(['--foo.bar', '200'], {
alias: {
'foo.bar': ['f']
},
default: {
'foo.bar': 99
}
})
argv.f.should.eql(200)
})
// see #279
it('should not set an undefined dot notation key', function () {
var argv = parser(['--foo.bar', '200'], {
default: {
'foo.bar': 99
},
alias: {
'foo.bar': ['f']
}
})
;('foo.bar' in argv).should.equal(false)
})
it('should respect .string() for dot notation arguments', function () {
var argv = parser(['--foo.bar', '99', '--bar.foo=99'], {
string: ['foo.bar']
})
argv.foo.bar.should.eql('99')
argv.bar.foo.should.eql(99)
})
it('should populate aliases when dot notation is used', function () {
var argv = parser(['--foo.bar', '99'], {
alias: {
foo: ['f']
}
})
argv.f.bar.should.eql(99)
})
it('should populate aliases when nested dot notation is used', function () {
var argv = parser(['--foo.bar.snuh', '99', '--foo.apple', '33', '--foo.bar.cool', '11'], {
alias: {
foo: ['f']
}
})
argv.f.bar.snuh.should.eql(99)
argv.foo.bar.snuh.should.eql(99)
argv.f.apple.should.eql(33)
argv.foo.apple.should.eql(33)
argv.f.bar.cool.should.eql(11)
argv.foo.bar.cool.should.eql(11)
})
it("should allow flags to use dot notation, when seperated by '='", function () {
var argv = parser(['-f.foo=99'])
argv.f.foo.should.eql(99)
})
it("should allow flags to use dot notation, when seperated by ' '", function () {
var argv = parser(['-f.foo', '99'])
argv.f.foo.should.eql(99)
})
it('should allow flags to use dot notation when no right-hand-side is given', function () {
var argv = parser(['-f.foo', '99', '-f.bar'])
argv.f.foo.should.eql(99)
argv.f.bar.should.eql(true)
})
})
it('should set boolean and alias using explicit true', function () {
var aliased = [ '-h', 'true' ]
var aliasedArgv = parser(aliased, {
boolean: ['h'],
alias: {
h: ['herp']
}
})
aliasedArgv.should.have.property('herp', true)
aliasedArgv.should.have.property('h', true)
aliasedArgv.should.have.property('_').with.length(0)
})
// regression, see https://github.com/substack/node-optimist/issues/71
it('should set boolean and --x=true', function () {
var parsed = parser(['--boool', '--other=true'], {
boolean: ['boool']
})
parsed.should.have.property('boool', true)
parsed.should.have.property('other', 'true')
parsed = parser(['--boool', '--other=false'], {
boolean: ['boool']
})
parsed.should.have.property('boool', true)
parsed.should.have.property('other', 'false')
})
// regression, see https://github.com/chevex/yargs/issues/66
it('should set boolean options values if next value is "true" or "false" with = as separator', function () {
var argv = parser(['--bool=false'], {
boolean: ['b'],
alias: {
b: ['bool']
},
default: {
b: true
}
})
argv.bool.should.eql(false)
})
describe('short options', function () {
it('should set the value of multiple single short options to the next supplied values relative to each', function () {
var parse = parser(['-h', 'localhost', '-p', '555'])
parse.should.have.property('h', 'localhost')
parse.should.have.property('p', 555)
parse.should.have.property('_').with.length(0)
})
it('should set the value of a single short option to the next supplied value', function () {
var parse = parser(['-h', 'localhost'])
parse.should.have.property('h', 'localhost')
parse.should.have.property('_').with.length(0)
})
it('should expand grouped short options to a hash with a key for each', function () {
var parse = parser(['-cats'])
parse.should.have.property('c', true)
parse.should.have.property('a', true)
parse.should.have.property('t', true)
parse.should.have.property('s', true)
parse.should.have.property('_').with.length(0)
})
it('should set n to the numeric value 123', function () {
var argv = parser([ '-n123' ])
argv.should.have.property('n', 123)
})
it('should set n to the numeric value 123, with n at the end of a group', function () {
var argv = parser([ '-ab5n123' ])
argv.should.have.property('a', true)
argv.should.have.property('b', true)
argv.should.have.property('5', true)
argv.should.have.property('n', 123)
argv.should.have.property('_').with.length(0)
})
it('should set n to the numeric value 123, with = as separator', function () {
var argv = parser([ '-n=123' ])
argv.should.have.property('n', 123)
})
it('should set n to the numeric value 123, with n at the end of a group and = as separator', function () {
var argv = parser([ '-ab5n=123' ])
argv.should.have.property('a', true)
argv.should.have.property('b', true)
argv.should.have.property('5', true)
argv.should.have.property('n', 123)
argv.should.have.property('_').with.length(0)
})
})
describe('whitespace', function () {
it('should be whitespace', function () {
var argv = parser([ '-x', '\t' ])
argv.should.have.property('x', '\t')
})
})
describe('boolean modifier function', function () {
it('should prevent yargs from sucking in the next option as the value of the first option', function () {
// Arrange & Act
var result = parser(['-b', '123'], {
boolean: ['b']
})
// Assert
result.should.have.property('b').that.is.a('boolean').and.is.true // eslint-disable-line
result.should.have.property('_').and.deep.equal([123])
})
})
describe('defaults', function () {
function checkNoArgs (opts, hasAlias) {
it('should set defaults if no args', function () {
var result = parser([], opts)
result.should.have.property('flag', true)
if (hasAlias) {
result.should.have.property('f', true)
}
})
}
function checkExtraArg (opts, hasAlias) {
it('should set defaults if one extra arg', function () {
var result = parser(['extra'], opts)
result.should.have.property('flag', true)
result.should.have.property('_').and.deep.equal(['extra'])
if (hasAlias) {
result.should.have.property('f', true)
}
})
}
function checkStringArg (opts, hasAlias) {
it('should set defaults even if arg looks like a string', function () {
var result = parser([ '--flag', 'extra' ], opts)
result.should.have.property('flag', true)
result.should.have.property('_').and.deep.equal(['extra'])
if (hasAlias) {
result.should.have.property('f', true)
}
})
}
describe('for options with aliases', function () {
var opts = {
alias: {
flag: ['f']
},
default: {
flag: true
}
}
checkNoArgs(opts, true)
checkExtraArg(opts, true)
})
describe('for typed options without aliases', function () {
var opts = {
boolean: ['flag'],
default: {
flag: true
}
}
checkNoArgs(opts)
checkExtraArg(opts)
checkStringArg(opts)
})
describe('for typed options with aliases', function () {
var opts = {
alias: {
flag: ['f']
},
boolean: ['flag'],
default: {
flag: true
}
}
checkNoArgs(opts, true)
checkExtraArg(opts, true)
checkStringArg(opts, true)
})
describe('for boolean options', function () {
[true, false, undefined, null].forEach(function (def) {
describe('with explicit ' + def + ' default', function () {
var opts = {
default: {
flag: def
},
boolean: ['flag']
}
it('should set true if --flag in arg', function () {
parser(['--flag'], opts).flag.should.be.true // eslint-disable-line
})
it('should set false if --no-flag in arg', function () {
parser(['--no-flag'], opts).flag.should.be.false // eslint-disable-line
})
it('should set ' + def + ' if no flag in arg', function () {
expect(parser([], opts).flag).to.equal(def)
})
})
})
describe('with implied false default', function () {
var opts = null
beforeEach(function () {
opts = {
boolean: ['flag']
}
})
it('should set true if --flag in arg', function () {
parser(['--flag'], opts).flag.should.be.true // eslint-disable-line
})
it('should set false if --no-flag in arg', function () {
parser(['--no-flag'], opts).flag.should.be.false // eslint-disable-line
})
it('should set false if no flag in arg', function () {
parser([], opts).flag.should.be.false // eslint-disable-line
})
})
// Fixes: https://github.com/bcoe/yargs/issues/341
it('should apply defaults to camel-case form of argument', function () {
var argv = parser([], {
default: {
'foo-bar': 99
}
})
argv.fooBar.should.equal(99)
})
})
it('should define option as boolean and set default to true', function () {
var argv = parser([], {
boolean: ['sometrue'],
default: {
sometrue: true
}
})
argv.should.have.property('sometrue', true)
})
it('should define option as boolean and set default to false', function () {
var argv = parser([], {
default: {
somefalse: false
},
boolean: ['somefalse']
})
argv.should.have.property('somefalse', false)
})
it('should set boolean options to false by default', function () {
var parse = parser(['moo'], {
boolean: ['t', 'verbose'],
default: {
verbose: false,
t: false
}
})
parse.should.have.property('verbose', false).and.be.a('boolean')
parse.should.have.property('t', false).and.be.a('boolean')
parse.should.have.property('_').and.deep.equal(['moo'])
})
})
describe('camelCase', function () {
function runTests (strict) {
if (!strict) {
// Skip this test in strict mode because this option is not specified
it('should provide options with dashes as camelCase properties', function () {
var result = parser(['--some-option'])
result.should.have.property('some-option').that.is.a('boolean').and.is.true // eslint-disable-line
result.should.have.property('someOption').that.is.a('boolean').and.is.true // eslint-disable-line
})
}
it('should provide count options with dashes as camelCase properties', function () {
var result = parser([ '--some-option', '--some-option', '--some-option' ], {
count: ['some-option']
})
result.should.have.property('some-option', 3)
result.should.have.property('someOption', 3)
})
it('should provide options with dashes and aliases as camelCase properties', function () {
var result = parser(['--some-option'], {
alias: {
'some-horse': 'o'
}
})
result.should.have.property('some-option').that.is.a('boolean').and.is.true // eslint-disable-line
result.should.have.property('someOption').that.is.a('boolean').and.is.true // eslint-disable-line
})
it('should provide defaults of options with dashes as camelCase properties', function () {
var result = parser([], {
default: {
'some-option': 'asdf'
}
})
result.should.have.property('some-option', 'asdf')
result.should.have.property('someOption', 'asdf')
})
it('should provide aliases of options with dashes as camelCase properties', function () {
var result = parser([], {
default: {
'some-option': 'asdf'
},
alias: {
'some-option': ['o']
}
})
result.should.have.property('o', 'asdf')
result.should.have.property('some-option', 'asdf')
result.should.have.property('someOption', 'asdf')
})
it('should provide aliases of options with dashes as camelCase properties', function () {
var result = parser([], {
alias: {
o: ['some-option']
},
default: {
o: 'asdf'
}
})
result.should.have.property('o', 'asdf')
result.should.have.property('some-option', 'asdf')
result.should.have.property('someOption', 'asdf')
})
it('should provide aliases with dashes as camelCase properties', function () {
var result = parser(['--some-option', 'val'], {
alias: {
o: 'some-option'
}
})
result.should.have.property('o').that.is.a('string').and.equals('val')
result.should.have.property('some-option').that.is.a('string').and.equals('val')
result.should.have.property('someOption').that.is.a('string').and.equals('val')
})
}
describe('dashes and camelCase', function () {
runTests()
})
describe('dashes and camelCase (strict)', function () {
runTests(true)
})
})
describe('-', function () {
it('should set - as value of n', function () {
var argv = parser(['-n', '-'])
argv.should.have.property('n', '-')
argv.should.have.property('_').with.length(0)
})
it('should set - as a non-hyphenated value', function () {
var argv = parser(['-'])
argv.should.have.property('_').and.deep.equal(['-'])
})
it('should set - as a value of f', function () {
var argv = parser(['-f-'])
argv.should.have.property('f', '-')
argv.should.have.property('_').with.length(0)
})
it('should set b to true and set - as a non-hyphenated value when b is set as a boolean', function () {
var argv = parser(['-b', '-'], {
boolean: ['b']
})
argv.should.have.property('b', true)
argv.should.have.property('_').and.deep.equal(['-'])
})
it('should set - as the value of s when s is set as a string', function () {
var argv = parser([ '-s', '-' ], {
string: ['s']
})
argv.should.have.property('s', '-')
argv.should.have.property('_').with.length(0)
})
})
describe('count', function () {
it('should count the number of times a boolean is present', function () {
var parsed
parsed = parser(['-x'], {
count: ['verbose']
})
parsed.verbose.should.equal(0)
parsed = parser(['--verbose'], {
count: ['verbose']
})
parsed.verbose.should.equal(1)
parsed = parser(['--verbose', '--verbose'], {
count: ['verbose']
})
parsed.verbose.should.equal(2)
parsed = parser(['-vvv'], {
alias: {
v: ['verbose']
},
count: ['verbose']
})
parsed.verbose.should.equal(3)
parsed = parser(['--verbose', '--verbose', '-v', '--verbose'], {
count: ['verbose'],
alias: {
v: ['verbose']
}
})
parsed.verbose.should.equal(4)
parsed = parser(['--verbose', '--verbose', '-v', '-vv'], {
count: ['verbose'],
alias: {
v: ['verbose']
}
})
parsed.verbose.should.equal(5)
})
it('should not consume the next argument', function () {
var parsed = parser([ '-v', 'moo' ], {
count: 'v'
})
parsed.v.should.equal(1)
parsed.should.have.property('_').and.deep.equal(['moo'])
parsed = parser([ '--verbose', 'moomoo', '--verbose' ], {
count: 'verbose'
})
parsed.verbose.should.equal(2)
parsed.should.have.property('_').and.deep.equal(['moomoo'])
})
it('should use a default value as is when no arg given', function () {
var parsed = parser([], {
count: 'v',
default: { v: 3 }
})
parsed.v.should.equal(3)
parsed = parser([], {
count: 'v',
default: { v: undefined }
})
expect(parsed.v).to.be.undefined // eslint-disable-line
parsed = parser([], {
count: 'v',
default: { v: null }
})
expect(parsed.v).to.be.null // eslint-disable-line
parsed = parser([], {
count: 'v',
default: { v: false }
})
parsed.v.should.equal(false)
parsed = parser([], {
count: 'v',
default: { v: 'hello' }
})
parsed.v.should.equal('hello')
})
it('should ignore a default value when arg given', function () {
var parsed = parser(['-vv', '-v', '-v'], {
count: 'v',
default: { v: 1 }
})
parsed.v.should.equal(4)
})
it('should increment regardless of arg value', function () {
var parsed = parser([
'-v',
'-v=true',
'-v', 'true',
'-v=false',
'-v', 'false',
'--no-v',
'-v=999',
'-v=foobar'
], { count: 'v' })
parsed.v.should.equal(8)
})
})
describe('array', function () {
it('should group values into an array if the same option is specified multiple times (duplicate-arguments-array=true)', function () {
var parse = parser(['-v', 'a', '-v', 'b', '-v', 'c'], {configuration: {'duplicate-arguments-array': true}})
parse.should.have.property('v').and.deep.equal(['a', 'b', 'c'])
parse.should.have.property('_').with.length(0)
})
it('should keep only the last value if the same option is specified multiple times (duplicate-arguments-false)', function () {
var parse = parser(['-v', 'a', '-v', 'b', '-v', 'c'], {configuration: {'duplicate-arguments-array': false}})
parse.should.have.property('v').and.equal('c')
parse.should.have.property('_').with.length(0)
})
it('should default an array to an empty array if passed as first option followed by another', function () {
var result = parser(['-a', '-b'], {
array: 'a'
})
result.should.have.property('a').and.deep.equal([])
})
it('should not attempt to default array if an element has already been populated', function () {
var result = parser(['-a', 'foo', 'bar', '-b'], {
array: 'a'
})
result.should.have.property('a').and.deep.equal(['foo', 'bar'])
})
it('should default argument to empty array if no value given', function () {
var result = parser(['-b'], {
array: 'b'
})
result.should.have.property('b').and.deep.equal([])
})
it('should place value of argument in array, when one argument provided', function () {
var result = parser(['-b', '33'], {
array: ['b']
})
Array.isArray(result.b).should.equal(true)
result.b[0].should.equal(33)
})
it('should add multiple argument values to the array', function () {
var result = parser(['-b', '33', '-b', 'hello'], {
array: 'b'
})
Array.isArray(result.b).should.equal(true)
result.b.should.include(33)
result.b.should.include('hello')
})
it('should allow array: true, to be set inside an option block', function () {
var result = parser(['-b', '33'], {
array: 'b'
})
Array.isArray(result.b).should.equal(true)
result.b.should.include(33)
})
// issue #103
it('should default camel-case alias to array type', function () {
var result = parser(['--ca-path', 'http://www.example.com'], {
array: ['ca-path']
})
Array.isArray(result['ca-path']).should.equal(true)
Array.isArray(result.caPath).should.equal(true)
})
it('should default alias to array type', function () {
var result = parser(['--ca-path', 'http://www.example.com'], {
array: 'ca-path',
alias: {
'ca-path': 'c'
}
})
Array.isArray(result['ca-path']).should.equal(true)
Array.isArray(result.caPath).should.equal(true)
Array.isArray(result.c).should.equal(true)
})
// see: https://github.com/bcoe/yargs/issues/162
it('should eat non-hyphenated arguments until hyphenated option is hit', function () {
var result = parser(['-a=hello', 'world', '-b',
'33', '22', '--foo', 'red', 'green',
'--bar=cat', 'dog'], {
array: ['a', 'b', 'foo', 'bar']
})
Array.isArray(result.a).should.equal(true)
result.a.should.include('hello')
result.a.should.include('world')
Array.isArray(result.b).should.equal(true)
result.b.should.include(33)
result.b.should.include(22)
Array.isArray(result.foo).should.equal(true)
result.foo.should.include('red')
result.foo.should.include('green')
Array.isArray(result.bar).should.equal(true)
result.bar.should.include('cat')
result.bar.should.include('dog')
})
// see: https://github.com/yargs/yargs-parser/pull/13
it('should support array for --foo= format when the key is a number', function () {
var result = parser(['--1=a', 'b'], {
array: ['1']
})
Array.isArray(result['1']).should.equal(true)
result['1'][0].should.equal('a')
result['1'][1].should.equal('b')
})
})
describe('nargs', function () {
it('should allow the number of arguments following a key to be specified', function () {
var result = parser([ '--foo', 'apple', 'bar' ], {
narg: {
foo: 2
}
})
Array.isArray(result.foo).should.equal(true)
result.foo[0].should.equal('apple')
result.foo[1].should.equal('bar')
})
it('should raise an exception if there are not enough arguments following key', function () {
var argv = parser.detailed('--foo apple', {
narg: {
foo: 2
}
})
argv.error.message.should.equal('Not enough arguments following: foo')
})
it('nargs is applied to aliases', function () {
var result = parser(['--bar', 'apple', 'bar'], {
narg: {
foo: 2
},
alias: {
foo: 'bar'
}
})
Array.isArray(result.foo).should.equal(true)
result.foo[0].should.equal('apple')
result.foo[1].should.equal('bar')
})
it('should apply nargs to flag arguments', function () {
var result = parser([ '-f', 'apple', 'bar', 'blerg' ], {
narg: {
f: 2
}
})
result.f[0].should.equal('apple')
result.f[1].should.equal('bar')
result._[0].should.equal('blerg')
})
it('should support nargs for -f= and --bar= format arguments', function () {
var result = parser(['-f=apple', 'bar', 'blerg', '--bar=monkey', 'washing', 'cat'], {
narg: {
f: 2,
bar: 2
}
})
result.f[0].should.equal('apple')
result.f[1].should.equal('bar')
result._[0].should.equal('blerg')
result.bar[0].should.equal('monkey')
result.bar[1].should.equal('washing')
result._[1].should.equal('cat')
})
it('should not modify the input args if an = was used', function () {
var expected = ['-f=apple', 'bar', 'blerg', '--bar=monkey', 'washing', 'cat']
var args = expected.slice()
parser(args, {
narg: {
f: 2,
bar: 2
}
})
args.should.deep.equal(expected)
parser.detailed(args, {
narg: {
f: 2,
bar: 2
}
})
args.should.deep.equal(expected)
})
it('allows multiple nargs to be set at the same time', function () {
var result = parser([ '--foo', 'apple', 'bar', '--bar', 'banana', '-f' ], {
narg: {
foo: 2,
bar: 1
}
})
Array.isArray(result.foo).should.equal(true)
result.foo[0].should.equal('apple')
result.foo[1].should.equal('bar')
result.bar.should.equal('banana')
result.f.should.equal(true)
})
// see: https://github.com/yargs/yargs-parser/pull/13
it('should support nargs for --foo= format when the key is a number', function () {
var result = parser(['--1=a', 'b'], {
narg: {
1: 2
}
})
Array.isArray(result['1']).should.equal(true)
result['1'][0].should.equal('a')
result['1'][1].should.equal('b')
})
})
describe('env vars', function () {
it('should apply all env vars if prefix is empty', function () {
process.env.ONE_FISH = 'twofish'
process.env.RED_FISH = 'bluefish'
var result = parser([], {
envPrefix: ''
})
result.oneFish.should.equal('twofish')
result.redFish.should.equal('bluefish')
})
it('should apply only env vars matching prefix if prefix is valid string', function () {
process.env.ONE_FISH = 'twofish'
process.env.RED_FISH = 'bluefish'
process.env.GREEN_EGGS = 'sam'
process.env.GREEN_HAM = 'iam'
var result = parser([], {
envPrefix: 'GREEN'
})
result.eggs.should.equal('sam')
result.ham.should.equal('iam')
expect(result.oneFish).to.be.undefined // eslint-disable-line
expect(result.redFish).to.be.undefined // eslint-disable-line
})
it('should set aliases for options defined by env var', function () {
process.env.AIRFORCE_ONE = 'two'
var result = parser([], {
envPrefix: 'AIRFORCE',
alias: {
'1': ['one', 'uno']
}
})
result['1'].should.equal('two')
result.one.should.equal('two')
result.uno.should.equal('two')
})
it('should prefer command line value over env var', function () {
process.env.FOO_BAR = 'ignore'
var result = parser(['--foo-bar', 'baz'], {
envPrefix: ''
})
result.fooBar.should.equal('baz')
})
it('should respect type for args defined by env var', function () {
process.env.MY_TEST_STRING = '1'
process.env.MY_TEST_NUMBER = '2'
var result = parser([], {
string: 'string',
envPrefix: 'MY_TEST_'
})
result.string.should.equal('1')
result.number.should.equal(2)
})
it('should set option from aliased env var', function () {
process.env.SPACE_X = 'awesome'
var result = parser([], {
alias: {
xactly: 'x'
},
envPrefix: 'SPACE'
})
result.xactly.should.equal('awesome')
})
it('should prefer env var value over configured default', function () {
process.env.FOO_BALL = 'wut'
process.env.FOO_BOOL = 'true'
var result = parser([], {
envPrefix: 'FOO',
default: {
ball: 'baz',
bool: false
},
boolean: 'bool',
string: 'ball'
})
result.ball.should.equal('wut')
result.bool.should.equal(true)
})
var jsonPath = path.resolve(__dirname, './fixtures/config.json')
it('should prefer environment variables over config file', function () {
process.env.CFG_HERP = 'zerp'
var result = parser(['--cfg', jsonPath], {
envPrefix: 'CFG',
config: 'cfg',
string: 'herp',
default: {
herp: 'nerp'
}
})
result.herp.should.equal('zerp')
})
it('should support an env var value as config file option', function () {
process.env.TUX_CFG = jsonPath
var result = parser([], {
envPrefix: 'TUX',
config: ['cfg'],
default: {
z: 44
}
})
result.should.have.property('herp')
result.should.have.property('foo')
result.should.have.property('version')
result.should.have.property('truthy')
result.z.should.equal(55)
})
it('should prefer cli config file option over env var config file option', function () {
process.env.MUX_CFG = path.resolve(__dirname, '../package.json')
var result = parser(['--cfg', jsonPath], {
envPrefix: 'MUX',
config: 'cfg'
})
result.should.have.property('herp')
result.should.have.property('foo')
result.should.have.property('version')
result.should.have.property('truthy')
result.z.should.equal(55)
})
it('should apply all nested env vars', function () {
process.env.TEST_A = 'a'
process.env.TEST_NESTED_OPTION__FOO = 'baz'
process.env.TEST_NESTED_OPTION__BAR = 'bar'
var result = parser(['--nestedOption.foo', 'bar'], {
envPrefix: 'TEST'
})
result.should.have.property('a', 'a')
result.should.have.property('nestedOption').and.deep.equal({
foo: 'bar',
bar: 'bar'
})
})
it('should apply nested env var if argv value is using default value', function () {
process.env.TEST_A = 'a'
process.env.TEST_NESTED_OPTION__FOO = 'baz'
process.env.TEST_NESTED_OPTION__BAR = 'bar'
var result = parser([], {
envPrefix: 'TEST',
default: {
'nestedOption.foo': 'banana'
}
})
result.should.have.property('a', 'a')
result.should.have.property('nestedOption').and.deep.equal({
foo: 'baz',
bar: 'bar'
})
})
})
describe('configuration', function () {
describe('short option groups', function () {
it('allows short-option-groups to be disabled', function () {
var parse = parser(['-cats=meow'], {
configuration: {
'short-option-groups': false
}
})
parse.cats.should.equal('meow')
parse = parser(['-cats', 'meow'], {
configuration: {
'short-option-groups': false
}
})
parse.cats.should.equal('meow')
})
})
describe('camel-case expansion', function () {
it('does not expand camel-case aliases', function () {
var parsed = parser.detailed([], {
alias: {
'foo-bar': ['x']
},
configuration: {
'camel-case-expansion': false
}
})
expect(parsed.newAliases.fooBar).to.equal(undefined)
expect(parsed.aliases.fooBar).to.equal(undefined)
})
it('does not expand camel-case keys', function () {
var parsed = parser.detailed(['--foo-bar=apple'], {
configuration: {
'camel-case-expansion': false
}
})
expect(parsed.argv.fooBar).to.equal(undefined)
expect(parsed.argv['foo-bar']).to.equal('apple')
})
})
describe('dot notation', function () {
it('does not expand dot notation defaults', function () {
var parsed = parser([], {
default: {
'foo.bar': 'x'
},
configuration: {
'dot-notation': false
}
})
expect(parsed['foo.bar']).to.equal('x')
})
it('does not expand dot notation arguments', function () {
var parsed = parser(['--foo.bar', 'banana'], {
configuration: {
'dot-notation': false
}
})
expect(parsed['foo.bar']).to.equal('banana')
parsed = parser(['--foo.bar=banana'], {
configuration: {
'dot-notation': false
}
})
expect(parsed['foo.bar']).to.equal('banana')
})
it('should use value from cli, if cli overrides dot notation default', function () {
var parsed = parser(['--foo.bar', 'abc'], {
default: {
'foo.bar': 'default'
},
configuration: {
'dot-notation': false
}
})
expect(parsed['foo.bar']).to.equal('abc')
})
it('should also override dot notation alias', function () {
var parsed = parser(['--foo.bar', 'abc'], {
alias: {
'foo.bar': ['alias.bar']
},
default: {
'foo.bar': 'default'
},
configuration: {
'dot-notation': false
}
})
expect(parsed['alias.bar']).to.equal('abc')
})
it('does not expand alias of first element of dot notation arguments', function () {
var parsed = parser(['--foo.bar', 'banana'], {
alias: {
'foo': ['f']
},
configuration: {
'dot-notation': false
}
})
expect(parsed['foo.bar']).to.equal('banana')
expect(parsed).not.to.include.keys('f.bar')
})
// addresses https://github.com/yargs/yargs/issues/716
it('does not append nested-object keys from config to top-level key', function () {
var parsed = parser([], {
alias: {
'foo': ['f']
},
configuration: {
'dot-notation': false
},
configObjects: [
{
'website.com': {
a: 'b',
b: 'c'
}
}
]
})
parsed['website.com'].should.deep.equal({
a: 'b',
b: 'c'
})
})
})
describe('parse numbers', function () {
it('does not coerce defaults into numbers', function () {
var parsed = parser([], {
default: {
'foo': '5'
},
configuration: {
'parse-numbers': false
}
})
expect(parsed['foo']).to.equal('5')
})
it('does not coerce arguments into numbers', function () {
var parsed = parser(['--foo', '5'], {
configuration: {
'parse-numbers': false
}
})
expect(parsed['foo']).to.equal('5')
})
it('does not coerce positional arguments into numbers', function () {
var parsed = parser(['5'], {
configuration: {
'parse-numbers': false
}
})
expect(parsed._[0]).to.equal('5')
})
it('parses number if option explicitly set to number type', function () {
var parsed = parser(['--foo', '5', '--bar', '6'], {
number: 'bar',
configuration: {
'parse-numbers': false
}
})
expect(parsed['foo']).to.equal('5')
expect(parsed['bar']).to.equal(6)
})
})
describe('boolean negation', function () {
it('does not negate arguments prefixed with --no-', function () {
var parsed = parser(['--no-dice'], {
configuration: {
'boolean-negation': false
}
})
parsed['no-dice'].should.equal(true)
expect(parsed.dice).to.equal(undefined)
})
it('negates boolean arguments with correct prefix', function () {
var parsed = parser(['--foodice'], {
configuration: {
'negation-prefix': 'foo'
}
})
expect(parsed['dice']).to.equal(false)
})
})
describe('duplicate arguments array', function () {
it('adds duplicate argument to array', function () {
var parsed = parser('-x a -x b', {
configuration: {
'duplicate-arguments-array': true
}
})
parsed['x'].should.deep.equal(['a', 'b'])
})
it('keeps only last argument', function () {
var parsed = parser('-x a -x b', {
configuration: {
'duplicate-arguments-array': false
}
})
parsed['x'].should.equal('b')
})
})
describe('flatten duplicate arrays', function () {
it('flattens duplicate array type', function () {
var parsed = parser('-x a b -x c d', {
array: ['x'],
configuration: {
'flatten-duplicate-arrays': true
}
})
parsed['x'].should.deep.equal(['a', 'b', 'c', 'd'])
})
it('nests duplicate array types', function () {
var parsed = parser('-x a b -x c d', {
array: ['x'],
configuration: {
'flatten-duplicate-arrays': false
}
})
parsed['x'].should.deep.equal([['a', 'b'], ['c', 'd']])
})
it('doesn\'t nests single arrays', function () {
var parsed = parser('-x a b', {
array: ['x'],
configuration: {
'flatten-duplicate-arrays': false
}
})
parsed['x'].should.deep.equal(['a', 'b'])
})
it('flattens duplicate array type, when argument uses dot notation', function () {
var parsed = parser('-x.foo a -x.foo b', {
array: ['x.foo'],
configuration: {
'flatten-duplicate-arrays': true
}
})
parsed['x'].should.deep.equal({foo: ['a', 'b']})
})
})
describe('duplicate-arguments-array VS flatten-duplicate-arrays', function () {
/*
duplicate=false, flatten=false
type=array
[-x 1 2 3] => [1, 2, 3]
[-x 1 2 3 -x 2 3 4] => [2, 3, 4]
type=string/number/etc
[-x 1 -x 2 -x 3] => 3
duplicate=false, flatten=true
type=array
[-x 1 2 3] => [1, 2, 3]
[-x 1 2 3 -x 2 3 4] => [2, 3, 4]
type=string/number/etc
[-x 1 -x 2 -x 3] => 3
duplicate=true, flatten=true
type=array
[-x 1 2 3] => [1, 2, 3]
[-x 1 2 3 -x 2 3 4] => [1, 2, 3, 2, 3, 4]
type=string/number/etc
[-x 1 -x 2 -x 3] => [1, 2, 3]
duplicate=true, flatten=false
type=array
[-x 1 2 3] => [1, 2, 3]
[-x 1 2 3 -x 2 3 4] => [[1, 2, 3], [2, 3, 4]]
type=string/number/etc
[-x 1 -x 2 -x 3] => [1, 2, 3]
*/
describe('duplicate=false, flatten=false,', function () {
describe('type=array', function () {
it('[-x 1 2 3] => [1, 2, 3]', function () {
var parsed = parser('-x 1 2 3', {
array: ['x'],
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': false
}
})
parsed['x'].should.deep.equal([1, 2, 3])
})
it('[-x 1 2 3 -x 2 3 4] => [2, 3, 4]', function () {
var parsed = parser('-x 1 2 3 -x 2 3 4', {
array: ['x'],
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': false
}
})
parsed['x'].should.deep.equal([2, 3, 4])
})
})
describe('type=number', function () {
it('[-x 1 -x 2 -x 3] => 3', function () {
var parsed = parser('-x 1 -x 2 -x 3', {
number: 'x',
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': false
}
})
parsed['x'].should.deep.equal(3)
})
})
})
describe('duplicate=false, flatten=true,', function () {
describe('type=array', function () {
it('[-x 1 2 3] => [1, 2, 3]', function () {
var parsed = parser('-x 1 2 3', {
array: ['x'],
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': true
}
})
parsed['x'].should.deep.equal([1, 2, 3])
})
it('[-x 1 2 3 -x 2 3 4] => [2, 3, 4]', function () {
var parsed = parser('-x 1 2 3 -x 2 3 4', {
array: ['x'],
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': true
}
})
parsed['x'].should.deep.equal([2, 3, 4])
})
})
describe('type=number', function () {
it('[-x 1 -x 2 -x 3] => 3', function () {
var parsed = parser('-x 1 -x 2 -x 3', {
number: 'x',
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': true
}
})
parsed['x'].should.deep.equal(3)
})
})
})
describe('duplicate=true, flatten=true,', function () {
describe('type=array', function () {
it('[-x 1 2 3] => [1, 2, 3]', function () {
var parsed = parser('-x 1 2 3', {
array: ['x'],
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': true
}
})
parsed['x'].should.deep.equal([1, 2, 3])
})
it('[-x 1 2 3 -x 2 3 4] => [1, 2, 3, 2, 3, 4]', function () {
var parsed = parser('-x 1 2 3 -x 2 3 4', {
array: ['x'],
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': true
}
})
parsed['x'].should.deep.equal([1, 2, 3, 2, 3, 4])
})
})
describe('type=number', function () {
it('[-x 1 -x 2 -x 3] => [1, 2, 3]', function () {
var parsed = parser('-x 1 -x 2 -x 3', {
number: 'x',
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': true
}
})
parsed['x'].should.deep.equal([1, 2, 3])
})
})
})
describe('duplicate=true, flatten=false,', function () {
describe('type=array', function () {
it('[-x 1 -x 2 -x 3] => [1, 2, 3]', function () {
var parsed = parser('-x 1 -x 2 -x 3', {
array: ['x'],
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': false
}
})
parsed['x'].should.deep.equal([1, 2, 3])
})
it('[-x 1 2 3 -x 2 3 4] => [[1, 2, 3], [ 2, 3, 4]]', function () {
var parsed = parser('-x 1 2 3 -x 2 3 4', {
array: ['x'],
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': false
}
})
parsed['x'].should.deep.equal([[1, 2, 3], [2, 3, 4]])
})
})
describe('type=number', function () {
it('[-x 1 -x 2 -x 3] => [1, 2, 3]', function () {
var parsed = parser('-x 1 -x 2 -x 3', {
number: 'x',
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': false
}
})
parsed['x'].should.deep.equal([1, 2, 3])
})
})
})
})
describe('populate--', function () {
it('should populate "_" by default', function () {
var result = parser([
'bare',
'--', '-h', 'eek', '--'
])
result.should.have.property('_').and.deep.equal(['bare', '-h', 'eek', '--'])
result.should.not.have.property('--')
})
it('should populate the "--" if populate-- is "true"', function () {
var result = parser([
'--name=meowmers', 'bare', '-cats', 'woo', 'moxy',
'-h', 'awesome', '--multi=quux',
'--key', 'value',
'-b', '--bool', '--no-meep', '--multi=baz',
'--', '--not-a-flag', '-', '-h', '-multi', '--', 'eek'
], {
configuration: {
'populate--': true
}
})
result.should.have.property('c', true)
result.should.have.property('a', true)
result.should.have.property('t', true)
result.should.have.property('s', 'woo')
result.should.have.property('h', 'awesome')
result.should.have.property('b', true)
result.should.have.property('bool', true)
result.should.have.property('key', 'value')
result.should.have.property('multi').and.deep.equal(['quux', 'baz'])
result.should.have.property('meep', false)
result.should.have.property('name', 'meowmers')
result.should.have.property('_').and.deep.equal(['bare', 'moxy'])
result.should.have.property('--').and.deep.equal(['--not-a-flag', '-', '-h', '-multi', '--', 'eek'])
})
})
})
// addresses: https://github.com/yargs/yargs-parser/issues/41
it('defaults to empty array if array option is provided no values', function () {
var parsed = parser(['-f'], {
'alias': {
'f': 'files'
},
'array': ['files']
})
parsed.f.should.deep.equal([])
parsed.files.should.deep.equal([])
parsed = parser(['--files'], {
'alias': {
'f': 'files'
},
'array': ['files']
})
parsed.f.should.deep.equal([])
parsed.files.should.deep.equal([])
parsed = parser(['-f', '-y'], {
'alias': {
'f': 'files'
},
'array': ['files']
})
parsed.f.should.deep.equal([])
parsed.files.should.deep.equal([])
})
describe('coerce', function () {
it('applies coercion function to simple arguments', function () {
var parsed = parser(['--foo', '99'], {
coerce: {
foo: function (arg) {
return arg * -1
}
}
})
parsed.foo.should.equal(-99)
})
it('applies coercion function to aliases', function () {
var parsed = parser(['--foo', '99'], {
coerce: {
f: function (arg) {
return arg * -1
}
},
alias: {
f: ['foo']
}
})
parsed.foo.should.equal(-99)
parsed.f.should.equal(-99)
})
it('applies coercion function to all dot options', function () {
var parsed = parser(['--foo.bar', 'nananana'], {
coerce: {
foo: function (val) {
val.bar += ', batman!'
return val
}
}
})
parsed.foo.bar.should.equal('nananana, batman!')
})
it('applies coercion to defaults', function () {
var parsed = parser([], {
default: { foo: 'bar' },
coerce: {
foo: function (val) {
return val.toUpperCase()
}
}
})
parsed.foo.should.equal('BAR')
})
it('applies coercion function to an implicit array', function () {
var parsed = parser(['--foo', '99', '-f', '33'], {
coerce: {
f: function (arg) {
return arg.map(function (a) {
return a * -1
})
}
},
alias: {
f: ['foo']
}
})
parsed.f.should.deep.equal([-99, -33])
parsed.foo.should.deep.equal([-99, -33])
})
it('applies coercion function to an explicit array', function () {
var parsed = parser(['--foo', '99', '-f', '33'], {
coerce: {
f: function (arg) {
return arg.map(function (a) {
return a * -1
})
}
},
array: ['foo'],
alias: {
f: ['foo']
}
})
parsed.f.should.deep.equal([-99, -33])
parsed.foo.should.deep.equal([-99, -33])
})
it('applies coercion function to _', function () {
var parsed = parser(['99', '33'], {
coerce: {
_: function (arg) {
return arg.map(function (a) {
return a * -1
})
}
}
})
parsed._.should.deep.equal([-99, -33])
})
// see: https://github.com/yargs/yargs/issues/550
it('coercion function can be used to parse large #s', function () {
var fancyNumberParser = function (arg) {
if (arg.length > 10) return arg
else return parseInt(arg)
}
var parsed = parser(['--foo', '88888889999990000998989898989898', '--bar', '998'], {
coerce: {
foo: fancyNumberParser,
bar: fancyNumberParser
}
})
;(typeof parsed.foo).should.equal('string')
parsed.foo.should.equal('88888889999990000998989898989898')
;(typeof parsed.bar).should.equal('number')
parsed.bar.should.equal(998)
})
it('populates argv.error, if an error is thrown', function () {
var parsed = parser.detailed(['--foo', '99'], {
coerce: {
foo: function (arg) {
throw Error('banana')
}
}
})
parsed.error.message.should.equal('banana')
})
it('populates argv.error, if an error is thrown for an explicit array', function () {
var parsed = parser.detailed(['--foo', '99'], {
array: ['foo'],
coerce: {
foo: function (arg) {
throw Error('foo is array: ' + Array.isArray(arg))
}
}
})
parsed.error.message.should.equal('foo is array: true')
})
})
// see: https://github.com/yargs/yargs-parser/issues/37
it('normalizes all paths in array when provided via config object', function () {
var argv = parser([ '--foo', 'bar' ], {
array: ['a'],
normalize: ['a'],
configObjects: [{'a': ['bin/../a.txt', 'bin/../b.txt']}]
})
argv.a.should.deep.equal(['a.txt', 'b.txt'])
})
// see: https://github.com/yargs/yargs/issues/963
it('does not magically convert numeric strings larger than Number.MAX_SAFE_INTEGER', () => {
const argv = parser([ '--foo', '93940495950949399948393' ])
argv.foo.should.equal('93940495950949399948393')
})
it('converts numeric options larger than Number.MAX_SAFE_INTEGER to number', () => {
const argv = parser([ '--foo', '93940495950949399948393' ], {
number: ['foo']
})
argv.foo.should.equal(9.39404959509494e+22)
})
})
yargs-parser-8.0.0/yargs-logo.png 0000664 0000000 0000000 00000041431 13165347466 0016751 0 ustar 00root root 0000000 0000000 PNG
IHDR X bKGD pHYs gR tIME9_ iTXtComment Created with GIMPd.e IDATxwXoT]cM$^5$^@(U{K$ؖ;
b⦆b5Q).efy>ffϜo! :A&