-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Open
Labels
enhancementpending releaseMerged into a branch for a future release, but not released yetMerged into a branch for a future release, but not released yetsemver: majorReleasing requires a major version bump, not backwards compatibleReleasing requires a major version bump, not backwards compatible
Description
Hey there! 👋
Thanks for this great library. I've been using it for years, and it's really amazing. :)
It would be really nice if the order in which options and their negations are specified didn't matter, since it's an invisible requirement that easily breaks when you want your options to be alphabetically sorted.
I was able to fix the issue with the patch below. Would something like this be considered for inclusion in the library? I can create a PR in that case, of course.
Thanks!
diff --git a/node_modules/commander/lib/command.js b/node_modules/commander/lib/command.js
index efbb8f6..5c74f6a 100644
--- a/node_modules/commander/lib/command.js
+++ b/node_modules/commander/lib/command.js
@@ -659,15 +659,43 @@ Expecting one of '${allowedValues.join("', '")}'`);
if (option.negate) {
// --no-foo is special and defaults foo to true, unless a --foo option is already defined
const positiveLongFlag = option.long.replace(/^--no-/, '--');
- if (!this._findOption(positiveLongFlag)) {
+ const positiveOption = this._findOption(positiveLongFlag);
+ if (!positiveOption) {
this.setOptionValueWithSource(
name,
option.defaultValue === undefined ? true : option.defaultValue,
'default',
);
+ } else {
+ // If positive option exists and was auto-defaulted to true due to this negative option being added later,
+ // remove that auto-default to prevent {foo: true} when neither --foo nor --no-foo is used
+ const positiveOptionName = positiveOption.attributeName();
+ if (this.getOptionValueSource(positiveOptionName) === 'default' &&
+ this.getOptionValue(positiveOptionName) === true &&
+ positiveOption.defaultValue === undefined) {
+ // Remove the auto-set default
+ delete this._optionValues[positiveOptionName];
+ delete this._optionValueSources[positiveOptionName];
+ }
}
} else if (option.defaultValue !== undefined) {
this.setOptionValueWithSource(name, option.defaultValue, 'default');
+ } else {
+ // Check if this positive option has a corresponding negative option that was added first
+ // and auto-set a default value. If so, remove that auto-default.
+ const negativeLongFlag = option.long ? option.long.replace(/^--/, '--no-') : null;
+ const negativeOption = negativeLongFlag && this._findOption(negativeLongFlag);
+ if (negativeOption && negativeOption.negate) {
+ // If we already have a default value set for this option due to the negative option,
+ // and the negative option didn't have an explicit default, remove the auto-default
+ if (this.getOptionValueSource(name) === 'default' &&
+ this.getOptionValue(name) === true &&
+ negativeOption.defaultValue === undefined) {
+ // Remove the auto-set default
+ delete this._optionValues[name];
+ delete this._optionValueSources[name];
+ }
+ }
}
// handler for cli and env supplied valuesMetadata
Metadata
Assignees
Labels
enhancementpending releaseMerged into a branch for a future release, but not released yetMerged into a branch for a future release, but not released yetsemver: majorReleasing requires a major version bump, not backwards compatibleReleasing requires a major version bump, not backwards compatible