Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: NaN can now be provided as a value for nargs, indicating "at least" one value is expected for array #251

Merged
merged 1 commit into from Mar 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 12 additions & 5 deletions index.js
Expand Up @@ -361,7 +361,10 @@ function parse (args, opts) {
// on the nargs option?
function eatNargs (i, key, args) {
let ii
const toEat = checkAllAliases(key, flags.nargs)
let toEat = checkAllAliases(key, flags.nargs)
// NaN has a special meaning for the array type, indicating that one or
// more values are expected.
toEat = isNaN(toEat) ? 1 : toEat

if (toEat === 0) {
setArg(key, defaultValue(key))
Expand Down Expand Up @@ -397,6 +400,8 @@ function parse (args, opts) {
function eatArray (i, key, args) {
let argsToSet = []
let next = 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)
Expand All @@ -413,14 +418,16 @@ function parse (args, opts) {
if (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next)) break
i = ii
argsToSet.push(processValue(key, next))
if (!configuration['greedy-arrays']) break
if (!configuration['greedy-arrays'] ||
(nargsCount && argsToSet.length >= nargsCount)) break
}
}

// If both array and nargs are configured, create an error if less than
// nargs positionals were found:
const toEat = checkAllAliases(key, flags.nargs)
if (toEat && argsToSet.length < toEat) {
// nargs positionals were found. NaN has special meaning, indicating
// that at least one value is required (more are okay).
if ((nargsCount && argsToSet.length < nargsCount) ||
(isNaN(nargsCount) && argsToSet.length === 0)) {
error = Error(__('Not enough arguments following: %s', key))
}

Expand Down
49 changes: 43 additions & 6 deletions test/yargs-parser.js
Expand Up @@ -3565,28 +3565,65 @@ describe('yargs-parser', function () {
parse.infinite.should.equal(false)
})

// See: https://github.com/yargs/yargs/issues/1098
// See: https://github.com/yargs/yargs/issues/1098,
// https://github.com/yargs/yargs/issues/1570
describe('array with nargs', () => {
it('allows array and nargs to be configured in conjunction, enforcing the nargs value', () => {
var parse = parser(['-a', 'apple', 'banana'], {
var parse = parser.detailed(['-a', 'apple', 'banana'], {
array: 'a',
narg: {
a: 1
}
})
parse.a.should.eql(['apple', 'banana'])
expect(parse.error).to.be.null // eslint-disable-line
parse.argv.a.should.eql(['apple'])
parse.argv._.should.eql(['banana'])
})

it('returns an error if not enough positionals were provided for nargs', () => {
// see; https://github.com/yargs/yargs/issues/1098
it('allows special NaN count to be provided to narg, to indicate one or more array values', () => {
var parse = parser.detailed(['-a', 'apple', 'banana'], {
array: 'a',
narg: {
a: NaN
}
})
expect(parse.error).to.be.null // eslint-disable-line
parse.argv.a.should.eql(['apple', 'banana'])
})

it('throws error if at least one value not provided for NaN', () => {
var parse = parser.detailed(['-a'], {
array: 'a',
narg: {
a: 1
a: NaN
}
})
parse.error.message.should.match(/Not enough arguments/)
})

it('returns an error if not enough positionals were provided for nargs', () => {
var parse = parser.detailed(['-a', '33'], {
array: 'a',
narg: {
a: 2
}
})
parse.argv.a.should.eql([])
parse.argv.a.should.eql([33])
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',
boolean: 'a',
narg: {
a: NaN
}
})
expect(parse.error).to.be.null // eslint-disable-line
parse.argv.a.should.eql([true])
})
})

describe('greedy-arrays=false', () => {
Expand Down