Skip to content

Commit

Permalink
feat!: rework collect-unknown-options into `unknown-options-as-args…
Browse files Browse the repository at this point in the history
…`, providing more comprehensive functionality
  • Loading branch information
henderea authored and bcoe committed Oct 6, 2019
1 parent ac11361 commit ef771ca
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 37 deletions.
14 changes: 7 additions & 7 deletions README.md
Expand Up @@ -386,26 +386,26 @@ node example.js --test-field 1
{ _: [], testField: 1 }
```
### collect unknown options
### unknown options as args
* default: `false`
* key: `collect-unknown-options`
* key: `unknown-options-as-args`
Should unknown options be collected into `_`? An unknown option is one that is not
Should unknown options be treated like regular arguments? An unknown option is one that is not
configured in `opts`.
_If disabled_
```sh
node example.js --unknown-option --known-option 2
{ _: [], unknownOption: true, knownOption: 2 }
node example.js --unknown-option --known-option 2 --string-option --unknown-option2
{ _: [], unknownOption: true, knownOption: 2, stringOption: '', unknownOption2: true }
```
_If enabled_
```sh
node example.js --unknown-option --known-option 2
{ _: ['--unknown-option'], knownOption: 2 }
node example.js --unknown-option --known-option 2 --string-option --unknown-option2
{ _: ['--unknown-option'], knownOption: 2, stringOption: '--unknown-option2' }
```
## Special Thanks
Expand Down
29 changes: 13 additions & 16 deletions index.js
Expand Up @@ -27,7 +27,7 @@ function parse (args, opts) {
'halt-at-non-option': false,
'strip-aliased': false,
'strip-dashed': false,
'collect-unknown-options': false
'unknown-options-as-args': false
}, opts.configuration)
var defaults = opts.default || {}
var configObjects = opts.configObjects || []
Expand Down Expand Up @@ -143,7 +143,7 @@ function parse (args, opts) {
var next
var value

if (configuration['collect-unknown-options'] && isUnknownOption(arg)) {
if (isUnknownOptionAsArg(arg)) {
argv._.push(arg)
// -- separated by =
} else if (arg.match(/^--.+=/) || (
Expand Down Expand Up @@ -361,7 +361,7 @@ function parse (args, opts) {
// and terminates when one is observed.
var available = 0
for (ii = i + 1; ii < args.length; ii++) {
if (!args[ii].match(/^-[^0-9]/)) available++
if (!args[ii].match(/^-[^0-9]/) || isUnknownOptionAsArg(args[ii])) available++
else break
}

Expand All @@ -384,7 +384,7 @@ function parse (args, opts) {

if (checkAllAliases(key, flags.bools) && !(/^(true|false)$/.test(next))) {
argsToSet.push(true)
} else if (isUndefined(next) || (/^-/.test(next) && !negative.test(next))) {
} else if (isUndefined(next) || (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next))) {
// for keys without value ==> argsToSet remains an empty []
// set user default value, if available
if (defaults.hasOwnProperty(key)) {
Expand All @@ -393,7 +393,7 @@ function parse (args, opts) {
} else {
for (var ii = i + 1; ii < args.length; ii++) {
next = args[ii]
if (/^-/.test(next) && !negative.test(next)) break
if (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next)) break
i = ii
argsToSet.push(processValue(key, next))
}
Expand Down Expand Up @@ -761,27 +761,20 @@ function parse (args, opts) {
}

function hasAnyFlag (key) {
var isSet = false
// XXX Switch to [].concat(...Object.values(flags)) once node.js 6 is dropped
var toCheck = [].concat(...Object.keys(flags).map(k => flags[k]))

toCheck.forEach(function (flag) {
if (flag[key]) isSet = flag[key]
return toCheck.some(function (flag) {
return flag[key]
})

return isSet
}

function hasFlagsMatching (arg, ...patterns) {
var hasFlag = false
var toCheck = [].concat(...patterns)
toCheck.forEach(function (pattern) {
return toCheck.some(function (pattern) {
var match = arg.match(pattern)
if (match && hasAnyFlag(match[1])) {
hasFlag = true
}
return match && hasAnyFlag(match[1])
})
return hasFlag
}

// based on a simplified version of the short flag group parsing logic
Expand Down Expand Up @@ -809,6 +802,10 @@ function parse (args, opts) {
return hasAllFlags
}

function isUnknownOptionAsArg (arg) {
return configuration['unknown-options-as-args'] && isUnknownOption(arg)
}

function isUnknownOption (arg) {
// ignore negative numbers
if (arg.match(negative)) { return false }
Expand Down
68 changes: 54 additions & 14 deletions test/yargs-parser.js
Expand Up @@ -2690,12 +2690,12 @@ describe('yargs-parser', function () {
})
})

describe('collect-unknown-options = true', function () {
describe('unknown-options-as-args = true', function () {
it('should ignore unknown options in long format separated by =', function () {
const argv = parser('--known-arg=1 --unknown-arg=2', {
number: ['known-arg'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
Expand All @@ -2708,7 +2708,7 @@ describe('yargs-parser', function () {
const argv = parser('--no-known-arg --no-unknown-arg', {
boolean: ['known-arg'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
Expand All @@ -2721,7 +2721,7 @@ describe('yargs-parser', function () {
const argv = parser('--known-arg a --unknown-arg b', {
string: ['known-arg'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
Expand All @@ -2734,7 +2734,7 @@ describe('yargs-parser', function () {
const argv = parser('-k.arg=a -u.arg=b', {
string: ['k.arg'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
Expand All @@ -2748,7 +2748,7 @@ describe('yargs-parser', function () {
const argv = parser('-k.arg 1 -u.arg 2', {
number: ['k.arg'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
Expand All @@ -2762,7 +2762,7 @@ describe('yargs-parser', function () {
const argv = parser('-k=a -u=b', {
string: ['k'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
Expand All @@ -2774,7 +2774,7 @@ describe('yargs-parser', function () {
const argv = parser('-k- -u-', {
string: ['k'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
Expand All @@ -2786,19 +2786,59 @@ describe('yargs-parser', function () {
const argv = parser('-k 1 -u 2', {
number: ['k'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['-u', '2'],
'k': 1
})
})
it('should allow an unknown arg to be used as the value of another flag in short form', function () {
const argv = parser('-k -u', {
string: ['k'],
narg: { 'k': 1 },
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: [],
'k': '-u'
})
})
it('should allow an unknown arg to be used as the value of another flag in long form', function () {
const argv = parser('--known-arg --unknown-arg', {
string: ['known-arg'],
narg: { 'known-arg': 1 },
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: [],
'knownArg': '--unknown-arg',
'known-arg': '--unknown-arg'
})
})
it('should allow an unknown arg to be used as the value of another flag in array form', function () {
const argv = parser('--known-arg --unknown-arg1 --unknown-arg2', {
array: ['known-arg'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: [],
'knownArg': ['--unknown-arg1', '--unknown-arg2'],
'known-arg': ['--unknown-arg1', '--unknown-arg2']
})
})
it('should ignore unknown options in short format followed by a number', function () {
const argv = parser('-k1 -u2', {
number: ['k'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
Expand All @@ -2810,7 +2850,7 @@ describe('yargs-parser', function () {
const argv = parser('-k/1/ -u/2/', {
string: ['k'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
Expand All @@ -2822,7 +2862,7 @@ describe('yargs-parser', function () {
const argv = parser('-kuv', {
boolean: ['k', 'v'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
Expand All @@ -2833,7 +2873,7 @@ describe('yargs-parser', function () {
const argv = parser('-kv', {
boolean: ['k', 'v'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
Expand All @@ -2846,7 +2886,7 @@ describe('yargs-parser', function () {
const argv = parser('-k -33', {
boolean: ['k'],
configuration: {
'collect-unknown-options': true
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
Expand Down

0 comments on commit ef771ca

Please sign in to comment.