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

Docs: calling .parse() is subtly different from .argv #1847

Closed
Hornwitser opened this issue Jan 3, 2021 · 4 comments
Closed

Docs: calling .parse() is subtly different from .argv #1847

Hornwitser opened this issue Jan 3, 2021 · 4 comments
Labels

Comments

@Hornwitser
Copy link

The API docs mentions that calling .parse() with no argument is equivalent to calling .argv. But during development of my app I found that not to be the case: The following code fails when using .argv but works as I expected it to when using .parse()

const yargs = require("yargs/yargs")(["foo"]);

yargs
    .command("foo")
    .option("blah")
    .help(false)
;

console.log(yargs.argv); // Prints { _: [ 'foo' ], '$0': 'test' }

yargs
    .command("bar")
    .help()
    .strict()
;

console.log(yargs.argv); // Prints help text and "Unknown argument: foo"

If .argv is replaced with .parse() in both instances then both logging statements prints { _: [ 'foo' ], '$0': 'test' }. This seems to have changed with #1369 where .parse() was extended to preserve state across multiple calls to it, while .argv does not preserve state.

It took me a long time to track down this issue, so I would really appreciate the docs for .argv being amended to say it destroys the state in the process and does not support being called multiple times as a result. And conversely for the docs to .parse() mention that it does support being called multiple times.

@bcoe bcoe added the docs label Jan 4, 2021
@shadowspawn
Copy link
Member

Firstly, .argv is being removed from the documentation. (So indirectly the problem with difference goes away!)

Secondly, there is some confusion in your description as to which behaviour parse and argv display, but I agree that .parse() works as for a single parse in this case and .argv does not. (Did you mean to to have bar in the second test in your example?)

To get consistent results in all circumstances I recommend making a new yargs instance for every test. For example:

const yargs = require("yargs/yargs");

const y1 = yargs(["foo"])
    .command("foo")
    .option("blah")
    .help(false)
;

console.log(y1.argv); // Prints { _: [ 'foo' ], '$0': 'test' }

const y2 = yargs(["foo"])
    .command("bar")
    .help()
    .strict()
;

console.log(y2.argv); // Prints help text and "Unknown argument: foo"

@Hornwitser
Copy link
Author

No, the code is as I intended to be, there's only one test case in it. One of the arguments to my app specifies a list of plugins to load and the plugins can add their own sub-commands to the command line interface. This means the command line first have to be parsed to figure out which plugins to load and then after plugins have loaded and added their own commands it's reparsed to get actual command intended.

@shadowspawn
Copy link
Member

shadowspawn commented Jul 22, 2023

Thanks for explanation. I was a bit confused about your intent, and I was a bit confused in my testing too!

Being more careful, I see same behaviour with your example code for .argv and .parse() with Yargs v17.7.2.

% node parse.js 
{ _: [ 'foo' ], '$0': 'parse.js' }
{ _: [ 'foo' ], '$0': 'parse.js' }

% node argv.js 
{ _: [ 'foo' ], '$0': 'argv.js' }
{ _: [ 'foo' ], '$0': 'argv.js' }

I think this was fixed in #1895. In the current code .argv is defined to call .parse().

// Legacy yargs.argv interface, it's recommended that you use .parse().
Object.defineProperty(yargs, 'argv', {
get: () => {
return yargs.parse();
},

@Hornwitser
Copy link
Author

If they act the same now then there's nothing to be done here. Thanks for letting me know.

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

3 participants