diff --git a/index.js b/index.js index b7a18391..4fe26632 100644 --- a/index.js +++ b/index.js @@ -167,12 +167,10 @@ function parse (args, opts) { // arrays format = '--f=a b c' if (checkAllAliases(m[1], flags.arrays)) { - args.splice(i + 1, 0, m[2]) - i = eatArray(i, m[1], args) - } else if (checkAllAliases(m[1], flags.nargs)) { + i = eatArray(i, m[1], args, m[2]) + } else if (checkAllAliases(m[1], flags.nargs) !== false) { // nargs format = '--f=monkey washing cat' - args.splice(i + 1, 0, m[2]) - i = eatNargs(i, m[1], args) + i = eatNargs(i, m[1], args, m[2]) } else { setArg(m[1], m[2]) } @@ -241,12 +239,10 @@ function parse (args, opts) { if (checkAllAliases(key, flags.arrays)) { // array format = '-f=a b c' - args.splice(i + 1, 0, value) - i = eatArray(i, key, args) - } else if (checkAllAliases(key, flags.nargs)) { + i = eatArray(i, key, args, value) + } else if (checkAllAliases(key, flags.nargs) !== false) { // nargs format = '-f=monkey washing cat' - args.splice(i + 1, 0, value) - i = eatNargs(i, key, args) + i = eatNargs(i, key, args, value) } else { setArg(key, value) } @@ -364,7 +360,7 @@ function parse (args, opts) { // how many arguments should we consume, based // on the nargs option? - function eatNargs (i, key, args) { + function eatNargs (i, key, args, argAfterEqualSign) { let ii let toEat = checkAllAliases(key, flags.nargs) // NaN has a special meaning for the array type, indicating that one or @@ -372,14 +368,19 @@ function parse (args, opts) { toEat = isNaN(toEat) ? 1 : toEat if (toEat === 0) { + if (!isUndefined(argAfterEqualSign)) { + error = Error(__('Argument unexpected for: %s', key)) + } setArg(key, defaultValue(key)) return i } - let available = 0 + let available = isUndefined(argAfterEqualSign) ? 0 : 1 if (configuration['nargs-eats-options']) { // classic behavior, yargs eats positional and dash arguments. - if (args.length - (i + 1) < toEat) error = Error(__('Not enough arguments following: %s', key)) + if (args.length - (i + 1) + available < toEat) { + error = Error(__('Not enough arguments following: %s', key)) + } available = toEat } else { // nargs will not consume flag arguments, e.g., -abc, --foo, @@ -391,7 +392,11 @@ function parse (args, opts) { if (available < toEat) error = Error(__('Not enough arguments following: %s', key)) } - const consumed = Math.min(available, toEat) + let consumed = Math.min(available, toEat) + if (!isUndefined(argAfterEqualSign) && consumed > 0) { + setArg(key, argAfterEqualSign) + consumed-- + } for (ii = i + 1; ii < (consumed + i + 1); ii++) { setArg(key, args[ii]) } @@ -402,15 +407,16 @@ function parse (args, opts) { // 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) { + function eatArray (i, key, args, argAfterEqualSign) { let argsToSet = [] - let next = args[i + 1] + let next = argAfterEqualSign || args[i + 1] // If both array and nargs are configured, enforce the nargs count: const nargsCount = checkAllAliases(key, flags.nargs) if (checkAllAliases(key, flags.bools) && !(/^(true|false)$/.test(next))) { argsToSet.push(true) - } else if (isUndefined(next) || (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next))) { + } else if (isUndefined(next) || + (isUndefined(argAfterEqualSign) && /^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next))) { // for keys without value ==> argsToSet remains an empty [] // set user default value, if available if (defaults[key] !== undefined) { @@ -418,13 +424,17 @@ function parse (args, opts) { argsToSet = Array.isArray(defVal) ? defVal : [defVal] } } else { + // value in --option=value is eaten as is + if (!isUndefined(argAfterEqualSign)) { + argsToSet.push(processValue(key, argAfterEqualSign)) + } for (let ii = i + 1; ii < args.length; ii++) { + if ((!configuration['greedy-arrays'] && argsToSet.length > 0) || + (nargsCount && argsToSet.length >= nargsCount)) break next = args[ii] if (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next)) break i = ii argsToSet.push(processValue(key, next)) - if (!configuration['greedy-arrays'] || - (nargsCount && argsToSet.length >= nargsCount)) break } } diff --git a/test/yargs-parser.js b/test/yargs-parser.js index 217f188f..aa7399ee 100644 --- a/test/yargs-parser.js +++ b/test/yargs-parser.js @@ -1748,6 +1748,20 @@ describe('yargs-parser', function () { result['1'][1].should.equal('b') }) + it('should support array for -f= and --bar= format when the value is dashed', function () { + var result = parser(['-f=--dog', 'cat', '--bar=--red', 'green'], { + array: ['f', 'bar'] + }) + + Array.isArray(result.f).should.equal(true) + result.f[0].should.equal('--dog') + result.f[1].should.equal('cat') + + Array.isArray(result.bar).should.equal(true) + result.bar[0].should.equal('--red') + result.bar[1].should.equal('green') + }) + it('should create an array when passing an argument twice with same value', function () { var result = parser(['-x', 'val1', '-x', 'val1']) result.should.have.property('x').that.is.an('array').and.to.deep.equal(['val1', 'val1']) @@ -1869,6 +1883,24 @@ describe('yargs-parser', function () { result.foo[1].should.equal('bar') }) + it('should raise an exception if -f== format is used for a key with no expected argument', function () { + var argv = parser.detailed('-f=apple', { + narg: { + f: 0 + } + }) + argv.error.message.should.equal('Argument unexpected for: f') + }) + + it('should raise an exception if --bar== format is used for a key with no expected argument', function () { + var argv = parser.detailed('--bar=apple', { + narg: { + bar: 0 + } + }) + argv.error.message.should.equal('Argument unexpected for: bar') + }) + it('should raise an exception if there are not enough arguments following key', function () { var argv = parser.detailed('--foo apple', { narg: { @@ -1921,6 +1953,23 @@ describe('yargs-parser', function () { result._[1].should.equal('cat') }) + it('should support nargs for -f= and --bar= format arguments with dashed values', 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() @@ -3680,6 +3729,18 @@ describe('yargs-parser', function () { parse.error.message.should.equal('Not enough arguments following: a') }) + it('returns an error if not enough positionals were provided for nargs even with nargs-eats-options', () => { + var parse = parser.detailed(['-a', '33', '--cat'], { + narg: { + a: 3 + }, + configuration: { + 'nargs-eats-options': true + } + }) + parse.error.message.should.equal('Not enough arguments following: a') + }) + it('does not raise error if no arguments are provided for boolean option', () => { var parse = parser.detailed(['-a'], { array: 'a',