fixes behavior of --no-* options#795
Conversation
| return this.long | ||
| .replace('--', '') | ||
| .replace('no-', ''); | ||
| return this.long.replace(/^--/, ''); |
There was a problem hiding this comment.
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
|
|
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 |
|
Shipped in v3: https://github.com/tj/commander.js/releases/tag/v3.0.0 |
A bug existed whenever a
--no-prefixed option was defined along withits counterpart (e.g.
--statusand--no-status), which caused thecorresponding boolean attribute to always be
falsewhen 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.