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 a way to override help and version help message #963

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions Readme.md
Expand Up @@ -224,6 +224,12 @@ You may specify custom flags by passing an additional parameter to the `version`
program.version('0.0.1', '-v, --version');
```

You can also override the help description for the version command.

```js
program.version('0.0.1', '-v, --version', 'output the current version');
```



## Command-specific options
Expand Down Expand Up @@ -433,6 +439,15 @@ function make_red(txt) {
}
```

## .helpOption(flags, description)

Override the default help flags and description.

```js
program
.helpOption('-e, --HELP', 'read more information');
```

## .help(cb)

Output help information and exit immediately.
Expand Down
21 changes: 21 additions & 0 deletions examples/custom-help-description
@@ -0,0 +1,21 @@
#!/usr/bin/env node

/**
* Module dependencies.
*/

var program = require('../');

program
.helpOption('-c, --HELP', 'custom help message')
.option('-s, --sessions', 'add session support')
.option('-t, --template <engine>', 'specify template engine (jade|ejs) [jade]', 'jade');

program
.command('child')
.option('--gender', 'specific gender of child')
.action((cmd) => {
console.log('Childsubcommand...');
});

program.parse(process.argv);
13 changes: 13 additions & 0 deletions examples/custom-version
@@ -0,0 +1,13 @@
#!/usr/bin/env node

/**
* Module dependencies.
*/

var program = require('../');

program
.version('0.0.1', '-v, --VERSION', 'new version message')
.option('-s, --sessions', 'add session support')
.option('-t, --template <engine>', 'specify template engine (jade|ejs) [jade]', 'jade')
.parse(process.argv);
58 changes: 49 additions & 9 deletions index.js
Expand Up @@ -103,6 +103,11 @@ function Command(name) {
this._allowUnknownOption = false;
this._args = [];
this._name = name || '';

this._helpFlags = '-h, --help';
this._helpDescription = 'output usage information';
this._helpShortFlag = '-h';
this._helpLongFlag = '--help';
}

/**
Expand Down Expand Up @@ -182,6 +187,10 @@ Command.prototype.command = function(name, desc, opts) {
if (opts.isDefault) this.defaultExecutable = cmd._name;
}
cmd._noHelp = !!opts.noHelp;
cmd._helpFlags = this._helpFlags;
cmd._helpDescription = this._helpDescription;
cmd._helpShortFlag = this._helpShortFlag;
cmd._helpLongFlag = this._helpLongFlag;
this.commands.push(cmd);
cmd.parseExpectedArgs(args);
cmd.parent = this;
Expand Down Expand Up @@ -466,7 +475,7 @@ Command.prototype.parse = function(argv) {
// github-style sub-commands with no sub-command
if (this.executables && argv.length < 3 && !this.defaultExecutable) {
// this user needs help
argv.push('--help');
argv.push(this._helpLongFlag);
}

// process argv
Expand Down Expand Up @@ -519,7 +528,7 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) {
// <cmd> --help
if (args[0] === 'help') {
args[0] = args[1];
args[1] = '--help';
args[1] = this._helpLongFlag;
}

// executable
Expand Down Expand Up @@ -848,15 +857,17 @@ Command.prototype.variadicArgNotLast = function(name) {
*
* @param {String} str
* @param {String} [flags]
* @param {String} [description]
* @return {Command} for chaining
* @api public
*/

