Skip to content

Commit

Permalink
Fix sub-command help flags, add documentation on help flags
Browse files Browse the repository at this point in the history
Sub-commands now inherit the help flags of their parent. These
can be overriden by calling ".help" on the sub-commands.

Added a test to cover these cases. Updated the example to also
demonstrate this feature.

Improved documentation on help and outputHelp functions for
both JS and TypeScript.
  • Loading branch information
idmontie committed Jun 6, 2019
1 parent c171655 commit 1daee1b
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 10 deletions.
12 changes: 10 additions & 2 deletions examples/custom-help-description
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,13 @@ var program = require('../');
program
.help('-c, --HELP', 'custom help message')
.option('-s, --sessions', 'add session support')
.option('-t, --template <engine>', 'specify template engine (jade|ejs) [jade]', 'jade')
.parse(process.argv);
.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);
23 changes: 18 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,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 @@ -1135,7 +1139,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 @@ -1151,10 +1158,14 @@ Command.prototype.outputHelp = function(cb) {
};

/**
* Output help information and exit.
* When called with no arguments, or with a callback, this will
* output help information and exit.
*
* @param {Function|String} cb
* @param {String} description
* You can pass in flags and a description to override the help
* flags and help description for your command.
*
* @param {Function|String} [flagsOrCb]
* @param {String} [description]
* @return {Command?}
* @api public
*/
Expand All @@ -1169,7 +1180,9 @@ Command.prototype.help = function(flagsOrCb, description) {
this._helpDescription = description || this._helpDescription;

var flags = this._helpFlags.split(/[ ,|]+/);
if (flags.length > 1 && !/^[[<]/.test(flags[1])) this._helpShortFlag = flags.shift();

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

this._helpLongFlag = flags.shift();

return this;
Expand Down
65 changes: 65 additions & 0 deletions test/test.command.helpSubCommand.customFlags.js
Original file line number Diff line number Diff line change
@@ -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
.help('-i, --ihelp', 'foo foo');

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

program
.command('family')
.help('-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();
14 changes: 11 additions & 3 deletions typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,21 +268,29 @@ 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;

/** Output help information and exit.
/**
* 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 | (str: string) => string} [flagsOrCb]
* @param {string} [description]
*/
help(flagsOrCb?: string | callback, description?: string): never;
help(flagsOrCb?: string | helpCallback, description?: string): never;
}

}

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

declare namespace commander {

Expand Down

0 comments on commit 1daee1b

Please sign in to comment.