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

Allow dynamically updating version number and version option flags and description #1933

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions lib/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ class Command extends EventEmitter {
this._helpCommandnameAndArgs = 'help [command]';
this._helpCommandDescription = 'display help for command';
this._helpConfiguration = {};

this._version = undefined;
this._versionOption = undefined;
}

/**
Expand Down Expand Up @@ -1559,10 +1562,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
// Preserve original behaviour so backwards compatible when still using properties
const result = {};
const len = this.options.length;
const versionOptionName = this._versionOption?.attributeName();

for (let i = 0; i < len; i++) {
const key = this.options[i].attributeName();
result[key] = key === this._versionOptionName ? this._version : this[key];
result[key] = key === versionOptionName ? this._version : this[key];
}
return result;
}
Expand Down Expand Up @@ -1807,24 +1811,31 @@ Expecting one of '${allowedValues.join("', '")}'`);
*
* You can optionally supply the flags and description to override the defaults.
*
* @param {string} str
* @param {string} [str]
* @param {string} [flags]
* @param {string} [description]
* @return {this | string} `this` command for chaining, or version string if no arguments
*/

version(str, flags, description) {
if (str === undefined) return this._version;
this._version = str;
flags = flags || '-V, --version';
description = description || 'output the version number';
const versionOption = this.createOption(flags, description);
this._versionOptionName = versionOption.attributeName();
this.options.push(versionOption);
this.on('option:' + versionOption.name(), () => {
this._outputConfiguration.writeOut(`${str}\n`);
this._exit(0, 'commander.version', str);
});
if (str === undefined && flags === undefined && description === undefined) {
return this._version;
}
if (str !== undefined) {
this._version = str;
}
if (!this._versionOption) {
flags = flags || '-V, --version';
description = description || 'output the version number';
this._versionOption = this.createOption(flags, description);
this.options.push(this._versionOption);
this.on('option:' + this._versionOption.name(), () => {
this._outputConfiguration.writeOut(`${this._version}\n`);
this._exit(0, 'commander.version', this._version);
});
} else {
this._versionOption.setFlagsAndDescription(flags, description);
}
return this;
}

Expand Down
60 changes: 46 additions & 14 deletions lib/option.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,8 @@ class Option {
*/

constructor(flags, description) {
this.flags = flags;
this.description = description || '';

this.required = flags.includes('<'); // A value must be supplied when the option is specified.
this.optional = flags.includes('['); // A value is optional when the option is specified.
// variadic test ignores <value,...> et al which might be used to describe custom splitting of single argument
this.variadic = /\w\.\.\.[>\]]$/.test(flags); // The option can take multiple values.
this.setFlagsAndDescription(flags, description);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was quite surprised this refactor did not break the typescript-checkJS run-script. At one time I am pretty sure we were getting errors for JavaScript properties which were not declared/set in the constructor.

TypeScript may have removed that check as too strict for real-world JavaScript.

microsoft/TypeScript#22896

this.mandatory = false; // The option must have a value after parsing, which usually means it must be specified on command line.
const optionFlags = splitOptionFlags(flags);
this.short = optionFlags.shortFlag;
this.long = optionFlags.longFlag;
this.negate = false;
if (this.long) {
this.negate = this.long.startsWith('--no-');
}
this.defaultValue = undefined;
this.defaultValueDescription = undefined;
this.presetArg = undefined;
Expand All @@ -37,6 +24,51 @@ class Option {
this.implied = undefined;
}

/**
* Set the option flags and description, if provided.
* Leave unchanged otherwise.
*
* @param {string} [flags]
* @param {string} [description]
*/

setFlagsAndDescription(flags, description) {
this.setFlags(flags);
this.setDescription(description);
}

/**
* Set the option flags, if provided.
* Leave unchanged otherwise.
*
* @param {string} [flags]
*/

setFlags(flags) {
if (flags !== undefined) {
this.flags = flags;
this.required = flags.includes('<'); // A value must be supplied when the option is specified.
this.optional = flags.includes('['); // A value is optional when the option is specified.
// variadic test ignores <value,...> et al which might be used to describe custom splitting of single argument
this.variadic = /\w\.\.\.[>\]]$/.test(flags); // The option can take multiple values.
const optionFlags = splitOptionFlags(flags);
this.short = optionFlags.shortFlag;
this.long = optionFlags.longFlag;
this.negate = this.long ? this.long.startsWith('--no-') : false;
}
}

/**
* Set the option description, if provided.
* Leave unchanged otherwise.
*
* @param {string} [description]
*/

setDescription(description) {
this.description = description || this.description || '';
}

/**
* Set the default value, and optionally supply the description to be displayed in the help.
*
Expand Down
2 changes: 1 addition & 1 deletion typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ export class Command {
*
* You can optionally supply the flags and description to override the defaults.
*/
version(str: string, flags?: string, description?: string): this;
version(str?: string, flags?: string, description?: string): this;

/**
* Define a command, implemented using an action handler.
Expand Down