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

Implement allowNegateOption. #1355

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 27 additions & 2 deletions index.js
Expand Up @@ -34,6 +34,13 @@ class Option {
}
this.description = description || '';
this.defaultValue = undefined;
this.negateOption = false;
}

allowNegateOption(allowNegateOption) {
allowNegateOption = (allowNegateOption === undefined) || allowNegateOption;
this.negateOption = !this.negate && this.long && !this.required && allowNegateOption;
mshima marked this conversation as resolved.
Show resolved Hide resolved
return this;
}

/**
Expand Down Expand Up @@ -112,6 +119,7 @@ class Command extends EventEmitter {
this.options = [];
this.parent = null;
this._allowUnknownOption = false;
this._implicitNegateOptions = false;
this._args = [];
this.rawArgs = null;
this._scriptPath = null;
Expand Down Expand Up @@ -491,7 +499,7 @@ Read more on https://git.io/JJc0W`);
*/

_optionEx(config, flags, description, fn, defaultValue) {
const option = new Option(flags, description);
const option = new Option(flags, description).allowNegateOption(this._implicitNegateOptions);
const oname = option.name();
const name = option.attributeName();
option.mandatory = !!config.mandatory;
Expand Down Expand Up @@ -669,6 +677,17 @@ Read more on https://git.io/JJc0W`);
return this;
};

/**
* Allow implicit negate value to options on the command line.
*
* @param {Boolean} [arg] - if `true` or omitted, a negate option will be accepted for non negative options with no value or non required values.
* @api public
*/
implicitNegateOptions(arg) {
this._implicitNegateOptions = (arg === undefined) || arg;
return this;
};

/**
* Whether to store option values as properties on command object,
* or store separately (specify false). In both cases the option values can be accessed using .opts().
Expand Down Expand Up @@ -1104,7 +1123,7 @@ Read more on https://git.io/JJc0W`);
activeVariadicOption = null;

if (maybeOption(arg)) {
const option = this._findOption(arg);
let option = this._findOption(arg);
// recognised option, call listener to assign value with possible custom processing
if (option) {
if (option.required) {
Expand All @@ -1123,6 +1142,12 @@ Read more on https://git.io/JJc0W`);
}
activeVariadicOption = option.variadic ? option : null;
continue;
} else if (arg.startsWith('--no-')) {
option = this._findOption(arg.replace(/^--no-/, '--'));
if (option && option.negateOption) {
this.emit(`option:${option.name()}`, false);
continue;
}
}
}

Expand Down
22 changes: 22 additions & 0 deletions tests/options.bool.test.js
Expand Up @@ -35,6 +35,16 @@ describe('boolean flag on program', () => {
program.parse(['node', 'test', '--no-cheese']);
expect(program.cheese).toBe(false);
});

test('when implicit negatable boolean flag specified then value is false', () => {
const program = new commander.Command();
program
.option('--cheese', 'add cheese')
._findOption('--cheese')
.allowNegateOption(true);
program.parse(['node', 'test', '--no-cheese']);
expect(program.cheese).toBe(false);
});
});

// boolean flag on command
Expand Down Expand Up @@ -82,6 +92,18 @@ describe('boolean flag on command', () => {
program.parse(['node', 'test', 'sub', '--no-cheese']);
expect(subCommand.cheese).toBe(false);
});

test('when implicit negatable boolean flag specified then value is false', () => {
let subCommand;
const program = new commander.Command();
program
.command('sub')
.implicitNegateOptions()
.option('--cheese', 'add cheese')
.action((cmd) => { subCommand = cmd; });
program.parse(['node', 'test', 'sub', '--no-cheese']);
expect(subCommand.cheese).toBe(false);
});
});

// This is a somewhat undocumented special behaviour which appears in some examples.
Expand Down