Command.prototype.version = function(str, flags) {
Command.prototype.version = function(str, flags, description) {
if (arguments.length === 0) return this._version;
this._version = str;
flags = flags || '-V, --version';
var versionOption = new Option(flags, 'output the version number');
description = description || 'output the version number';
var versionOption = new Option(flags, description);
this._versionOptionName = versionOption.long.substr(2) || 'version';
this.options.push(versionOption);
this.on('option:' + this._versionOptionName, function() {
Expand Down Expand Up @@ -990,8 +1001,9 @@ Command.prototype.largestCommandLength = function() {
Command.prototype.largestOptionLength = function() {
var options = [].slice.call(this.options);
options.push({
flags: '-h, --help'
flags: this._helpFlags
});

return options.reduce(function(max, option) {
return Math.max(max, option.flags.length);
}, 0);
Expand Down Expand Up @@ -1048,7 +1060,7 @@ Command.prototype.optionHelp = function() {
return this.options.map(function(option) {
return pad(option.flags, width) + ' ' + option.description +
((option.bool && option.defaultValue !== undefined) ? ' (default: ' + JSON.stringify(option.defaultValue) + ')' : '');
}).concat([pad('-h, --help', width) + ' ' + 'output usage information'])
}).concat([pad(this._helpFlags, width) + ' ' + this._helpDescription])
.join('\n');
};

Expand Down Expand Up @@ -1129,7 +1141,10 @@ Command.prototype.helpInformation = function() {
};

/**
* Output help information for this command
* Output help information for this command.
*
* When listener(s) are available for the helpLongFlag
* those callbacks are invoked.
*
* @api public
*/
Expand All @@ -1145,12 +1160,36 @@ Command.prototype.outputHelp = function(cb) {
throw new Error('outputHelp callback must return a string or a Buffer');
}
process.stdout.write(cbOutput);
this.emit('--help');
this.emit(this._helpLongFlag);
};

/**
* You can pass in flags and a description to override the help
* flags and help description for your command.
*
* @param {String} flags
* @param {String} description
shadowspawn marked this conversation as resolved.
Show resolved Hide resolved
* @return {Command}
* @api public
*/

Command.prototype.helpOption = function(flags, description) {
this._helpFlags = flags || this._helpFlags;
this._helpDescription = description || this._helpDescription;

var splitFlags = this._helpFlags.split(/[ ,|]+/);

if (splitFlags.length > 1) this._helpShortFlag = splitFlags.shift();

this._helpLongFlag = splitFlags.shift();

return this;
};

/**
* Output help information and exit.
*
* @param {Function} cb
* @api public
*/

Expand Down Expand Up @@ -1197,8 +1236,9 @@ function pad(str, width) {

function outputHelpIfNecessary(cmd, options) {
options = options || [];

for (var i = 0; i < options.length; i++) {
if (options[i] === '--help' || options[i] === '-h') {
if (options[i] === cmd._helpLongFlag || options[i] === cmd._helpShortFlag) {
cmd.outputHelp();
process.exit(0);
}
Expand Down
46 changes: 46 additions & 0 deletions test/test.command.helpInformation.custom.js
@@ -0,0 +1,46 @@
var program = require('../')
, sinon = require('sinon').sandbox.create()
, should = require('should');

sinon.stub(process, 'exit');
sinon.stub(process.stdout, 'write');

program.helpOption('-c, --HELP', 'custom help output');
program.command('somecommand');
program.command('anothercommand [options]');

var expectedHelpInformation = [
'Usage: [options] [command]',
'',
'Options:',
' -c, --HELP custom help output',
'',
'Commands:',
' somecommand',
' anothercommand [options]',
''
].join('\n');

program.helpInformation().should.equal(expectedHelpInformation);

// Test arguments
var expectedCommandHelpInformation = [
'Usage: test [options] [command]',
'',
'Options:',
' -c, --HELP custom help output',
'',
'Commands:',
' somecommand',
' anothercommand [options]',
''
].join('\n');

program.parse(['node', 'test', '--HELP']);

process.stdout.write.called.should.equal(true);

var output = process.stdout.write.args[0];
output[0].should.equal(expectedCommandHelpInformation);

sinon.restore();
65 changes: 65 additions & 0 deletions test/test.command.helpSubCommand.customFlags.js
@@ -0,0 +1,65 @@
var program = require('../'),
sinon = require('sinon').sandbox.create(),
should = require('should');

sinon.stub(process, 'exit');
sinon.stub(process.stdout, 'write');

// Test that subcommands inherit the help flags
// but can also override help flags
program
.helpOption('-i, --ihelp', 'foo foo');

program
.command('child')
.option('--gender', 'specific gender of child')
.action((cmd) => {
console.log('Childsubcommand...');
});

program
.command('family')
.helpOption('-h, --help')
.action((cmd) => {
console.log('Familysubcommand...');
});

// Test arguments
var expectedCommandHelpInformation = [
'Usage: child [options]',
'',
'Options:',
' --gender specific gender of child',
' -i, --ihelp foo foo',
''
].join('\n');

program.parse(['node', 'test', 'child', '-i']);

process.stdout.write.called.should.equal(true);

var output = process.stdout.write.args[0];
output[0].should.equal(expectedCommandHelpInformation);

// Test other command
sinon.restore();

sinon.stub(process, 'exit');
sinon.stub(process.stdout, 'write');

var expectedFamilyCommandHelpInformation = [
'Usage: family [options]',
'',
'Options:',
' -h, --help foo foo',
''
].join('\n');

program.parse(['node', 'test', 'family', '-h']);

process.stdout.write.called.should.equal(true);

var output2 = process.stdout.write.args[0];
output2[0].should.equal(expectedFamilyCommandHelpInformation);

sinon.restore();
22 changes: 22 additions & 0 deletions test/test.options.version.customHelpDescription.js
@@ -0,0 +1,22 @@
var program = require('../')
, sinon = require('sinon').sandbox.create()
, should = require('should');

program.version('1.0.0', undefined, 'custom version output');
program.command('somecommand');
program.command('anothercommand [options]');

var expectedHelpInformation = [
'Usage: [options] [command]',
'',
'Options:',
' -V, --version custom version output',
' -h, --help output usage information',
'',
'Commands:',
' somecommand',
' anothercommand [options]',
''
].join('\n');

program.helpInformation().should.equal(expectedHelpInformation);
23 changes: 21 additions & 2 deletions typings/index.d.ts
Expand Up @@ -45,7 +45,7 @@ declare namespace local {
* @param {string} [flags]
* @returns {Command} for chaining
*/
version(str: string, flags?: string): Command;
version(str: string, flags?: string, description?: string): Command;

/**
* Add command `name`.
Expand Down Expand Up @@ -268,19 +268,38 @@ declare namespace local {
/**
* Output help information for this command.
*
* When listener(s) are available for the helpLongFlag
* those callbacks are invoked.
*
* @param {(str: string) => string} [cb]
*/
outputHelp(cb?: (str: string) => string): void;

/**
* When called with no arguments, or with a callback, this will
* output help information and exit.
*
* You can pass in flags and a description to override the help
* flags and help description for your command.
*
* @param {string} [flags]
* @param {string} [description]
* @return {Command}
*/
helpOption(flags?: string, description?: string): Command;

/** Output help information and exit.
shadowspawn marked this conversation as resolved.
Show resolved Hide resolved
*
* @param {(str: string) => string} [cb]
* @param {string} [description]
*/
help(cb?: (str: string) => string): never;
help(cb: helpCallback, description?: string): never;
}

}

type helpCallback = (str: string) => string;

declare namespace commander {

type Command = local.Command
Expand Down