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

Feature createOption #1380

Merged
merged 4 commits into from Oct 26, 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
29 changes: 22 additions & 7 deletions index.js
Expand Up @@ -58,11 +58,11 @@ class Help {
if (showShortHelpFlag || showLongHelpFlag) {
let helpOption;
if (!showShortHelpFlag) {
helpOption = new Option(cmd._helpLongFlag, cmd._helpDescription);
helpOption = cmd.createOption(cmd._helpLongFlag, cmd._helpDescription);
} else if (!showLongHelpFlag) {
helpOption = new Option(cmd._helpShortFlag, cmd._helpDescription);
helpOption = cmd.createOption(cmd._helpShortFlag, cmd._helpDescription);
} else {
helpOption = new Option(cmd._helpFlags, cmd._helpDescription);
helpOption = cmd.createOption(cmd._helpFlags, cmd._helpDescription);
}
visibleOptions.push(helpOption);
}
Expand Down Expand Up @@ -912,6 +912,21 @@ Read more on https://git.io/JJc0W`);
}
};

/**
* Factory routine to create a new unattached option.
*
* See .option() for creating an attached option, which uses this routine to
* create the option. You can override createOption to return a custom option.
*
* @param {string} flags
* @param {string} [description]
* @return {Option} new option
*/

createOption(flags, description) {
return new Option(flags, description);
};

/**
* Add an option.
*
Expand Down Expand Up @@ -991,7 +1006,7 @@ Read more on https://git.io/JJc0W`);
* @api private
*/
_optionEx(config, flags, description, fn, defaultValue) {
const option = new Option(flags, description);
const option = this.createOption(flags, description);
option.makeOptionMandatory(!!config.mandatory);
if (typeof fn === 'function') {
option.default(defaultValue).argParser(fn);
Expand Down Expand Up @@ -1055,7 +1070,7 @@ Read more on https://git.io/JJc0W`);
* program.option('-c, --cheese [type]', 'add cheese [marble]');
*
* @param {string} flags
* @param {string} description
* @param {string} [description]
* @param {Function|*} [fn] - custom option processing function or default value
* @param {*} [defaultValue]
* @return {Command} `this` command for chaining
Expand All @@ -1072,7 +1087,7 @@ Read more on https://git.io/JJc0W`);
* The `flags` string contains the short and/or long flags, separated by comma, a pipe or space.
*
* @param {string} flags
* @param {string} description
* @param {string} [description]
* @param {Function|*} [fn] - custom option processing function or default value
* @param {*} [defaultValue]
* @return {Command} `this` command for chaining
Expand Down Expand Up @@ -1720,7 +1735,7 @@ Read more on https://git.io/JJc0W`);
this._version = str;
flags = flags || '-V, --version';
description = description || 'output the version number';
const versionOption = new Option(flags, description);
const versionOption = this.createOption(flags, description);
this._versionOptionName = versionOption.attributeName();
this.options.push(versionOption);
this.on('option:' + versionOption.name(), () => {
Expand Down
42 changes: 42 additions & 0 deletions tests/command.createOption.test.js
@@ -0,0 +1,42 @@
const commander = require('../');

class MyOption extends commander.Option {
constructor(flags, description) {
super(flags, description);
this.myProperty = 'MyOption';
};
}

class MyCommand extends commander.Command {
createOption(flags, description) {
return new MyOption(flags, description);
};
}

test('when override createOption then used for option()', () => {
const program = new MyCommand();
program.option('-a, --alpha');
expect(program.options.length).toEqual(1);
expect(program.options[0].myProperty).toEqual('MyOption');
});

test('when override createOption then used for requiredOption()', () => {
const program = new MyCommand();
program.requiredOption('-a, --alpha');
expect(program.options.length).toEqual(1);
expect(program.options[0].myProperty).toEqual('MyOption');
});

test('when override createOption then used for version()', () => {
const program = new MyCommand();
program.version('1.2.3');
expect(program.options.length).toEqual(1);
expect(program.options[0].myProperty).toEqual('MyOption');
});

test('when override createOption then used for help option in visibleOptions', () => {
const program = new MyCommand();
const visibleOptions = program.createHelp().visibleOptions(program);
expect(visibleOptions.length).toEqual(1);
expect(visibleOptions[0].myProperty).toEqual('MyOption');
});
5 changes: 4 additions & 1 deletion typings/commander-tests.ts
Expand Up @@ -135,6 +135,10 @@ const requiredOptionThis9: commander.Command = program.requiredOption('-v, --ver
const requiredOptionThis10: commander.Command = program.requiredOption('-c, --collect <value>', 'repeatable value', collect, []);
const requiredOptionThis11: commander.Command = program.requiredOption('-l, --list <items>', 'comma separated list', commaSeparatedList);

// createOption
const createOption1: commander.Option = program.createOption('a, --alpha');
const createOption2: commander.Option = program.createOption('a, --alpha', 'description');

// addOption
const addOptionThis: commander.Command = program.addOption(new commander.Option('-s,--simple'));

Expand Down Expand Up @@ -234,7 +238,6 @@ const onThis: commander.Command = program.on('command:foo', () => {

// createCommand

const createInstance1: commander.Command = program.createCommand();
const createInstance2: commander.Command = program.createCommand('name');

class MyCommand extends commander.Command {
Expand Down
9 changes: 9 additions & 0 deletions typings/index.d.ts
Expand Up @@ -322,6 +322,15 @@ declare namespace commander {
/** @deprecated since v7, instead use choices or a custom function */
requiredOption(flags: string, description: string, regexp: RegExp, defaultValue?: string | boolean): this;

/**
* Factory routine to create a new unattached option.
*
* See .option() for creating an attached option, which uses this routine to
* create the option. You can override createOption to return a custom option.
*/

createOption(flags: string, description?: string): Option;

/**
* Add a prepared Option.
*
Expand Down