-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
fixes behavior of --no-* options #795
Conversation
return this.long | ||
.replace('--', '') | ||
.replace('no-', ''); | ||
return this.long.replace(/^--/, ''); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: This may be a breaking change for people who use the (only recently-documented) Custom Event Listeners, though I can also clarify this by adding another illustrative example to the Readme in that section, if required.
Bump–@vanesyan, does this look OK for you? |
Yes, everything is ok for me, but cannot merge this until the next major bump as it's breaking change. |
339eb97
to
af89052
Compare
Good description of problem and changes, thanks @usmonster I am hopeful this will tidy up Also good catch that the JSDoc was claiming default value was true rather than undefined, oops. |
@usmonster The change to the custom event listener makes this a breaking change for a major version, so I have been working on some other pull requests first. Good to know you are still around and interested, makes this one high on my list. :-) |
(In top two of my PR queue. Hopefully take another look this week.) |
I have been trying all the permutations by running programs to check behaviour, as the code itself is quite subtle. One request, one comment, one thing I am still wondering about, one future change. (Sorry, I do some long comments!) Overall, I think this will make
const program = require("commander");
program
.option('-c, --cheese <type>', 'Add the specified type of cheese', "marble")
.option('-C, --no-cheese', 'You do not want any cheese')
.option('--what <type>')
.option('--no-what');
program.parse(process.argv);
console.log(`cheese is ${program.cheese}`);
console.log(`what is ${program.what}`);
|
Please, take a look at my comment here. |
Thanks for the comment, @slavafomin. I replied in the thread. Belated thanks, @shadowspawn, for the thorough review and feedback! No need to apologize for long comments, as they are appreciated. :) I'll reply to each below:
const handleWhat = function() {
// negate `what` if default isn't `true`
if ('WHAT' in process.env && process.env.WHAT !== 'true') {
this.what = !this.what;
}
};
program
.option('--what', 'enable on command line')
.option('--no-what', 'disable on command line')
.on('option:what', handleWhat)
.on('option:no-what', handleWhat)
.parse(process.argv);
console.log(`what is ${program.what}`); It can even be done without event listeners by doing the conditional reassignment at some point after the Thanks in advance for your feedback, especially on my question in point 3. :) |
a830068
to
0a2e760
Compare
e.g. https://eslint.org/docs/rules/guard-for-in
|
A bug existed whenever a "--no"-prefixed option was defined along with its counterpart (e.g. "--status" and "--no-status"), which caused the corresponding boolean attribute to always be `false` when either option was specified on the command line. This was because the definition of a negating option would overwrite the default value of the attribute, combined with the fact that specifying either option would emit two events with conflicting logic. This has been corrected in two ways: 1. During the setup of a negating option, we now check to see if the non-negated counterpart was already defined, in which case we don't set/overwrite the default value (which would be "true"); 2. An option's name no longer omits its negation prefix; that is, "--no-cheese" is internally "no-cheese", which will distinguish it from "--cheese"—this will allow unique events to be registered and emitted, depending on which option is passed to the command, thus avoiding any attribute assignment collision. Additionally, tests for negated options were added/updated to more explicitly demonstrate the expected behavior, and a couple of relevant examples were fixed to match their intended behavior.
0a2e760
to
26594fb
Compare
Thanks for switching base branch! I have not been asking people to do that in case it creates problems, but does make it easier for me. :-) |
Starting merge. |
Updated example and README with new improved behaviour, and added entries to CHANGELOG This is one of my favourite changes in v3. 😄 Thank you for your contributions. |
Thanks for your proactive involvement! |
Available now as a prerelease. See #1001 |
A bug existed whenever a
--no
-prefixed option was defined along withits counterpart (e.g.
--status
and--no-status
), which caused thecorresponding boolean attribute to always be
false
when either optionwas specified on the command line.
This was because the definition of a negating option would overwrite the
default value of the attribute, combined with the fact that specifying either
option would emit two events with conflicting logic.
This has been corrected in two ways:
non-negated counterpart was already defined, in which case we don't
set/overwrite the default value (which would otherwise be set to
true
);"--no-cheese" is now internally named
"no-cheese"
, which will distinguishit from "--cheese". This will allow unique listeners & events to be registered and
emitted, depending on which option is passed to the command, thus
avoiding any attribute assignment collision/race.
Additionally, the tests for negated options were updated to more
explicitly demonstrate the expected behavior, and a couple of relevant
examples were fixed to match their intended behavior.