Skip to content

Commit

Permalink
Feature createOption (#1380)
Browse files Browse the repository at this point in the history
* Add createOption (like createCommand and createHelp)

* Add tests

* Add TypeScript

* option description is optional
  • Loading branch information
shadowspawn committed Oct 26, 2020
1 parent 033e6d9 commit b1d984b
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 8 deletions.
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

0 comments on commit b1d984b

Please sign in to comment.