From 1d4cca395a98b395e6318f0505fc73bef8b01350 Mon Sep 17 00:00:00 2001 From: "Benjamin E. Coe" Date: Tue, 18 Feb 2020 12:47:29 -0800 Subject: [PATCH 1/4] feat: introduces strictCommands() subset of strict mode (#1540) --- docs/api.md | 7 ++++ lib/validation.js | 26 ++++++++++++++ test/validation.js | 87 ++++++++++++++++++++++++++++++++++++++++++++++ yargs.js | 18 +++++++++- 4 files changed, 137 insertions(+), 1 deletion(-) diff --git a/docs/api.md b/docs/api.md index e6659dd79..9f55c0788 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1401,6 +1401,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. + .string(key) ------------ diff --git a/lib/validation.js b/lib/validation.js index 35659a356..5af0c724b 100644 --- a/lib/validation.js +++ b/lib/validation.js @@ -120,6 +120,32 @@ 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) { diff --git a/test/validation.js b/test/validation.js index e9dc0d65a..ebd7d7331 100644 --- a/test/validation.js +++ b/test/validation.js @@ -939,4 +939,91 @@ describe('validation tests', () => { .parse() }) }) + + describe('strictCommands', () => { + it('succeeds in parse if command is known', () => { + const parsed = yargs('foo -a 10') + .strictCommands() + .command('foo', 'foo command') + .parse() + parsed.a.should.equal(10) + parsed._.should.eql(['foo']) + }) + + it('succeeds in parse if top level and inner command are known', () => { + const parsed = yargs('foo bar --cool beans') + .strictCommands() + .command('foo', 'foo command', (yargs) => { + yargs.command('bar') + }) + .parse() + parsed.cool.should.equal('beans') + parsed._.should.eql(['foo', 'bar']) + }) + + it('fails with error if command is unknown', (done) => { + yargs('blerg -a 10') + .strictCommands() + .command('foo', 'foo command') + .fail((msg) => { + msg.should.equal('Unknown command: blerg') + return done() + }) + .parse() + }) + + it('fails with error if inner command is unknown', (done) => { + yargs('foo blarg --cool beans') + .strictCommands() + .command('foo', 'foo command', (yargs) => { + yargs.command('bar') + }) + .fail((msg) => { + msg.should.equal('Unknown command: blarg') + return done() + }) + .parse() + }) + + // TODO(bcoe): consider implementing this behvaior in the next major version of yargs: + // + // // for the special case of yargs.demandCommand() and yargs.demandCommand(1), if + // // yargs has been configured with commands, we automatically enable strictCommands. + // if (commandKeys.length && demandedCommands._ && demandedCommands._.min === 1 && demandedCommands._.max === Infinity) { + // yargs.strictCommands() + // } + // it('enables strict commands if commands used in conjunction with demandCommand', (done) => { + // yargs('blerg -a 10') + // .demandCommand() + // .command('foo', 'foo command') + // .fail((msg) => { + // msg.should.equal('Unknown command: blerg') + // return done() + // }) + // .parse() + // }) + + it('does not apply implicit strictCommands to inner commands', () => { + const parse = yargs('foo blarg --cool beans') + .demandCommand() + .command('foo', 'foo command', (yargs) => { + yargs.command('bar') + }) + .parse() + parse.cool.should.equal('beans') + parse._.should.eql(['foo', 'blarg']) + }) + + it('allows strictCommands to be applied to inner commands', (done) => { + yargs('foo blarg') + .command('foo', 'foo command', (yargs) => { + yargs.command('bar').strictCommands() + }) + .fail((msg) => { + msg.should.equal('Unknown command: blarg') + return done() + }) + .parse() + }) + }) }) diff --git a/yargs.js b/yargs.js index d9a30ac5b..238900f58 100644 --- a/yargs.js +++ b/yargs.js @@ -167,6 +167,7 @@ function Yargs (processArgs, cwd, parentRequire) { validation.freeze() command.freeze() frozen.strict = strict + frozen.strictCommands = strictCommands frozen.completionCommand = completionCommand frozen.output = output frozen.exitError = exitError @@ -190,6 +191,7 @@ function Yargs (processArgs, cwd, parentRequire) { validation.unfreeze() command.unfreeze() strict = frozen.strict + strictCommands = frozen.strictCommands completionCommand = frozen.completionCommand parseFn = frozen.parseFn parseContext = frozen.parseContext @@ -795,6 +797,14 @@ function Yargs (processArgs, cwd, parentRequire) { } self.getStrict = () => strict + let strictCommands = false + self.strictCommands = function (enabled) { + argsert('[boolean]', [enabled], arguments.length) + strictCommands = enabled !== false + return self + } + self.getStrictCommands = () => strictCommands + let parserConfig = {} self.parserConfiguration = function parserConfiguration (config) { argsert('', [config], arguments.length) @@ -1219,7 +1229,13 @@ function Yargs (processArgs, cwd, parentRequire) { if (parseErrors) throw new YError(parseErrors.message) validation.nonOptionCount(argv) validation.requiredArguments(argv) - if (strict) validation.unknownArguments(argv, aliases, positionalMap) + let failedStrictCommands = false + if (strictCommands) { + failedStrictCommands = validation.unknownCommands(argv, aliases, positionalMap) + } + if (strict && !failedStrictCommands) { + validation.unknownArguments(argv, aliases, positionalMap) + } validation.customChecks(argv, aliases) validation.limitedChoices(argv) validation.implications(argv) From 996329ba505b1b5131572f7e819778478ee5e955 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Feb 2020 14:39:59 -0800 Subject: [PATCH 2/4] chore(deps): update dependency standard to v14 (#1549) --- lib/apply-extends.js | 2 +- lib/command.js | 6 +++--- lib/usage.js | 8 ++++---- lib/validation.js | 22 +++++++++++----------- package.json | 2 +- test/command.js | 22 +++++++++++----------- test/completion.js | 4 ++-- test/helpers/utils.js | 2 +- test/integration.js | 22 +++++++++++----------- test/middleware.js | 22 +++++++++++----------- test/usage.js | 12 ++++++------ test/validation.js | 28 ++++++++++++++-------------- test/yargs.js | 6 +++--- yargs.js | 10 +++++----- 14 files changed, 84 insertions(+), 84 deletions(-) diff --git a/lib/apply-extends.js b/lib/apply-extends.js index 643c91335..6f2bb44bf 100644 --- a/lib/apply-extends.js +++ b/lib/apply-extends.js @@ -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 { diff --git a/lib/command.js b/lib/command.js index 7ee670a03..7678ae64e 100644 --- a/lib/command.js +++ b/lib/command.js @@ -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 diff --git a/lib/usage.js b/lib/usage.js index 2aeb7c7ea..02ddb030a 100644 --- a/lib/usage.js +++ b/lib/usage.js @@ -267,7 +267,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. @@ -526,9 +526,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 @@ -540,7 +540,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 diff --git a/lib/validation.js b/lib/validation.js index 5af0c724b..c81be368f 100644 --- a/lib/validation.js +++ b/lib/validation.js @@ -60,7 +60,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] } @@ -94,8 +94,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) @@ -149,12 +149,12 @@ module.exports = function validation (yargs, usage, y18n) { // 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 } } @@ -170,7 +170,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 && @@ -252,7 +252,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') { @@ -357,16 +357,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 diff --git a/package.json b/package.json index dde4c445b..f3471bd59 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "hashish": "0.0.4", "mocha": "^7.0.0", "rimraf": "^3.0.0", - "standard": "^12.0.1", + "standard": "^14.0.0", "which": "^2.0.0", "yargs-test-extends": "^1.0.1" }, diff --git a/test/command.js b/test/command.js index 87b098c65..9011759e0 100644 --- a/test/command.js +++ b/test/command.js @@ -154,13 +154,13 @@ describe('Command', () => { .command('foo [awesome...]', 'my awesome command', noop, (argv2) => { argv2.bar.should.eql('hello') argv2.awesome.should.eql(['world', 'series']) - argv2['_'].should.eql(['foo', 'apple', 'banana']) + argv2._.should.eql(['foo', 'apple', 'banana']) called = true }) .parse() argv.bar.should.eql('hello') argv.awesome.should.eql(['world', 'series']) - argv['_'].should.eql(['foo', 'apple', 'banana']) + argv._.should.eql(['foo', 'apple', 'banana']) called.should.equal(true) }) @@ -171,7 +171,7 @@ describe('Command', () => { .command('foo [awesome...]', 'my awesome command', noop, (argv2) => { argv2.bar.should.eql('hello') argv2.awesome.should.eql(['world', 'series']) - argv2['_'].should.eql(['foo']) + argv2._.should.eql(['foo']) argv2['--'].should.eql(['apple', 'banana']) called = true }) @@ -181,7 +181,7 @@ describe('Command', () => { .parse() argv.bar.should.eql('hello') argv.awesome.should.eql(['world', 'series']) - argv['_'].should.eql(['foo']) + argv._.should.eql(['foo']) argv['--'].should.eql(['apple', 'banana']) called.should.equal(true) }) @@ -612,7 +612,7 @@ describe('Command', () => { it('supports nested subcommands', () => { const r = checkOutput(() => yargs('dream --help').wrap(null) .commandDir('fixtures/cmddir') - .parse(), [ './command' ]) + .parse(), ['./command']) r.exit.should.equal(true) r.errors.length.should.equal(0) r.logs[0].split(/\n+/).should.deep.equal([ @@ -680,7 +680,7 @@ describe('Command', () => { it('detects and ignores cyclic dir references', () => { const r = checkOutput(() => yargs('cyclic --help').wrap(null) .commandDir('fixtures/cmddir_cyclic') - .parse(), [ './command' ]) + .parse(), ['./command']) r.exit.should.equal(true) r.errors.length.should.equal(0) r.should.have.property('logs') @@ -732,27 +732,27 @@ describe('Command', () => { const helpCmd = checkOutput(() => yargs('help cmd') .wrap(null) .command(cmd) - .parse(), [ './command' ]) + .parse(), ['./command']) const cmdHelp = checkOutput(() => yargs('cmd help') .wrap(null) .command(cmd) - .parse(), [ './command' ]) + .parse(), ['./command']) const helpCmdSub = checkOutput(() => yargs('help cmd sub') .wrap(null) .command(cmd) - .parse(), [ './command' ]) + .parse(), ['./command']) const cmdHelpSub = checkOutput(() => yargs('cmd help sub') .wrap(null) .command(cmd) - .parse(), [ './command' ]) + .parse(), ['./command']) const cmdSubHelp = checkOutput(() => yargs('cmd sub help') .wrap(null) .command(cmd) - .parse(), [ './command' ]) + .parse(), ['./command']) const expectedCmd = [ 'command cmd ', diff --git a/test/completion.js b/test/completion.js index fd777aecf..d6b919b0f 100644 --- a/test/completion.js +++ b/test/completion.js @@ -565,7 +565,7 @@ describe('Completion', () => { const r = checkUsage(() => { try { return yargs(['./completion', '--get-yargs-completions', '--']) - .option('foo', { 'describe': 'bar' }) + .option('foo', { describe: 'bar' }) .completion() .strict() .argv @@ -583,7 +583,7 @@ describe('Completion', () => { const r = checkUsage(() => { try { return yargs(['./completion', '--get-yargs-completions', 'dream']) - .commandDir('./fixtures/cmddir', { 'recurse': true }) + .commandDir('./fixtures/cmddir', { recurse: true }) .demand(1) .strict() .completion() diff --git a/test/helpers/utils.js b/test/helpers/utils.js index 76c09e7fe..7e21b8038 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -15,7 +15,7 @@ exports.checkOutput = function checkOutput (f, argv, cb) { process.exit = () => { exit = true } process.env = Hash.merge(process.env, { _: 'node' }) - process.argv = argv || [ './usage' ] + process.argv = argv || ['./usage'] const errors = [] const logs = [] diff --git a/test/integration.js b/test/integration.js index 1f4d0b370..bf4c9e1b6 100644 --- a/test/integration.js +++ b/test/integration.js @@ -16,7 +16,7 @@ describe('integration tests', () => { }) it('should run as a shell script with arguments', (done) => { - testArgs('./bin.js', [ 'a', 'b', 'c' ], done) + testArgs('./bin.js', ['a', 'b', 'c'], done) }) it('should run as a node script with no arguments', (done) => { @@ -24,7 +24,7 @@ describe('integration tests', () => { }) it('should run as a node script with arguments', (done) => { - testArgs('node bin.js', [ 'x', 'y', 'z' ], done) + testArgs('node bin.js', ['x', 'y', 'z'], done) }) describe('path returned by "which"', () => { @@ -40,14 +40,14 @@ describe('integration tests', () => { which('node', (err, resolvedPath) => { if (err) return done(err) testArgs(`${resolvedPath.replace('Program Files (x86)', 'Progra~2') - .replace('Program Files', 'Progra~1')} bin.js`, [ 'q', 'r' ], done) + .replace('Program Files', 'Progra~1')} bin.js`, ['q', 'r'], done) }) }) }) // see #177 it('allows --help to be completed without returning help message', (done) => { - testCmd('./bin.js', [ '--get-yargs-completions', '--h' ], (code, stdout) => { + testCmd('./bin.js', ['--get-yargs-completions', '--h'], (code, stdout) => { if (code) { done(new Error(`cmd exited with code ${code}`)) return @@ -66,7 +66,7 @@ describe('integration tests', () => { return this.skip() } - testCmd('./issue-497.js', [ '--help' ], (code, stdout) => { + testCmd('./issue-497.js', ['--help'], (code, stdout) => { if (code) { done(new Error(`cmd exited with code ${code}`)) return @@ -125,7 +125,7 @@ describe('integration tests', () => { describe('version #', () => { it('defaults to appropriate version # when yargs is installed normally', (done) => { - testCmd('./normal-bin.js', [ '--version' ], (code, stdout) => { + testCmd('./normal-bin.js', ['--version'], (code, stdout) => { if (code) { return done(new Error(`cmd exited with code ${code}`)) } @@ -136,7 +136,7 @@ describe('integration tests', () => { }) it('defaults to appropriate version # when yargs is symlinked', (done) => { - testCmd('./symlink-bin.js', [ '--version' ], (code, stdout) => { + testCmd('./symlink-bin.js', ['--version'], (code, stdout) => { if (code) { return done(new Error(`cmd exited with code ${code}`)) } @@ -149,7 +149,7 @@ describe('integration tests', () => { describe('parser settings', () => { it('reads parser config settings when yargs is installed normally', (done) => { - testCmd('./normal-bin.js', [ '--foo.bar' ], (code, stdout) => { + testCmd('./normal-bin.js', ['--foo.bar'], (code, stdout) => { if (code) { return done(new Error(`cmd exited with code ${code}`)) } @@ -160,7 +160,7 @@ describe('integration tests', () => { }) it('reads parser config settings when yargs is installed as a symlink', (done) => { - testCmd('./symlink-bin.js', [ '--foo.bar' ], (code, stdout) => { + testCmd('./symlink-bin.js', ['--foo.bar'], (code, stdout) => { if (code) { return done(new Error(`cmd exited with code ${code}`)) } @@ -171,7 +171,7 @@ describe('integration tests', () => { }) it('reads parser config settings when somebody obscures require.main', (done) => { - testCmd('./no-require-main.js', [ '--foo.bar' ], (code, stdout) => { + testCmd('./no-require-main.js', ['--foo.bar'], (code, stdout) => { if (code) { return done(new Error(`cmd exited with code ${code}`)) } @@ -182,7 +182,7 @@ describe('integration tests', () => { }) it('reads parser config settings when entry file has no extension', (done) => { - testCmd('./no-extension', [ '--foo.bar' ], (code, stdout) => { + testCmd('./no-extension', ['--foo.bar'], (code, stdout) => { if (code) { return done(new Error(`cmd exited with code ${code}`)) } diff --git a/test/middleware.js b/test/middleware.js index 5ea318935..1e059883f 100644 --- a/test/middleware.js +++ b/test/middleware.js @@ -118,7 +118,7 @@ describe('middleware', () => { const error = new Error() const handlerErr = new Error('should not have been called') yargs('foo') - .command('foo', 'foo command', () => {}, (argv) => done(handlerErr), [ (argv) => Promise.reject(error) ]) + .command('foo', 'foo command', () => {}, (argv) => done(handlerErr), [(argv) => Promise.reject(error)]) .fail((msg, err) => { expect(msg).to.equal(null) expect(err).to.equal(error) @@ -138,7 +138,7 @@ describe('middleware', () => { argv.hello.should.equal('world') argv.foo.should.equal('bar') done() - }, [ middleware('hello', 'world'), middleware('foo', 'bar') ]) + }, [middleware('hello', 'world'), middleware('foo', 'bar')]) .fail((msg, err) => { return done(Error('should not have been called')) }) @@ -148,7 +148,7 @@ describe('middleware', () => { it('calls an async middleware only once for nested subcommands', (done) => { let callCount = 0 - let argv = yargs('cmd subcmd') + const argv = yargs('cmd subcmd') .command( 'cmd', 'cmd command', @@ -274,9 +274,9 @@ describe('middleware', () => { 'mw', 'adds func to middleware', { - 'mw': { - 'demand': true, - 'string': true + mw: { + demand: true, + string: true } }, function (argv) { @@ -300,9 +300,9 @@ describe('middleware', () => { 'mw', 'adds func to middleware', { - 'mw': { - 'demand': true, - 'string': true + mw: { + demand: true, + string: true } }, function (argv) { @@ -346,8 +346,8 @@ describe('middleware', () => { 'mw', 'adds func to middleware', { - 'mw': { - 'demand': true + mw: { + demand: true } }, function (argv) { diff --git a/test/usage.js b/test/usage.js index d5408e96b..b4fd9dfb0 100644 --- a/test/usage.js +++ b/test/usage.js @@ -1007,8 +1007,8 @@ describe('usage tests', () => { const r = checkUsage(() => yargs('-y 10 -z 20') .usage('Usage: $0 -x NUM [-y NUM]') .options({ - 'x': { description: 'an option', demand: true }, - 'y': { description: 'another option', demand: false } + x: { description: 'an option', demand: true }, + y: { description: 'another option', demand: false } }) .wrap(null) .parse() @@ -1037,8 +1037,8 @@ describe('usage tests', () => { const r = checkUsage(() => yargs('-y 10 -z 20') .usage('Usage: $0 -x NUM [-y NUM]') .options({ - 'x': { description: 'an option', required: true }, - 'y': { description: 'another option', required: false } + x: { description: 'an option', required: true }, + y: { description: 'another option', required: false } }) .wrap(null) .parse() @@ -1066,8 +1066,8 @@ describe('usage tests', () => { const r = checkUsage(() => yargs('-w 10') .usage('Usage: $0 --width NUM [--height NUM]') .options({ - 'width': { description: 'Width', alias: 'w', demand: true }, - 'height': { description: 'Height', alias: 'h', demand: false } + width: { description: 'Width', alias: 'w', demand: true }, + height: { description: 'Height', alias: 'h', demand: false } }) .wrap(null) .parse() diff --git a/test/validation.js b/test/validation.js index ebd7d7331..bec119b3c 100644 --- a/test/validation.js +++ b/test/validation.js @@ -32,7 +32,7 @@ describe('validation tests', () => { yargs(['--foo']) .boolean('foo') .implies({ - 'foo': 1 // --foo means 1 arg in _ is required + foo: 1 // --foo means 1 arg in _ is required }) .fail((msg) => { msg.should.match(implicationsFailedPattern) @@ -74,7 +74,7 @@ describe('validation tests', () => { it('fails if a key is set, along with a key that it implies should not be set', (done) => { yargs(['--bar', '--foo']) .implies({ - 'bar': '--no-foo' // --bar means --foo cannot be given + bar: '--no-foo' // --bar means --foo cannot be given }) .fail((msg) => { msg.should.match(implicationsFailedPattern) @@ -87,7 +87,7 @@ describe('validation tests', () => { let failCalled = false yargs('--bar') .implies({ - 'bar': 'noFoo' // --bar means --noFoo (or --no-foo with boolean-negation disabled) is required + bar: 'noFoo' // --bar means --noFoo (or --no-foo with boolean-negation disabled) is required // note that this has nothing to do with --foo }) .fail((msg) => { @@ -102,7 +102,7 @@ describe('validation tests', () => { let failCalled = false const argv = yargs('--bar --noFoo') .implies({ - 'bar': 'noFoo' // --bar means --noFoo (or --no-foo with boolean-negation disabled) is required + bar: 'noFoo' // --bar means --noFoo (or --no-foo with boolean-negation disabled) is required // note that this has nothing to do with --foo }) .fail((msg) => { @@ -119,7 +119,7 @@ describe('validation tests', () => { let failCalled = false yargs('--bar --noFoo') .implies({ - 'bar': '--no-noFoo' // --bar means --noFoo (or --no-foo with boolean-negation disabled) cannot be given + bar: '--no-noFoo' // --bar means --noFoo (or --no-foo with boolean-negation disabled) cannot be given // note that this has nothing to do with --foo }) .fail((msg) => { @@ -134,7 +134,7 @@ describe('validation tests', () => { let failCalled = false const argv = yargs('--bar') .implies({ - 'bar': '--no-noFoo' // --bar means --noFoo (or --no-foo with boolean-negation disabled) cannot be given + bar: '--no-noFoo' // --bar means --noFoo (or --no-foo with boolean-negation disabled) cannot be given // note that this has nothing to do with --foo }) .fail((msg) => { @@ -231,8 +231,8 @@ describe('validation tests', () => { it('allows an object to be provided defining conflicting option pairs', (done) => { yargs(['-t', '-s']) .conflicts({ - 'c': 'a', - 's': 't' + c: 'a', + s: 't' }) .fail((msg) => { msg.should.equal('Arguments s and t are mutually exclusive') @@ -244,8 +244,8 @@ describe('validation tests', () => { it('takes into account aliases when applying conflicts logic', (done) => { yargs(['-t', '-c']) .conflicts({ - 'c': 'a', - 's': 't' + c: 'a', + s: 't' }) .alias('c', 's') .fail((msg) => { @@ -598,7 +598,7 @@ describe('validation tests', () => { .command('one', 'level one', (yargs) => { yargs .options({ - 'a': { + a: { demandOption: true, choices: [10, 20] } @@ -620,7 +620,7 @@ describe('validation tests', () => { .command('one', 'level one', (yargs) => { yargs .options({ - 'c': { + c: { choices: ['1', '2'] } }) @@ -641,7 +641,7 @@ describe('validation tests', () => { .command('one', 'level one', (yargs) => { yargs .options({ - 'a': { + a: { demandOption: false, choices: [10, 20] } @@ -661,7 +661,7 @@ describe('validation tests', () => { .command('one', 'level one', (yargs) => { yargs .options({ - 'a': { + a: { choices: [10, 20] } }) diff --git a/test/yargs.js b/test/yargs.js index 1ecea4c83..1c13791c6 100644 --- a/test/yargs.js +++ b/test/yargs.js @@ -34,7 +34,7 @@ describe('yargs dsl tests', () => { process.env._ = '/usr/local/bin/ndm' process.execPath = '/usr/local/bin/ndm' const argv = yargs([]).parse() - argv['$0'].should.equal('ndm') + argv.$0.should.equal('ndm') yargs.$0.should.equal('ndm') }) @@ -44,7 +44,7 @@ describe('yargs dsl tests', () => { process.defaultApp = false yargs = require('../') const argv = yargs.parse() - argv['f'].should.equal('toto') + argv.f.should.equal('toto') }) it('accepts an object for aliases', () => { @@ -865,7 +865,7 @@ describe('yargs dsl tests', () => { }) it('can be called multiple times with the same behavior', () => { - let counter = { foobar: 0 } + const counter = { foobar: 0 } yargs(['test', 'foobar']) .command( 'test ', diff --git a/yargs.js b/yargs.js index 238900f58..aa61db7a8 100644 --- a/yargs.js +++ b/yargs.js @@ -28,9 +28,9 @@ function Yargs (processArgs, cwd, parentRequire) { let command = null let completion = null let groups = {} - let globalMiddleware = [] + const globalMiddleware = [] let output = '' - let preservedGroups = {} + const preservedGroups = {} let usage = null let validation = null let handlerFinishCommand = null @@ -155,9 +155,9 @@ function Yargs (processArgs, cwd, parentRequire) { self.resetOptions() // temporary hack: allow "freezing" of reset-able state for parse(msg, cb) - let frozens = [] + const frozens = [] function freeze () { - let frozen = {} + const frozen = {} frozens.push(frozen) frozen.options = options frozen.configObjects = options.configObjects.slice(0) @@ -178,7 +178,7 @@ function Yargs (processArgs, cwd, parentRequire) { frozen.handlerFinishCommand = handlerFinishCommand } function unfreeze () { - let frozen = frozens.pop() + const frozen = frozens.pop() options = frozen.options options.configObjects = frozen.configObjects exitProcess = frozen.exitProcess From 94fa38cbab8d86943e87bf41d368ed56dffa6835 Mon Sep 17 00:00:00 2001 From: Mael Le Guen Date: Wed, 19 Feb 2020 00:36:55 +0100 Subject: [PATCH 3/4] fix(translations): fix pluralization in error messages. (#1557) --- lib/validation.js | 24 +++++++++++++++++--- locales/be.json | 10 +++++++-- locales/de.json | 10 +++++++-- locales/en.json | 10 +++++++-- locales/es.json | 10 +++++++-- locales/fi.json | 10 +++++++-- locales/fr.json | 56 +++++++++++++++++++++++++++------------------- locales/hi.json | 10 +++++++-- locales/hu.json | 10 +++++++-- locales/id.json | 10 +++++++-- locales/it.json | 10 +++++++-- locales/ja.json | 10 +++++++-- locales/ko.json | 10 +++++++-- locales/nb.json | 10 +++++++-- locales/nl.json | 10 +++++++-- locales/nn.json | 12 ++++++---- locales/pl.json | 10 +++++++-- locales/pt.json | 10 +++++++-- locales/pt_BR.json | 10 +++++++-- locales/ru.json | 10 +++++++-- locales/th.json | 10 +++++++-- locales/tr.json | 10 +++++++-- locales/zh_CN.json | 10 +++++++-- locales/zh_TW.json | 10 +++++++-- 24 files changed, 230 insertions(+), 72 deletions(-) diff --git a/lib/validation.js b/lib/validation.js index c81be368f..e960379cd 100644 --- a/lib/validation.js +++ b/lib/validation.js @@ -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) { @@ -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 + ) ) } } @@ -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 + ) ) } } diff --git a/locales/be.json b/locales/be.json index 141ebe1e1..332ef0a07 100644 --- a/locales/be.json +++ b/locales/be.json @@ -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" diff --git a/locales/de.json b/locales/de.json index 05d983737..8551e348d 100644 --- a/locales/de.json +++ b/locales/de.json @@ -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" diff --git a/locales/en.json b/locales/en.json index b32a63f27..a03c1388b 100644 --- a/locales/en.json +++ b/locales/en.json @@ -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" diff --git a/locales/es.json b/locales/es.json index d7c8af9f8..631a45c67 100644 --- a/locales/es.json +++ b/locales/es.json @@ -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" diff --git a/locales/fi.json b/locales/fi.json index 16acd12dc..e65beee80 100644 --- a/locales/fi.json +++ b/locales/fi.json @@ -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" diff --git a/locales/fr.json b/locales/fr.json index 3245e4e0a..82b3df401 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -1,38 +1,48 @@ { - "Commands:": "Commandes:", - "Options:": "Options:", - "Examples:": "Exemples:", + "Commands:": "Commandes :", + "Options:": "Options :", + "Examples:": "Exemples :", "boolean": "booléen", - "count": "comptage", - "string": "chaine de caractère", + "count": "compteur", + "string": "chaîne de caractères", "number": "nombre", "array": "tableau", "required": "requis", - "default:": "défaut:", - "choices:": "choix:", + "default:": "défaut :", + "choices:": "choix :", + "aliases:": "alias :", "generated-value": "valeur générée", - "Not enough non-option arguments: got %s, need at least %s": "Pas assez d'arguments non-option: reçu %s, besoin d'au moins %s", - "Too many non-option arguments: got %s, maximum of %s": "Trop d'arguments non-option: reçu %s, maximum %s", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Pas assez d'arguments (hors options) : reçu %s, besoin d'au moins %s", + "other": "Pas assez d'arguments (hors options) : reçus %s, besoin d'au moins %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Trop d'arguments (hors options) : reçu %s, maximum de %s", + "other": "Trop d'arguments (hors options) : reçus %s, maximum de %s" + }, "Missing argument value: %s": { - "one": "Argument manquant: %s", - "other": "Arguments manquants: %s" + "one": "Argument manquant : %s", + "other": "Arguments manquants : %s" }, "Missing required argument: %s": { - "one": "Argument requis manquant: %s", - "other": "Arguments requis manquants: %s" + "one": "Argument requis manquant : %s", + "other": "Arguments requis manquants : %s" }, "Unknown argument: %s": { - "one": "Argument inconnu: %s", - "other": "Arguments inconnus: %s" + "one": "Argument inconnu : %s", + "other": "Arguments inconnus : %s" }, - "Invalid values:": "Valeurs invalides:", - "Argument: %s, Given: %s, Choices: %s": "Argument: %s, Donné: %s, Choix: %s", - "Argument check failed: %s": "Echec de la vérification de l'argument: %s", - "Implications failed:": "Arguments dépendants manquants:", - "Not enough arguments following: %s": "Pas assez d'arguments suivant: %s", - "Invalid JSON config file: %s": "Fichier de configuration JSON invalide: %s", + "Invalid values:": "Valeurs invalides :", + "Argument: %s, Given: %s, Choices: %s": "Argument : %s, donné : %s, choix : %s", + "Argument check failed: %s": "Echec de la vérification de l'argument : %s", + "Implications failed:": "Arguments dépendants manquants :", + "Not enough arguments following: %s": "Pas assez d'arguments après : %s", + "Invalid JSON config file: %s": "Fichier de configuration JSON invalide : %s", "Path to JSON config file": "Chemin du fichier de configuration JSON", - "Show help": "Affiche de l'aide", + "Show help": "Affiche l'aide", "Show version number": "Affiche le numéro de version", - "Arguments %s and %s are mutually exclusive" : "Les arguments %s et %s sont mutuellement exclusifs" + "Did you mean %s?": "Vouliez-vous dire %s ?", + "Arguments %s and %s are mutually exclusive" : "Les arguments %s et %s sont mutuellement exclusifs", + "Positionals:": "Arguments positionnels :", + "command": "commande" } diff --git a/locales/hi.json b/locales/hi.json index 2cd677acb..021f005f8 100644 --- a/locales/hi.json +++ b/locales/hi.json @@ -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" diff --git a/locales/hu.json b/locales/hu.json index 7b7d16606..1ddad5cc9 100644 --- a/locales/hu.json +++ b/locales/hu.json @@ -12,8 +12,14 @@ "choices:": "lehetőségek:", "aliases:": "aliaszok:", "generated-value": "generált-érték", - "Not enough non-option arguments: got %s, need at least %s": "Nincs elég nem opcionális argumentum: %s van, legalább %s kell", - "Too many non-option arguments: got %s, maximum of %s": "Túl sok nem opciánlis argumentum van: %s van, maximum %s lehet", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Nincs elég nem opcionális argumentum: %s van, legalább %s kell", + "other": "Nincs elég nem opcionális argumentum: %s van, legalább %s kell" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Túl sok nem opciánlis argumentum van: %s van, maximum %s lehet", + "other": "Túl sok nem opciánlis argumentum van: %s van, maximum %s lehet" + }, "Missing argument value: %s": { "one": "Hiányzó argumentum érték: %s", "other": "Hiányzó argumentum értékek: %s" diff --git a/locales/id.json b/locales/id.json index 87e441cd8..075857e34 100644 --- a/locales/id.json +++ b/locales/id.json @@ -13,8 +13,14 @@ "aliases:": "istilah lain:", "choices:": "pilihan:", "generated-value": "nilai-yang-dihasilkan", - "Not enough non-option arguments: got %s, need at least %s": "Argumen wajib kurang: hanya %s, minimal %s", - "Too many non-option arguments: got %s, maximum of %s": "Terlalu banyak argumen wajib: ada %s, maksimal %s", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Argumen wajib kurang: hanya %s, minimal %s", + "other": "Argumen wajib kurang: hanya %s, minimal %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Terlalu banyak argumen wajib: ada %s, maksimal %s", + "other": "Terlalu banyak argumen wajib: ada %s, maksimal %s" + }, "Missing argument value: %s": { "one": "Kurang argumen: %s", "other": "Kurang argumen: %s" diff --git a/locales/it.json b/locales/it.json index 9ee900d34..ae61cc4a7 100644 --- a/locales/it.json +++ b/locales/it.json @@ -12,8 +12,14 @@ "choices:": "scelte:", "aliases:": "alias:", "generated-value": "valore generato", - "Not enough non-option arguments: got %s, need at least %s": "Numero insufficiente di argomenti non opzione: inseriti %s, richiesti almeno %s", - "Too many non-option arguments: got %s, maximum of %s": "Troppi argomenti non opzione: inseriti %s, massimo possibile %s", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Numero insufficiente di argomenti non opzione: inseriti %s, richiesti almeno %s", + "other": "Numero insufficiente di argomenti non opzione: inseriti %s, richiesti almeno %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Troppi argomenti non opzione: inseriti %s, massimo possibile %s", + "other": "Troppi argomenti non opzione: inseriti %s, massimo possibile %s" + }, "Missing argument value: %s": { "one": "Argomento mancante: %s", "other": "Argomenti mancanti: %s" diff --git a/locales/ja.json b/locales/ja.json index 64ee6d3fb..f7c96eedc 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -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" diff --git a/locales/ko.json b/locales/ko.json index 0eaeab2f8..a56fde92b 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -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" diff --git a/locales/nb.json b/locales/nb.json index 55be1fbed..7d5f73e9d 100644 --- a/locales/nb.json +++ b/locales/nb.json @@ -11,8 +11,14 @@ "default:": "standard:", "choices:": "valg:", "generated-value": "generert-verdi", - "Not enough non-option arguments: got %s, need at least %s": "Ikke nok ikke-alternativ argumenter: fikk %s, trenger minst %s", - "Too many non-option arguments: got %s, maximum of %s": "For mange ikke-alternativ argumenter: fikk %s, maksimum %s", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Ikke nok ikke-alternativ argumenter: fikk %s, trenger minst %s", + "other": "Ikke nok ikke-alternativ argumenter: fikk %s, trenger minst %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "For mange ikke-alternativ argumenter: fikk %s, maksimum %s", + "other": "For mange ikke-alternativ argumenter: fikk %s, maksimum %s" + }, "Missing argument value: %s": { "one": "Mangler argument verdi: %s", "other": "Mangler argument verdier: %s" diff --git a/locales/nl.json b/locales/nl.json index 5d62e0fc3..b42a323a9 100644 --- a/locales/nl.json +++ b/locales/nl.json @@ -12,8 +12,14 @@ "choices:": "keuzes:", "aliases:": "aliassen:", "generated-value": "gegenereerde waarde", - "Not enough non-option arguments: got %s, need at least %s": "Niet genoeg niet-optie-argumenten: %s gekregen, minstens %s nodig", - "Too many non-option arguments: got %s, maximum of %s": "Te veel niet-optie-argumenten: %s gekregen, maximum is %s", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Niet genoeg niet-optie-argumenten: %s gekregen, minstens %s nodig", + "other": "Niet genoeg niet-optie-argumenten: %s gekregen, minstens %s nodig" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Te veel niet-optie-argumenten: %s gekregen, maximum is %s", + "other": "Te veel niet-optie-argumenten: %s gekregen, maximum is %s" + }, "Missing argument value: %s": { "one": "Missende argumentwaarde: %s", "other": "Missende argumentwaarden: %s" diff --git a/locales/nn.json b/locales/nn.json index 5a3c9514d..545c0641d 100644 --- a/locales/nn.json +++ b/locales/nn.json @@ -11,10 +11,14 @@ "default:": "standard:", "choices:": "val:", "generated-value": "generert-verdi", - "Not enough non-option arguments: got %s, need at least %s": - "Ikkje nok ikkje-alternativ argument: fekk %s, treng minst %s", - "Too many non-option arguments: got %s, maximum of %s": - "For mange ikkje-alternativ argument: fekk %s, maksimum %s", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Ikkje nok ikkje-alternativ argument: fekk %s, treng minst %s", + "other": "Ikkje nok ikkje-alternativ argument: fekk %s, treng minst %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "For mange ikkje-alternativ argument: fekk %s, maksimum %s", + "other": "For mange ikkje-alternativ argument: fekk %s, maksimum %s" + }, "Missing argument value: %s": { "one": "Manglar argumentverdi: %s", "other": "Manglar argumentverdiar: %s" diff --git a/locales/pl.json b/locales/pl.json index 6926a4548..5f6c578e0 100644 --- a/locales/pl.json +++ b/locales/pl.json @@ -12,8 +12,14 @@ "choices:": "dostępne:", "aliases:": "aliasy:", "generated-value": "wygenerowana-wartość", - "Not enough non-option arguments: got %s, need at least %s": "Niewystarczająca ilość argumentów: otrzymano %s, wymagane co najmniej %s", - "Too many non-option arguments: got %s, maximum of %s": "Zbyt duża ilość argumentów: otrzymano %s, wymagane co najwyżej %s", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Niewystarczająca ilość argumentów: otrzymano %s, wymagane co najmniej %s", + "other": "Niewystarczająca ilość argumentów: otrzymano %s, wymagane co najmniej %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Zbyt duża ilość argumentów: otrzymano %s, wymagane co najwyżej %s", + "other": "Zbyt duża ilość argumentów: otrzymano %s, wymagane co najwyżej %s" + }, "Missing argument value: %s": { "one": "Brak wartości dla argumentu: %s", "other": "Brak wartości dla argumentów: %s" diff --git a/locales/pt.json b/locales/pt.json index 75c3921c8..78da747b1 100644 --- a/locales/pt.json +++ b/locales/pt.json @@ -11,8 +11,14 @@ "default:": "padrão:", "choices:": "escolhas:", "generated-value": "valor-gerado", - "Not enough non-option arguments: got %s, need at least %s": "Argumentos insuficientes não opcionais: Argumento %s, necessário pelo menos %s", - "Too many non-option arguments: got %s, maximum of %s": "Excesso de argumentos não opcionais: recebido %s, máximo de %s", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Argumentos insuficientes não opcionais: Argumento %s, necessário pelo menos %s", + "other": "Argumentos insuficientes não opcionais: Argumento %s, necessário pelo menos %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Excesso de argumentos não opcionais: recebido %s, máximo de %s", + "other": "Excesso de argumentos não opcionais: recebido %s, máximo de %s" + }, "Missing argument value: %s": { "one": "Falta valor de argumento: %s", "other": "Falta valores de argumento: %s" diff --git a/locales/pt_BR.json b/locales/pt_BR.json index 904cb66eb..eae1ec60d 100644 --- a/locales/pt_BR.json +++ b/locales/pt_BR.json @@ -12,8 +12,14 @@ "choices:": "opções:", "aliases:": "sinônimos:", "generated-value": "valor-gerado", - "Not enough non-option arguments: got %s, need at least %s": "Argumentos insuficientes: Argumento %s, necessário pelo menos %s", - "Too many non-option arguments: got %s, maximum of %s": "Excesso de argumentos: recebido %s, máximo de %s", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Argumentos insuficientes: Argumento %s, necessário pelo menos %s", + "other": "Argumentos insuficientes: Argumento %s, necessário pelo menos %s" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Excesso de argumentos: recebido %s, máximo de %s", + "other": "Excesso de argumentos: recebido %s, máximo de %s" + }, "Missing argument value: %s": { "one": "Falta valor de argumento: %s", "other": "Falta valores de argumento: %s" diff --git a/locales/ru.json b/locales/ru.json index cb7b88b49..c9001d1e9 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -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" diff --git a/locales/th.json b/locales/th.json index 3f08dcd23..250298beb 100644 --- a/locales/th.json +++ b/locales/th.json @@ -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" diff --git a/locales/tr.json b/locales/tr.json index 9b06c52a8..b9ad65f0e 100644 --- a/locales/tr.json +++ b/locales/tr.json @@ -12,8 +12,14 @@ "choices:": "seçimler:", "aliases:": "takma adlar:", "generated-value": "oluşturulan-değer", - "Not enough non-option arguments: got %s, need at least %s": "Seçenek dışı argümanlar yetersiz: %s bulundu, %s gerekli", - "Too many non-option arguments: got %s, maximum of %s": "Seçenek dışı argümanlar gereğinden fazla: %s bulundu, azami %s", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "Seçenek dışı argümanlar yetersiz: %s bulundu, %s gerekli", + "other": "Seçenek dışı argümanlar yetersiz: %s bulundu, %s gerekli" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "Seçenek dışı argümanlar gereğinden fazla: %s bulundu, azami %s", + "other": "Seçenek dışı argümanlar gereğinden fazla: %s bulundu, azami %s" + }, "Missing argument value: %s": { "one": "Eksik argüman değeri: %s", "other": "Eksik argüman değerleri: %s" diff --git a/locales/zh_CN.json b/locales/zh_CN.json index 03a3d94f0..4872a0954 100644 --- a/locales/zh_CN.json +++ b/locales/zh_CN.json @@ -11,8 +11,14 @@ "default:": "默认值:", "choices:": "可选值:", "generated-value": "生成的值", - "Not enough non-option arguments: got %s, need at least %s": "缺少 non-option 参数:传入了 %s 个, 至少需要 %s 个", - "Too many non-option arguments: got %s, maximum of %s": "non-option 参数过多:传入了 %s 个, 最大允许 %s 个", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "缺少 non-option 参数:传入了 %s 个, 至少需要 %s 个", + "other": "缺少 non-option 参数:传入了 %s 个, 至少需要 %s 个" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "non-option 参数过多:传入了 %s 个, 最大允许 %s 个", + "other": "non-option 参数过多:传入了 %s 个, 最大允许 %s 个" + }, "Missing argument value: %s": { "one": "没有给此选项指定值:%s", "other": "没有给这些选项指定值:%s" diff --git a/locales/zh_TW.json b/locales/zh_TW.json index 12498888a..c41a517d9 100644 --- a/locales/zh_TW.json +++ b/locales/zh_TW.json @@ -12,8 +12,14 @@ "choices:": "可選值:", "aliases:": "別名:", "generated-value": "生成的值", - "Not enough non-option arguments: got %s, need at least %s": "non-option 引數不足:只傳入了 %s 個, 至少要 %s 個", - "Too many non-option arguments: got %s, maximum of %s": "non-option 引數過多:傳入了 %s 個, 但最多 %s 個", + "Not enough non-option arguments: got %s, need at least %s": { + "one": "non-option 引數不足:只傳入了 %s 個, 至少要 %s 個", + "other": "non-option 引數不足:只傳入了 %s 個, 至少要 %s 個" + }, + "Too many non-option arguments: got %s, maximum of %s": { + "one": "non-option 引數過多:傳入了 %s 個, 但最多 %s 個", + "other": "non-option 引數過多:傳入了 %s 個, 但最多 %s 個" + }, "Missing argument value: %s": { "one": "此引數無指定值:%s", "other": "這些引數無指定值:%s" From a0b61ac21e2b554aa73dbf1a66d4a7af94047c2f Mon Sep 17 00:00:00 2001 From: Mael Le Guen Date: Thu, 20 Feb 2020 11:50:36 +0100 Subject: [PATCH 4/4] fix(yargs): correct support of bundled electron apps (#1554) --- lib/process-argv.js | 23 ++++++++++++++++++----- test/yargs.js | 29 +++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/lib/process-argv.js b/lib/process-argv.js index 691a6933f..bfe91534d 100644 --- a/lib/process-argv.js +++ b/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) } diff --git a/test/yargs.js b/test/yargs.js index 1c13791c6..a16946fe5 100644 --- a/test/yargs.js +++ b/test/yargs.js @@ -15,17 +15,19 @@ const noop = () => {} const implicationsFailedPattern = new RegExp(english['Implications failed:']) describe('yargs dsl tests', () => { - const oldProcess = {} + const oldProcess = { versions: {} } beforeEach(() => { oldProcess.argv = process.argv oldProcess.defaultApp = process.defaultApp + oldProcess.versions.electron = process.versions.electron yargs = require('../') }) afterEach(() => { process.argv = oldProcess.argv process.defaultApp = oldProcess.defaultApp + process.versions.electron = oldProcess.versions.electron delete require.cache[require.resolve('../')] }) @@ -38,13 +40,32 @@ describe('yargs dsl tests', () => { yargs.$0.should.equal('ndm') }) - it('should not remove the 1st argument of built electron apps', () => { + it('should not remove the 1st argument of bundled electron apps', () => { delete require.cache[require.resolve('../')] - process.argv = ['/usr/local/bin/app', '-f', 'toto'] - process.defaultApp = false + process.argv = ['/usr/local/bin/app', '-f', 'toto', 'tutu'] + process.versions.electron = '10.0.0-nightly.20200211' yargs = require('../') const argv = yargs.parse() + argv.should.have.property('f') argv.f.should.equal('toto') + argv._.should.deep.equal(['tutu']) + }) + + it('should remove the 1st argument of unbundled electron apps', () => { + delete require.cache[require.resolve('../')] + process.argv = ['/usr/local/bin/electron', 'app.js', '-f', 'toto', 'tutu'] + process.versions.electron = '10.0.0-nightly.20200211' + // Same syntax as in electron + Object.defineProperty(process, 'defaultApp', { + configurable: false, + enumerable: true, + value: true + }) + yargs = require('../') + const argv = yargs.parse() + argv.should.have.property('f') + argv.f.should.equal('toto') + argv._.should.deep.equal(['tutu']) }) it('accepts an object for aliases', () => {