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

--no is bugged with default arguments #2068

Closed
Zamiell opened this issue Nov 8, 2023 · 4 comments
Closed

--no is bugged with default arguments #2068

Zamiell opened this issue Nov 8, 2023 · 4 comments

Comments

@Zamiell
Copy link

Zamiell commented Nov 8, 2023

Hello, and thanks for the useful library.

Consider the following program:

const { program } = require('commander');

program.option('--no-foo', true)
program.option('--no-bar', false)
program.parse();

const options = program.opts();
console.log(options)

Running this program will result in the following output:

{ foo: true, bar: true }

This is a bug, because commander.js is not using the default value that was specified. Specifically, I would expect specifying true for the default value of --no-foo would mean that false should be the default value of --foo, which means that the correct output should be:

{ foo: false, bar: true }

Additionally, I will say that I do not like the special/magic behavior of commander.js to invert my --no arguments. It makes for a more confusing code base, especially when bugs like the above exist! Is there some way to disable this special/magic behavior?

@shadowspawn
Copy link
Collaborator

Thanks for the example code.

You are missing the description argument in your example, so the true/false are being read as a description and not a default value.

Try:

program.option('--no-foo', 'foo description', true)
program.option('--no-bar', 'bar description', false)

Is there some way to disable this special/magic behavior?

No, it is a built-in feature which can not be disabled.

(I think you can flip the results by specifying both a default value and a preset value, but I suggest it is not worth the effort!)

@Zamiell
Copy link
Author

Zamiell commented Nov 9, 2023

Sorry about that. With the following program:

const { program } = require('commander');

program.option('--no-foo', 'foo description', true)
program.option('--no-bar', 'bar description', false)
program.parse();

const options = program.opts();
console.log(options)

I get the following output:

{ foo: true, bar: false }

However, as I said above, this output is a bug. Consider the following line:

program.option('--no-foo', 'foo description', true)

When translated to English, this line means: "By default, we want there to be no foo."
Thus, the output should be:

{ foo: false, bar: true }

I understand that Commander.js has magic behavior to transform no-foo --> foo, but this special behavior should also properly flip the default argument as well.

@shadowspawn
Copy link
Collaborator

I understand that Commander.js has magic behavior to transform no-foo --> foo, but this special behavior should also properly flip the default argument as well.

Here is another way of describing it. Adding an option with flags --no-foo creates an option named foo. Specifying a default value sets the starting value of option foo, just like with any other option.

I see your interpretation, but it isn't the only interpretation and I don't think is worth considering changing the behaviour. Not least because specifying a default value for a negated option is probably rare.

@Zamiell
Copy link
Author

Zamiell commented Nov 9, 2023

Ok, I will close this issue, thank you.

In the future, a way to disable the magic behavior would be welcome, I see that it was also previously requested here: #979

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants