Skip to content

Commit

Permalink
merged / tweaked
Browse files Browse the repository at this point in the history
  • Loading branch information
tj committed Dec 4, 2011
2 parents ba74d56 + 4788f70 commit 6ccb639
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 23 deletions.
5 changes: 5 additions & 0 deletions examples/deploy
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ program
.option("-e, --exec_mode <mode>", "Which exec mode to use")
.action(function(cmd, options){
console.log('exec "%s" using %s mode', cmd, options.exec_mode);
}).on('--help', function() {
console.log(' Examples:');
console.log('');
console.log(' $ deploy exec sequential');
console.log(' $ deploy exec async');
});

program
Expand Down
73 changes: 52 additions & 21 deletions lib/commander.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,16 @@ Command.prototype.action = function(fn){
var self = this;
this.parent.on(this.name, function(args, unknown){
// Parse any so-far unknown options
unknown = unknown || [];
var parsed = self.parseOptions(unknown);

// Output help if necessary
outputHelpIfNecessary(self, parsed.unknown);

// If there are still any unknown options, then we simply
// die.
if (parsed.unknown.length > 0) {
// die, unless someone asked for help, in which case we give it
// to them, and then we die.
if (parsed.unknown.length > 0) {
self.unknownOption(parsed.unknown[0]);
}

Expand All @@ -218,7 +223,11 @@ Command.prototype.action = function(fn){
// Always append ourselves to the end of the arguments,
// to make sure we match the number of arguments the user
// expects
args[self.args.length] = self;
if (self.args.length) {
args[self.args.length] = self;
} else {
args.push(self);
}

fn.apply(this, args);
});
Expand Down Expand Up @@ -388,14 +397,15 @@ Command.prototype.parseArgs = function(args, unknown){
name = args[0];
if (this.listeners(name).length) {
this.emit(args.shift(), args, unknown);
} else {
} else {
this.emit('*', args);
}
}
else {
} else {
outputHelpIfNecessary(this, unknown);

// If there were no args and we have unknown options,
// then they are extraneous and we need to error.
if (unknown.length > 0) {
if (unknown.length > 0) {
this.unknownOption(unknown[0]);
}
}
Expand Down Expand Up @@ -486,7 +496,7 @@ Command.prototype.parseOptions = function(argv){
// If the next argument looks like it might be
// an argument for this option, we pass it on.
// If it isn't, then it'll simply be ignored
if (argv[i+1] && !(argv[i+1][0] === '-')) {
if (argv[i+1] && '-' != argv[i+1][0]) {
unknownOptions.push(argv[++i]);
}
continue;
Expand Down Expand Up @@ -593,9 +603,15 @@ Command.prototype.description = function(str){
*/

Command.prototype.usage = function(str){
var args = this.args.map(function(arg){
return arg.required
? '<' + arg.name + '>'
: '[' + arg.name + ']';
});
var usage = '[options'
+ (this.commands.length ? '] [command' : '')
+ ']';
+ ']'
+ (this.args.length ? ' ' + args : '');
if (0 == arguments.length) return this._usage || usage;
this._usage = str;
return this;
Expand Down Expand Up @@ -623,10 +639,14 @@ Command.prototype.largestOptionLength = function(){

Command.prototype.optionHelp = function(){
var width = this.largestOptionLength();
return this.options.map(function(option){
return pad(option.flags, width)
+ ' ' + option.description;
}).join('\n');

// Prepend the help information
return [pad('-h, --help', width) + ' ' + 'output usage information']
.concat(this.options.map(function(option){
return pad(option.flags, width)
+ ' ' + option.description;
}))
.join('\n');
};

/**
Expand All @@ -648,7 +668,10 @@ Command.prototype.commandHelp = function(){
? '<' + arg.name + '>'
: '[' + arg.name + ']';
}).join(' ');
return cmd.name + ' ' + args
return cmd.name
+ (cmd.options.length
? ' [options]'
: '') + ' ' + args
+ (cmd.description()
? '\n' + cmd.description()
: '');
Expand Down Expand Up @@ -945,12 +968,20 @@ function pad(str, width) {
}

/**
* Default -h, --help option.
* Output help information if necessary
*
* @param {Command} command to output help for
* @param {Array} array of options to search for -h or --help
* @api private
*/

exports.option('-h, --help', 'output usage information');
exports.on('help', function(){
process.stdout.write(this.helpInformation());
exports.emit('--help');
process.exit(0);
});
function outputHelpIfNecessary(cmd, options) {
options = options || [];
for (var i = 0; i < options.length; i++) {
if (options[i] == '--help' || options[i] == '-h') {
cmd.emit('--help');
process.stdout.write(cmd.helpInformation());
process.exit(0);
}
}
}
15 changes: 13 additions & 2 deletions test/test.options.commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ program

var envValue = "";
var cmdValue = "";
var customHelp = false;

program
.command('setup [env]')
Expand All @@ -33,6 +34,8 @@ program
.option("-t, --target [target]", "Target to use")
.action(function(cmd, options){
cmdValue = cmd;
}).on("--help", function(){
customHelp = true;
});

program
Expand Down Expand Up @@ -85,14 +88,22 @@ cmdValue.should.equal("exec3");
// Make sure we still catch errors with required values for options
var exceptionOccurred = false;
var oldProcessExit = process.exit;
var oldConsoleError = console.error;
process.exit = function() { exceptionOccurred = true; throw new Error(); };
console.error = function() {};

try {
program.parse(['node', 'test', '--config', 'conf6', 'exec', '--help']);
} catch(ex) {
program.config.should.equal("conf6");
}

try {
program.parse(['node', 'test', '--config', 'conf', 'exec', '-t', 'target1', 'exec1', '-e']);
}
catch(ex) {
}

process.exit = oldProcessExit;
exceptionOccurred.should.be.true;

process.exit = oldProcessExit;
customHelp.should.be.true;

0 comments on commit 6ccb639

Please sign in to comment.