Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7909cc4

Browse filesBrowse files
hendereaBenjamin E. Coe
authored andcommitted
feat: add configuration option to "collect-unknown-options" (#181)
1 parent d3d9027 commit 7909cc4
Copy full SHA for 7909cc4

File tree

Expand file treeCollapse file tree

3 files changed

+314
-55
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

3 files changed

+314
-55
lines changed
Open diff view settings
Collapse file

‎README.md‎

Copy file name to clipboardExpand all lines: README.md
+22Lines changed: 22 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,28 @@ node example.js --test-field 1
386386
{ _: [], testField: 1 }
387387
```
388388
389+
### collect unknown options
390+
391+
* default: `false`
392+
* key: `collect-unknown-options`
393+
394+
Should unknown options be collected into `_`? An unknown option is one that is not
395+
configured in `opts`.
396+
397+
_If disabled_
398+
399+
```sh
400+
node example.js --unknown-option --known-option 2
401+
{ _: [], unknownOption: true, knownOption: 2 }
402+
```
403+
404+
_If enabled_
405+
406+
```sh
407+
node example.js --unknown-option --known-option 2
408+
{ _: ['--unknown-option'], knownOption: 2 }
409+
```
410+
389411
## Special Thanks
390412
391413
The yargs project evolves from optimist and minimist. It owes its
Collapse file

‎index.js‎

Copy file name to clipboardExpand all lines: index.js
+73-2Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ function parse (args, opts) {
2626
'set-placeholder-key': false,
2727
'halt-at-non-option': false,
2828
'strip-aliased': false,
29-
'strip-dashed': false
29+
'strip-dashed': false,
30+
'collect-unknown-options': false
3031
}, opts.configuration)
3132
var defaults = opts.default || {}
3233
var configObjects = opts.configObjects || []
@@ -142,8 +143,10 @@ function parse (args, opts) {
142143
var next
143144
var value
144145

146+
if (configuration['collect-unknown-options'] && isUnknownOption(arg)) {
147+
argv._.push(arg)
145148
// -- separated by =
146-
if (arg.match(/^--.+=/) || (
149+
} else if (arg.match(/^--.+=/) || (
147150
!configuration['short-option-groups'] && arg.match(/^-.+=/)
148151
)) {
149152
// Using [\s\S] instead of . because js doesn't support the
@@ -757,6 +760,74 @@ function parse (args, opts) {
757760
return isSet
758761
}
759762

763+
function hasAnyFlag (key) {
764+
var isSet = false
765+
// XXX Switch to [].concat(...Object.values(flags)) once node.js 6 is dropped
766+
var toCheck = [].concat(...Object.keys(flags).map(k => flags[k]))
767+
768+
toCheck.forEach(function (flag) {
769+
if (flag[key]) isSet = flag[key]
770+
})
771+
772+
return isSet
773+
}
774+
775+
function hasFlagsMatching (arg, ...patterns) {
776+
var hasFlag = false
777+
var toCheck = [].concat(...patterns)
778+
toCheck.forEach(function (pattern) {
779+
var match = arg.match(pattern)
780+
if (match && hasAnyFlag(match[1])) {
781+
hasFlag = true
782+
}
783+
})
784+
return hasFlag
785+
}
786+
787+
// based on a simplified version of the short flag group parsing logic
788+
function hasAllShortFlags (arg) {
789+
// if this is a negative number, or doesn't start with a single hyphen, it's not a short flag group
790+
if (arg.match(negative) || !arg.match(/^-[^-]+/)) { return false }
791+
var hasAllFlags = true
792+
var letters = arg.slice(1).split('')
793+
var next
794+
for (var j = 0; j < letters.length; j++) {
795+
next = arg.slice(j + 2)
796+
797+
if (!hasAnyFlag(letters[j])) {
798+
hasAllFlags = false
799+
break
800+
}
801+
802+
if ((letters[j + 1] && letters[j + 1] === '=') ||
803+
next === '-' ||
804+
(/[A-Za-z]/.test(letters[j]) && /^-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) ||
805+
(letters[j + 1] && letters[j + 1].match(/\W/))) {
806+
break
807+
}
808+
}
809+
return hasAllFlags
810+
}
811+
812+
function isUnknownOption (arg) {
813+
// ignore negative numbers
814+
if (arg.match(negative)) { return false }
815+
// if this is a short option group and all of them are configured, it isn't unknown
816+
if (hasAllShortFlags(arg)) { return false }
817+
// e.g. '--count=2'
818+
const flagWithEquals = /^-+([^=]+?)=[\s\S]*$/
819+
// e.g. '-a' or '--arg'
820+
const normalFlag = /^-+([^=]+?)$/
821+
// e.g. '-a-'
822+
const flagEndingInHyphen = /^-+([^=]+?)-$/
823+
// e.g. '-abc123'
824+
const flagEndingInDigits = /^-+([^=]+?)\d+$/
825+
// e.g. '-a/usr/local'
826+
const flagEndingInNonWordCharacters = /^-+([^=]+?)\W+.*$/
827+
// check the different types of flag styles, including negatedBoolean, a pattern defined near the start of the parse method
828+
return !hasFlagsMatching(arg, flagWithEquals, negatedBoolean, normalFlag, flagEndingInHyphen, flagEndingInDigits, flagEndingInNonWordCharacters)
829+
}
830+
760831
// make a best effor to pick a default value
761832
// for an option based on name and type.
762833
function defaultValue (key) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.