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

Regression: 15.2.0 ignores nargs for array #1570

Closed
kevinoid opened this issue Mar 1, 2020 · 9 comments
Closed

Regression: 15.2.0 ignores nargs for array #1570

kevinoid opened this issue Mar 1, 2020 · 9 comments
Labels

Comments

@kevinoid
Copy link

kevinoid commented Mar 1, 2020

Yargs 15.2.0 included an incompatible change in how nargs is handled for array options. For example, code for a repeatable option where the option should have a single argument on each occurrence (e.g. to behave like curl's --header option):

#!/usr/bin/env node
const yargs = require('yargs')
console.log(
  yargs
    .option('header', {
      requiresArg: true,
      array: true,
      nargs: 1
    })
    .argv
)

When invoked as ./example.js --header foo bar with yargs@15.1.0 this would print:

{ _: [ 'bar' ], header: [ 'foo' ], '$0': 'example.js' }

with yargs@15.2.0 this would print:

{ _: [], header: [ 'foo', 'bar' ], '$0': 'example.js' }

I bisected the change to b9409da (#1553) then to yargs/yargs-parser@4cbc188 as a result of #1098. I'm not sure if this is a bug in yargs-parser or if this is the intended behavior (in which case it might warrant a major version bump and some guidance about how to get the previous behavior).

Thanks for considering,
Kevin

@bcoe
Copy link
Member

bcoe commented Mar 1, 2020

My thinking on this regression is that using array and nargs in conjunction was never documented behavior, so much as a side effect folks found (I noticed mocha did this as well, so you're not alone).

I will look at adding this behavior back to yargs-parser, so that the next release of yargs doesn't need to be breaking, but I would rather that this behavior in the future was more explicit, with something like:

#!/usr/bin/env node
const yargs = require('yargs')
console.log(
  yargs
    .option('header', {
      array: true,
      demand: 1
    })
    .argv
)

In general I'm not happy with array parsing, and would like to move towards arrays not being "greedy" by default, see:

https://github.com/yargs/yargs-parser#greedy-arrays

Instead I would rather the default behavior is closer to what you're describing, mainly have a single argument on each occurrence, potentially with introducing a demand option which would require that an array be a certain size.

If we have this, I'm honestly tempted to drop the nargs feature in the next major version of yargs and yargs-parser.

@kevinoid
Copy link
Author

kevinoid commented Mar 1, 2020

Thanks for the detailed explanation @bcoe! Sounds great.

Setting 'greedy-arrays': false will work for me. I've only ever used arrays to combine repeated options, rather than multiple arguments to a single occurrence of an option, so making that the default and dropping nargs certainly fits my use cases.

Feel free to close this issue as you see fit. greedy-arrays should solve it for me.

@bcoe
Copy link
Member

bcoe commented Mar 1, 2020

@kevinoid I'm working on a fix right now, the problem with my wanting to drop nargs is we use this currently for requiresArg (which sets nargs of 1) which is where this bug comes from.

I had an idea I'm working on, if we make it set nargs of Infinity instead, and give Infinity a special meaning, I think we can support both behaviors.

@kevinoid
Copy link
Author

kevinoid commented Mar 1, 2020

I'm not sure I understand. Why does setting nargs: 1 cause it to consume both arguments instead of just 1?

@bcoe
Copy link
Member

bcoe commented Mar 1, 2020

@kevinoid we switched the parsing order to parse array then nargs, vs., nargs then array, to solve this bug. The array parsing logic doesn't, currently, have logic that terminates parsing after the nargs count is hit. However, if we were to implement this logic, we would break requiresArg (which sets nargs = 1).

If requiresArg instead set a special value, like NaN, then we could support both logical paths.

@kevinoid
Copy link
Author

kevinoid commented Mar 1, 2020

Gotcha. Thanks @bcoe!

@bcoe
Copy link
Member

bcoe commented Mar 8, 2020

@kevinoid can I bother you one more time to try npm i yargs@next, I think I might have squashed an additional bug.

@kevinoid
Copy link
Author

kevinoid commented Mar 8, 2020

Sure thing. In my testing yargs@next fixes this issue. It behaves like yargs@15.1.0 in the example code and passes the failing tests that drew my initial interest. Thanks @bcoe!

@bcoe
Copy link
Member

bcoe commented Mar 9, 2020

Fixed in latest version.

@bcoe bcoe closed this as completed Mar 9, 2020
kevinoid added a commit to kevinoid/swagger-spec-validator that referenced this issue Mar 9, 2020
To avoid a regression in 15.2.0 related to array+nargs for parsing -H.
See yargs/yargs#1570.

Fixes: #71

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants