Commander.js
Commander is a light-weight, expressive, and powerful command-line framework for node.js.
exports.Option
Expose Option.
Source
exports.Option = Option;Option()
Initialize a new Option with the given flags and description.
Source
function Option(flags, description) {
this.flags = flags;
this.required = ~flags.indexOf('<');
this.optional = ~flags.indexOf('[');
this.bool = !~flags.indexOf('-no-');
flags = flags.split(/[ ,|]+/)
this.short = flags.shift();
this.long = flags.shift();
this.description = description;
}Command()
Initialize a new Command.
Source
function Command(name) {
this.commands = [];
this.options = [];
this.args = [];
this.name = name;
}Command#command()
Add command name.
The .action() callback is invoked when the
command name is specified via ARGV,
and the remaining arguments are applied to the
function for access.
When the name is "*" an un-matched command
will be passed as the first arg, followed by
the rest of ARGV remaining.
Examples
program
.version('0.0.1')
.option('-C, --chdir <path>', 'change the working directory')
.option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
.option('-T, --no-tests', 'ignore test hook')
program
.command('setup')
.description('run remote setup commands')
.action(function(){
console.log('setup');
});
program
.command('exec <cmd>')
.description('run the given remote command')
.action(function(cmd){
console.log('exec "%s"', cmd);
});
program
.command('*')
.description('deploy the given env')
.action(function(env){
console.log('deploying "%s"', env);
});
program.parse(process.argv);
Source
Command.prototype.command = function(name){
var args = name.split(/ +/);
var cmd = new Command(args.shift());
this.commands.push(cmd);
cmd.parseExpectedArgs(args);
cmd.parent = this;
return cmd;
};Command#action()
Register callback fn for the command.
Examples
program
.command('help')
.description('display verbose help')
.action(function(){
// output help here
});
Source
Command.prototype.action = function(fn){
var self = this;
this.parent.on(this.name, function(args){
self.args.forEach(function(arg, i){
if (arg.required && null == args[i]) {
self.missingArgument(arg.name);
}
});
fn.apply(this, args);
});
return this;
};Command#option()
Define option with flags, description and optional
coercion fn.
The flags string should contain both the short and long flags,
separated by comma, a pipe or space. The following are all valid
all will output this way when --help is used.
"-p, --pepper"
"-p|--pepper"
"-p --pepper"
Examples
// simple boolean defaulting to false
program.option('-p, --pepper', 'add pepper');
--pepper
program.pepper
// => Boolean
// simple boolean defaulting to false
program.option('-C, --no-cheese', 'remove cheese');
program.cheese
// => true
--no-cheese
program.cheese
// => true
// required argument
program.option('-C, --chdir <path>', 'change the working directory');
--chdir /tmp
program.chdir
// => "/tmp"
// optional argument
program.option('-c, --cheese [type]', 'add cheese [marble]');
Source
Command.prototype.option = function(flags, description, fn, defaultValue){
var self = this
, option = new Option(flags, description)
, oname = option.name()
, name = camelcase(oname);
// default as 3rd arg
if ('function' != typeof fn) defaultValue = fn, fn = null;
// preassign default value only for --no-*, [optional], or
if (false == option.bool || option.optional || option.required) {
// when --no-* we make sure default is true
if (false == option.bool) defaultValue = true;
// preassign only if we have a default
if (undefined !== defaultValue) self[name] = defaultValue;
}
// register the option
this.options.push(option);
// when it's passed assign the value
// and conditionally invoke the callback
this.on(oname, function(val){
// coercion
if (null != val && fn) val = fn(val);
// unassigned or bool
if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) {
// if no value, bool true, and we have a default, then use it!
if (null == val) {
self[name] = option.bool
? defaultValue || true
: false;
} else {
self[name] = val;
}
} else if (null !== val) {
// reassign
self[name] = val;
}
});
return this;
}; Command#parse()
Parse argv, settings options and invoking commands when defined.
Source
Command.prototype.parse = function(argv){
// store raw args
this.rawArgs = argv;
// guess name
if (!this.name) this.name = basename(argv[1]);
// process argv
this.args = this.parseOptions(this.normalize(argv));
return this.parseArgs(this.args);
};Command#description()
Set the description str.
Source
Command.prototype.description = function(str){
if (0 == arguments.length) return this._description;
this._description = str;
return this;
};Command#usage()
Set / get the command usage str.
Source
Command.prototype.usage = function(str){
var usage = '[options'
+ (this.commands.length ? '] [command' : '')
+ ']';
if (0 == arguments.length) return this._usage || usage;
this._usage = str;
return this;
};Command#prompt()
Prompt str and callback fn(val)
Commander supports single-line and multi-line prompts.
To issue a single-line prompt simply add white-space
to the end of str, something like "name: ", whereas
for a multi-line prompt omit this "description:".
Examples
program.prompt('Username: ', function(name){
console.log('hi %s', name);
});
program.prompt('Description:', function(desc){
console.log('description was "%s"', desc.trim());
});
Source
Command.prototype.prompt = function(str, fn){
if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments);
this.promptMultiLine(str, fn);
};Command#password()
Prompt for password with str, mask char and callback fn(val).
The mask string defaults to '', aka no output is
written while typing, you may want to use "*" etc.
Examples
program.password('Password: ', function(pass){
console.log('got "%s"', pass);
process.stdin.destroy();
});
program.password('Password: ', '*', function(pass){
console.log('got "%s"', pass);
process.stdin.destroy();
});
Source
Command.prototype.password = function(str, mask, fn){
var self = this
, buf = '';
// default mask
if ('function' == typeof mask) {
fn = mask;
mask = '';
}
tty.setRawMode(true);
process.stdout.write(str);
// keypress
process.stdin.on('keypress', function(c, key){
if (key && 'enter' == key.name) {
console.log();
process.stdin.removeAllListeners('keypress');
tty.setRawMode(false);
if (!buf.trim().length) return self.password(str, mask, fn);
fn(buf);
return;
}
if (key && key.ctrl && 'c' == key.name) {
console.log('%s', buf);
process.exit();
}
process.stdout.write(mask);
buf += c;
}).resume();
};Command#confirm()
Confirmation prompt with str and callback fn(bool)
Examples
program.confirm('continue? ', function(ok){
console.log(' got %j', ok);
process.stdin.destroy();
});
Source
Command.prototype.confirm = function(str, fn){
var self = this;
this.prompt(str, function(ok){
if (!ok.trim()) {
return self.confirm(str, fn);
}
fn(parseBool(ok));
});
};Command#choose()
Choice prompt with list of items and callback fn(index, item)
Examples
var list = ['tobi', 'loki', 'jane', 'manny', 'luna'];
console.log('Choose the coolest pet:');
program.choose(list, function(i){
console.log('you chose %d "%s"', i, list[i]);
process.stdin.destroy();
});
Source
Command.prototype.choose = function(list, fn){
var self = this;
list.forEach(function(item, i){
console.log(' %d) %s', i + 1, item);
});
function again() {
self.prompt(' : ', function(val){
val = parseInt(val, 10) - 1;
if (null == list[val]) {
again();
} else {
fn(val, list[val]);
}
});
}
again();
};
exports.Command
Expose
Command.Source