Skip to content

Commit

Permalink
Merge branch 'master' into feat/deprecate-option
Browse files Browse the repository at this point in the history
  • Loading branch information
bcoe committed Feb 20, 2020
2 parents 3ef37c8 + a0b61ac commit 4c1ac6e
Show file tree
Hide file tree
Showing 39 changed files with 494 additions and 166 deletions.
7 changes: 7 additions & 0 deletions docs/api.md
Expand Up @@ -1439,6 +1439,13 @@ corresponding description, will be reported as an error.

Unrecognized commands will also be reported as errors.

.strictCommands([enabled=true])
---------

Similar to `.strict()`, except that it only applies to unrecognized commands. A
user can still provide arbitrary options, but unknown positional commands
will raise an error.

<a name="string"></a>.string(key)
------------

Expand Down
2 changes: 1 addition & 1 deletion lib/apply-extends.js
Expand Up @@ -20,7 +20,7 @@ function mergeDeep (config1, config2) {
const target = {}
const isObject = obj => obj && typeof obj === 'object' && !Array.isArray(obj)
Object.assign(target, config1)
for (let key of Object.keys(config2)) {
for (const key of Object.keys(config2)) {
if (isObject(config2[key]) && isObject(target[key])) {
target[key] = mergeDeep(config1[key], config2[key])
} else {
Expand Down
6 changes: 3 additions & 3 deletions lib/command.js
Expand Up @@ -443,16 +443,16 @@ module.exports = function command (yargs, usage, validation, globalMiddleware) {
// the state of commands such that
// we can apply .parse() multiple times
// with the same yargs instance.
let frozens = []
const frozens = []
self.freeze = () => {
let frozen = {}
const frozen = {}
frozens.push(frozen)
frozen.handlers = handlers
frozen.aliasMap = aliasMap
frozen.defaultCommand = defaultCommand
}
self.unfreeze = () => {
let frozen = frozens.pop()
const frozen = frozens.pop()
handlers = frozen.handlers
aliasMap = frozen.aliasMap
defaultCommand = frozen.defaultCommand
Expand Down
23 changes: 18 additions & 5 deletions lib/process-argv.js
@@ -1,12 +1,25 @@
function getProcessArgvBinIndex () {
// Built Electron app: app argv1 argv2 ... argvn
// (process.defaultApp is set to false by electron for built app for this purpose,
// see https://github.com/electron/electron/issues/4690#issuecomment-217435222)
if (process.defaultApp === false) return 0
// Default: node app.js argv1 argv2 ... argvn
// The binary name is the first command line argument for:
// - bundled Electron apps: bin argv1 argv2 ... argvn
if (isBundledElectronApp()) return 0
// or the second one (default) for:
// - standard node apps: node bin.js argv1 argv2 ... argvn
// - unbundled Electron apps: electron bin.js argv1 arg2 ... argvn
return 1
}

function isBundledElectronApp () {
// process.defaultApp is either set by electron in an electron unbundled app, or undefined
// see https://github.com/electron/electron/blob/master/docs/api/process.md#processdefaultapp-readonly
return isElectronApp() && !process.defaultApp
}

function isElectronApp () {
// process.versions.electron is either set by electron, or undefined
// see https://github.com/electron/electron/blob/master/docs/api/process.md#processversionselectron-readonly
return !!process.versions.electron
}

function getProcessArgvWithoutBin () {
return process.argv.slice(getProcessArgvBinIndex() + 1)
}
Expand Down
8 changes: 4 additions & 4 deletions lib/usage.js
Expand Up @@ -268,7 +268,7 @@ module.exports = function usage (yargs, y18n) {

// actually generate the switches string --foo, -f, --bar.
const switches = normalizedKeys.reduce((acc, key) => {
acc[key] = [ key ].concat(options.alias[key] || [])
acc[key] = [key].concat(options.alias[key] || [])
.map(sw => {
// for the special positional group don't
// add '--' or '-' prefix.
Expand Down Expand Up @@ -530,9 +530,9 @@ module.exports = function usage (yargs, y18n) {
return self
}

let frozens = []
const frozens = []
self.freeze = function freeze () {
let frozen = {}
const frozen = {}
frozens.push(frozen)
frozen.failMessage = failMessage
frozen.failureOutput = failureOutput
Expand All @@ -544,7 +544,7 @@ module.exports = function usage (yargs, y18n) {
frozen.descriptions = descriptions
}
self.unfreeze = function unfreeze () {
let frozen = frozens.pop()
const frozen = frozens.pop()
failMessage = frozen.failMessage
failureOutput = frozen.failureOutput
usages = frozen.usages
Expand Down
72 changes: 58 additions & 14 deletions lib/validation.js
Expand Up @@ -26,7 +26,13 @@ module.exports = function validation (yargs, usage, y18n) {
)
} else {
usage.fail(
__('Not enough non-option arguments: got %s, need at least %s', _s, demandedCommands._.min)
__n(
'Not enough non-option arguments: got %s, need at least %s',
'Not enough non-option arguments: got %s, need at least %s',
_s,
_s,
demandedCommands._.min
)
)
}
} else if (_s > demandedCommands._.max) {
Expand All @@ -37,7 +43,13 @@ module.exports = function validation (yargs, usage, y18n) {
)
} else {
usage.fail(
__('Too many non-option arguments: got %s, maximum of %s', _s, demandedCommands._.max)
__n(
'Too many non-option arguments: got %s, maximum of %s',
'Too many non-option arguments: got %s, maximum of %s',
_s,
_s,
demandedCommands._.max
)
)
}
}
Expand All @@ -49,7 +61,13 @@ module.exports = function validation (yargs, usage, y18n) {
self.positionalCount = function positionalCount (required, observed) {
if (observed < required) {
usage.fail(
__('Not enough non-option arguments: got %s, need at least %s', observed, required)
__n(
'Not enough non-option arguments: got %s, need at least %s',
'Not enough non-option arguments: got %s, need at least %s',
observed,
observed,
required
)
)
}
}
Expand All @@ -60,7 +78,7 @@ module.exports = function validation (yargs, usage, y18n) {
let missing = null

Object.keys(demandedOptions).forEach((key) => {
if (!argv.hasOwnProperty(key) || typeof argv[key] === 'undefined') {
if (!Object.prototype.hasOwnProperty.call(argv, key) || typeof argv[key] === 'undefined') {
missing = missing || {}
missing[key] = demandedOptions[key]
}
Expand Down Expand Up @@ -94,8 +112,8 @@ module.exports = function validation (yargs, usage, y18n) {

Object.keys(argv).forEach((key) => {
if (specialKeys.indexOf(key) === -1 &&
!positionalMap.hasOwnProperty(key) &&
!yargs._getParseContext().hasOwnProperty(key) &&
!Object.prototype.hasOwnProperty.call(positionalMap, key) &&
!Object.prototype.hasOwnProperty.call(yargs._getParseContext(), key) &&
!self.isValidAndSomeAliasIsNotNew(key, aliases)
) {
unknown.push(key)
Expand All @@ -120,15 +138,41 @@ module.exports = function validation (yargs, usage, y18n) {
}
}

self.unknownCommands = function unknownCommands (argv, aliases, positionalMap) {
const commandKeys = yargs.getCommandInstance().getCommands()
const unknown = []
const currentContext = yargs.getContext()

if ((currentContext.commands.length > 0) || (commandKeys.length > 0)) {
argv._.slice(currentContext.commands.length).forEach((key) => {
if (commandKeys.indexOf(key) === -1) {
unknown.push(key)
}
})
}

if (unknown.length > 0) {
usage.fail(__n(
'Unknown command: %s',
'Unknown commands: %s',
unknown.length,
unknown.join(', ')
))
return true
} else {
return false
}
}

// check for a key that is not an alias, or for which every alias is new,
// implying that it was invented by the parser, e.g., during camelization
self.isValidAndSomeAliasIsNotNew = function isValidAndSomeAliasIsNotNew (key, aliases) {
if (!aliases.hasOwnProperty(key)) {
if (!Object.prototype.hasOwnProperty.call(aliases, key)) {
return false
}
const newAliases = yargs.parsed.newAliases
for (let a of [key, ...aliases[key]]) {
if (!newAliases.hasOwnProperty(a) || !newAliases[key]) {
for (const a of [key, ...aliases[key]]) {
if (!Object.prototype.hasOwnProperty.call(newAliases, a) || !newAliases[key]) {
return true
}
}
Expand All @@ -144,7 +188,7 @@ module.exports = function validation (yargs, usage, y18n) {

Object.keys(argv).forEach((key) => {
if (specialKeys.indexOf(key) === -1 &&
options.choices.hasOwnProperty(key)) {
Object.prototype.hasOwnProperty.call(options.choices, key)) {
[].concat(argv[key]).forEach((value) => {
// TODO case-insensitive configurability
if (options.choices[key].indexOf(value) === -1 &&
Expand Down Expand Up @@ -226,7 +270,7 @@ module.exports = function validation (yargs, usage, y18n) {

function keyExists (argv, val) {
// convert string '1' to number 1
let num = Number(val)
const num = Number(val)
val = isNaN(num) ? val : num

if (typeof val === 'number') {
Expand Down Expand Up @@ -331,16 +375,16 @@ module.exports = function validation (yargs, usage, y18n) {
return self
}

let frozens = []
const frozens = []
self.freeze = function freeze () {
let frozen = {}
const frozen = {}
frozens.push(frozen)
frozen.implied = implied
frozen.checks = checks
frozen.conflicting = conflicting
}
self.unfreeze = function unfreeze () {
let frozen = frozens.pop()
const frozen = frozens.pop()
implied = frozen.implied
checks = frozen.checks
conflicting = frozen.conflicting
Expand Down
10 changes: 8 additions & 2 deletions locales/be.json
Expand Up @@ -12,8 +12,14 @@
"choices:": "магчымасці:",
"aliases:": "аліасы:",
"generated-value": "згенераванае значэнне",
"Not enough non-option arguments: got %s, need at least %s": "Недастаткова неапцыйных аргументаў: ёсць %s, трэба як мінімум %s",
"Too many non-option arguments: got %s, maximum of %s": "Занадта шмат неапцыйных аргументаў: ёсць %s, максімум дапушчальна %s",
"Not enough non-option arguments: got %s, need at least %s": {
"one": "Недастаткова неапцыйных аргументаў: ёсць %s, трэба як мінімум %s",
"other": "Недастаткова неапцыйных аргументаў: ёсць %s, трэба як мінімум %s"
},
"Too many non-option arguments: got %s, maximum of %s": {
"one": "Занадта шмат неапцыйных аргументаў: ёсць %s, максімум дапушчальна %s",
"other": "Занадта шмат неапцыйных аргументаў: ёсць %s, максімум дапушчальна %s"
},
"Missing argument value: %s": {
"one": "Не хапае значэння аргументу: %s",
"other": "Не хапае значэнняў аргументаў: %s"
Expand Down
10 changes: 8 additions & 2 deletions locales/de.json
Expand Up @@ -12,8 +12,14 @@
"choices:": "Möglichkeiten:",
"aliases:": "Aliase:",
"generated-value": "Generierter-Wert",
"Not enough non-option arguments: got %s, need at least %s": "Nicht genügend Argumente ohne Optionen: %s vorhanden, mindestens %s benötigt",
"Too many non-option arguments: got %s, maximum of %s": "Zu viele Argumente ohne Optionen: %s vorhanden, maximal %s erlaubt",
"Not enough non-option arguments: got %s, need at least %s": {
"one": "Nicht genügend Argumente ohne Optionen: %s vorhanden, mindestens %s benötigt",
"other": "Nicht genügend Argumente ohne Optionen: %s vorhanden, mindestens %s benötigt"
},
"Too many non-option arguments: got %s, maximum of %s": {
"one": "Zu viele Argumente ohne Optionen: %s vorhanden, maximal %s erlaubt",
"other": "Zu viele Argumente ohne Optionen: %s vorhanden, maximal %s erlaubt"
},
"Missing argument value: %s": {
"one": "Fehlender Argumentwert: %s",
"other": "Fehlende Argumentwerte: %s"
Expand Down
10 changes: 8 additions & 2 deletions locales/en.json
Expand Up @@ -12,8 +12,14 @@
"choices:": "choices:",
"aliases:": "aliases:",
"generated-value": "generated-value",
"Not enough non-option arguments: got %s, need at least %s": "Not enough non-option arguments: got %s, need at least %s",
"Too many non-option arguments: got %s, maximum of %s": "Too many non-option arguments: got %s, maximum of %s",
"Not enough non-option arguments: got %s, need at least %s": {
"one": "Not enough non-option arguments: got %s, need at least %s",
"other": "Not enough non-option arguments: got %s, need at least %s"
},
"Too many non-option arguments: got %s, maximum of %s": {
"one": "Too many non-option arguments: got %s, maximum of %s",
"other": "Too many non-option arguments: got %s, maximum of %s"
},
"Missing argument value: %s": {
"one": "Missing argument value: %s",
"other": "Missing argument values: %s"
Expand Down
10 changes: 8 additions & 2 deletions locales/es.json
Expand Up @@ -12,8 +12,14 @@
"choices:": "selección:",
"aliases:": "alias:",
"generated-value": "valor-generado",
"Not enough non-option arguments: got %s, need at least %s": "Hacen falta argumentos no-opcionales: Número recibido %s, necesita por lo menos %s",
"Too many non-option arguments: got %s, maximum of %s": "Demasiados argumentos no-opcionales: Número recibido %s, máximo es %s",
"Not enough non-option arguments: got %s, need at least %s": {
"one": "Hacen falta argumentos no-opcionales: Número recibido %s, necesita por lo menos %s",
"other": "Hacen falta argumentos no-opcionales: Número recibido %s, necesita por lo menos %s"
},
"Too many non-option arguments: got %s, maximum of %s": {
"one": "Demasiados argumentos no-opcionales: Número recibido %s, máximo es %s",
"other": "Demasiados argumentos no-opcionales: Número recibido %s, máximo es %s"
},
"Missing argument value: %s": {
"one": "Falta argumento: %s",
"other": "Faltan argumentos: %s"
Expand Down
10 changes: 8 additions & 2 deletions locales/fi.json
Expand Up @@ -12,8 +12,14 @@
"choices:": "vaihtoehdot:",
"aliases:": "aliakset:",
"generated-value": "generoitu-arvo",
"Not enough non-option arguments: got %s, need at least %s": "Liian vähän argumentteja, jotka eivät ole valintoja: annettu %s, vaaditaan vähintään %s",
"Too many non-option arguments: got %s, maximum of %s": "Liikaa argumentteja, jotka eivät ole valintoja: annettu %s, sallitaan enintään %s",
"Not enough non-option arguments: got %s, need at least %s": {
"one": "Liian vähän argumentteja, jotka eivät ole valintoja: annettu %s, vaaditaan vähintään %s",
"other": "Liian vähän argumentteja, jotka eivät ole valintoja: annettu %s, vaaditaan vähintään %s"
},
"Too many non-option arguments: got %s, maximum of %s": {
"one": "Liikaa argumentteja, jotka eivät ole valintoja: annettu %s, sallitaan enintään %s",
"other": "Liikaa argumentteja, jotka eivät ole valintoja: annettu %s, sallitaan enintään %s"
},
"Missing argument value: %s": {
"one": "Argumentin arvo puuttuu: %s",
"other": "Argumentin arvot puuttuvat: %s"
Expand Down

0 comments on commit 4c1ac6e

Please sign in to comment.