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

Add combineFlagAndOptionalValue #1326

Merged
merged 4 commits into from Aug 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -114,6 +114,9 @@ If you use `program.args` or more complicated tests to detect a missing subcomma

If you use `.command('*')` to add a default command, you may be be able to switch to `isDefault:true` with a named command.

If you want to continue combining short options with optional values as though they were boolean flags, set `combineFlagAndOptionalValue(false)`
to expand `-fb` to `-f -b` rather than `-f b`.

## [5.0.0-4] (2020-03-03)

(Released in 5.0.0)
Expand Down
21 changes: 20 additions & 1 deletion index.js
Expand Up @@ -127,6 +127,7 @@ class Command extends EventEmitter {
this._defaultCommandName = null;
this._exitCallback = null;
this._aliases = [];
this._combineFlagAndOptionalValue = true;

this._hidden = false;
this._helpFlags = '-h, --help';
Expand Down Expand Up @@ -194,6 +195,7 @@ class Command extends EventEmitter {
cmd._exitCallback = this._exitCallback;
cmd._storeOptionsAsProperties = this._storeOptionsAsProperties;
cmd._passCommandToAction = this._passCommandToAction;
cmd._combineFlagAndOptionalValue = this._combineFlagAndOptionalValue;

cmd._executableFile = opts.executableFile || null; // Custom name for executable file, set missing to null to match constructor
this.commands.push(cmd);
Expand Down Expand Up @@ -636,6 +638,23 @@ Read more on https://git.io/JJc0W`);
return this._optionEx({ mandatory: true }, flags, description, fn, defaultValue);
};

/**
* Alter parsing of short flags with optional values.
*
* Examples:
*
* // for `.option('-f,--flag [value]'):
* .combineFlagAndOptionalValue(true) // `-f80` is treated like `--flag=80`, this is the default behaviour
* .combineFlagAndOptionalValue(false) // `-fb` is treated like `-f -b`
*
* @param {Boolean} [arg] - if `true` or omitted, an optional value can be specified directly after the flag.
* @api public
*/
combineFlagAndOptionalValue(arg) {
this._combineFlagAndOptionalValue = (arg === undefined) || arg;
return this;
};

/**
* Allow unknown options on the command line.
*
Expand Down Expand Up @@ -1109,7 +1128,7 @@ Read more on https://git.io/JJc0W`);
if (arg.length > 2 && arg[0] === '-' && arg[1] !== '-') {
const option = this._findOption(`-${arg[1]}`);
if (option) {
if (option.required || option.optional) {
if (option.required || (option.optional && this._combineFlagAndOptionalValue)) {
// option with value following in same argument
this.emit(`option:${option.name()}`, arg.slice(2));
} else {
Expand Down
21 changes: 21 additions & 0 deletions tests/command.parseOptions.test.js
Expand Up @@ -288,4 +288,25 @@ describe('Utility Conventions', () => {
expect(result).toEqual({ operands: [], unknown: ['--rrr=value'] });
expect(program.opts()).toEqual({ });
});

test('when program has combo optional and combineFlagAndOptionalValue() then treat as value', () => {
const program = createProgram();
program.combineFlagAndOptionalValue();
program.parseOptions(['-db']);
expect(program.opts()).toEqual({ ddd: 'b' });
});

test('when program has combo optional and combineFlagAndOptionalValue(true) then treat as value', () => {
const program = createProgram();
program.combineFlagAndOptionalValue(true);
program.parseOptions(['-db']);
expect(program.opts()).toEqual({ ddd: 'b' });
});

test('when program has combo optional and combineFlagAndOptionalValue(false) then treat as boolean', () => {
const program = createProgram();
program.combineFlagAndOptionalValue(false);
program.parseOptions(['-db']);
expect(program.opts()).toEqual({ ddd: true, bbb: true });
});
});
4 changes: 4 additions & 0 deletions typings/commander-tests.ts
Expand Up @@ -134,6 +134,10 @@ const storeOptionsAsPropertiesThis2: commander.Command = program.storeOptionsAsP
const passCommandToActionThis1: commander.Command = program.passCommandToAction();
const passCommandToActionThis2: commander.Command = program.passCommandToAction(false);

// combineFlagAndOptionalValue
const combineFlagAndOptionalValueThis1: commander.Command = program.combineFlagAndOptionalValue();
const combineFlagAndOptionalValueThis2: commander.Command = program.combineFlagAndOptionalValue(false);

// allowUnknownOption
const allowUnknownOptionThis1: commander.Command = program.allowUnknownOption();
const allowUnknownOptionThis2: commander.Command = program.allowUnknownOption(false);
Expand Down
12 changes: 12 additions & 0 deletions typings/index.d.ts
Expand Up @@ -201,6 +201,18 @@ declare namespace commander {
*/
passCommandToAction(value?: boolean): this;

/**
* Alter parsing of short flags with optional values.
*
* @example
* // for `.option('-f,--flag [value]'):
* .combineFlagAndOptionalValue(true) // `-f80` is treated like `--flag=80`, this is the default behaviour
* .combineFlagAndOptionalValue(false) // `-fb` is treated like `-f -b`
*
* @returns `this` command for chaining
*/
combineFlagAndOptionalValue(arg?: boolean): this;

/**
* Allow unknown options on the command line.
*
Expand Down