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 support for multiple aliases #1236

Merged
merged 5 commits into from
Apr 21, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 31 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class Command extends EventEmitter {
this._executableFile = null; // custom name for executable
this._defaultCommandName = null;
this._exitCallback = null;
this._alias = null;
this._aliases = [];

this._hidden = false;
this._helpFlags = '-h, --help';
Expand Down Expand Up @@ -937,7 +937,7 @@ class Command extends EventEmitter {
*/
_findCommand(name) {
if (!name) return undefined;
return this.commands.find(cmd => cmd._name === name || cmd._alias === name);
return this.commands.find(cmd => cmd._name === name || cmd._aliases.includes(name));
};

/**
Expand Down Expand Up @@ -1201,7 +1201,7 @@ class Command extends EventEmitter {
*
* @param {string} str
* @param {Object} [argsDescription]
* @return {String|Command}
* @return {string|Command}
* @api public
*/

Expand All @@ -1213,15 +1213,17 @@ class Command extends EventEmitter {
};

/**
* Set an alias for the command
* Set an alias for the command.
*
* @param {string} alias
* @return {String|Command}
* You may call more than once to add multiple aliases. Only the first alias is shown in the auto-generated help.
*
* @param {string} [alias]
* @return {string|Command}
* @api public
*/

alias(alias) {
if (alias === undefined) return this._alias;
if (alias === undefined) return this._aliases[0]; // just return first, for backwards compatibility

let command = this;
if (this.commands.length !== 0 && this.commands[this.commands.length - 1]._executableHandler) {
Expand All @@ -1231,7 +1233,25 @@ class Command extends EventEmitter {

if (alias === command._name) throw new Error('Command alias can\'t be the same as its name');

command._alias = alias;
command._aliases.push(alias);
return this;
};

/**
* Set aliases for the command.
*
* Only the first alias is shown in the auto-generated help.
*
* @param {string[]} [aliases]
* @return {string[]|Command}
* @api public
*/

aliases(aliases) {
// Getter for the array of aliases is the main reason for having aliases() in addition to alias().
if (aliases === undefined) return this._aliases;

shadowspawn marked this conversation as resolved.
Show resolved Hide resolved
aliases.forEach((alias) => this.alias(alias));
return this;
};

Expand Down Expand Up @@ -1290,7 +1310,7 @@ class Command extends EventEmitter {

return [
cmd._name +
(cmd._alias ? '|' + cmd._alias : '') +
(cmd._aliases[0] ? '|' + cmd._aliases[0] : '') +
(cmd.options.length ? ' [options]' : '') +
(args ? ' ' + args : ''),
cmd._description
Expand Down Expand Up @@ -1450,8 +1470,8 @@ class Command extends EventEmitter {
}

let cmdName = this._name;
if (this._alias) {
cmdName = cmdName + '|' + this._alias;
if (this._aliases[0]) {
cmdName = cmdName + '|' + this._aliases[0];
}
let parentCmdNames = '';
for (let parentCmd = this.parent; parentCmd; parentCmd = parentCmd.parent) {
Expand Down
55 changes: 54 additions & 1 deletion tests/command.alias.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,64 @@ test('when command has alias then appears in help', () => {
expect(helpInformation).toMatch('info|i');
});

test('when command = alias then error', () => {
test('when command has aliases added separately then only first appears in help', () => {
const program = new commander.Command();
program
.command('list [thing]')
.alias('ls')
.alias('dir');
const helpInformation = program.helpInformation();
expect(helpInformation).toMatch('list|ls ');
});

test('when command has aliases then only first appears in help', () => {
const program = new commander.Command();
program
.command('list [thing]')
.aliases(['ls', 'dir']);
const helpInformation = program.helpInformation();
expect(helpInformation).toMatch('list|ls ');
});

test('when command name = alias then error', () => {
const program = new commander.Command();
expect(() => {
program
.command('fail')
.alias('fail');
}).toThrow("Command alias can't be the same as its name");
});

test('when use alias then action handler called', () => {
const program = new commander.Command();
const actionMock = jest.fn();
program
.command('list')
.alias('ls')
.action(actionMock);
program.parse(['ls'], { from: 'user' });
expect(actionMock).toHaveBeenCalled();
});

test('when use second alias added separately then action handler called', () => {
const program = new commander.Command();
const actionMock = jest.fn();
program
.command('list')
.alias('ls')
.alias('dir')
.action(actionMock);
program.parse(['dir'], { from: 'user' });
expect(actionMock).toHaveBeenCalled();
});

test('when use second of aliases then action handler called', () => {
const program = new commander.Command();
const actionMock = jest.fn();
program
.command('list')
.aliases(['ls', 'dir'])
.action(actionMock);
program.parse(['dir'], { from: 'user' });
expect(actionMock).toHaveBeenCalled();
});
4 changes: 4 additions & 0 deletions typings/commander-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ const descriptionValue: string = program.description();
const aliasThis: commander.Command = program.alias('my alias');
const aliasValue: string = program.alias();

// aliases
const aliasesThis: commander.Command = program.aliases(['first-alias', 'second-alias']);
const aliasesValue: string[] = program.aliases();

// usage
const usageThis: commander.Command = program.usage('my usage');
const usageValue: string = program.usage();
Expand Down
15 changes: 15 additions & 0 deletions typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ declare namespace commander {
/**
* Set an alias for the command.
*
* You may call more than once to add multiple aliases. Only the first alias is shown in the auto-generated help.
*
* @returns `this` command for chaining
*/
alias(alias: string): this;
Expand All @@ -283,6 +285,19 @@ declare namespace commander {
*/
alias(): string;

/**
* Set aliases for the command.
*
* Only the first alias is shown in the auto-generated help.
*
* @returns `this` command for chaining
*/
aliases(aliases: string[]): this;
/**
* Get aliases for the command.
*/
aliases(): string[];

/**
* Set the command usage.
*
Expand Down