"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/commander/index.js" (8 Mar 2017, 24714 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /**
    2  * Module dependencies.
    3  */
    4 
    5 var EventEmitter = require('events').EventEmitter;
    6 var spawn = require('child_process').spawn;
    7 var readlink = require('graceful-readlink').readlinkSync;
    8 var path = require('path');
    9 var dirname = path.dirname;
   10 var basename = path.basename;
   11 var fs = require('fs');
   12 
   13 /**
   14  * Expose the root command.
   15  */
   16 
   17 exports = module.exports = new Command();
   18 
   19 /**
   20  * Expose `Command`.
   21  */
   22 
   23 exports.Command = Command;
   24 
   25 /**
   26  * Expose `Option`.
   27  */
   28 
   29 exports.Option = Option;
   30 
   31 /**
   32  * Initialize a new `Option` with the given `flags` and `description`.
   33  *
   34  * @param {String} flags
   35  * @param {String} description
   36  * @api public
   37  */
   38 
   39 function Option(flags, description) {
   40   this.flags = flags;
   41   this.required = ~flags.indexOf('<');
   42   this.optional = ~flags.indexOf('[');
   43   this.bool = !~flags.indexOf('-no-');
   44   flags = flags.split(/[ ,|]+/);
   45   if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift();
   46   this.long = flags.shift();
   47   this.description = description || '';
   48 }
   49 
   50 /**
   51  * Return option name.
   52  *
   53  * @return {String}
   54  * @api private
   55  */
   56 
   57 Option.prototype.name = function() {
   58   return this.long
   59     .replace('--', '')
   60     .replace('no-', '');
   61 };
   62 
   63 /**
   64  * Check if `arg` matches the short or long flag.
   65  *
   66  * @param {String} arg
   67  * @return {Boolean}
   68  * @api private
   69  */
   70 
   71 Option.prototype.is = function(arg) {
   72   return arg == this.short || arg == this.long;
   73 };
   74 
   75 /**
   76  * Initialize a new `Command`.
   77  *
   78  * @param {String} name
   79  * @api public
   80  */
   81 
   82 function Command(name) {
   83   this.commands = [];
   84   this.options = [];
   85   this._execs = {};
   86   this._allowUnknownOption = false;
   87   this._args = [];
   88   this._name = name || '';
   89 }
   90 
   91 /**
   92  * Inherit from `EventEmitter.prototype`.
   93  */
   94 
   95 Command.prototype.__proto__ = EventEmitter.prototype;
   96 
   97 /**
   98  * Add command `name`.
   99  *
  100  * The `.action()` callback is invoked when the
  101  * command `name` is specified via __ARGV__,
  102  * and the remaining arguments are applied to the
  103  * function for access.
  104  *
  105  * When the `name` is "*" an un-matched command
  106  * will be passed as the first arg, followed by
  107  * the rest of __ARGV__ remaining.
  108  *
  109  * Examples:
  110  *
  111  *      program
  112  *        .version('0.0.1')
  113  *        .option('-C, --chdir <path>', 'change the working directory')
  114  *        .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
  115  *        .option('-T, --no-tests', 'ignore test hook')
  116  *
  117  *      program
  118  *        .command('setup')
  119  *        .description('run remote setup commands')
  120  *        .action(function() {
  121  *          console.log('setup');
  122  *        });
  123  *
  124  *      program
  125  *        .command('exec <cmd>')
  126  *        .description('run the given remote command')
  127  *        .action(function(cmd) {
  128  *          console.log('exec "%s"', cmd);
  129  *        });
  130  *
  131  *      program
  132  *        .command('teardown <dir> [otherDirs...]')
  133  *        .description('run teardown commands')
  134  *        .action(function(dir, otherDirs) {
  135  *          console.log('dir "%s"', dir);
  136  *          if (otherDirs) {
  137  *            otherDirs.forEach(function (oDir) {
  138  *              console.log('dir "%s"', oDir);
  139  *            });
  140  *          }
  141  *        });
  142  *
  143  *      program
  144  *        .command('*')
  145  *        .description('deploy the given env')
  146  *        .action(function(env) {
  147  *          console.log('deploying "%s"', env);
  148  *        });
  149  *
  150  *      program.parse(process.argv);
  151   *
  152  * @param {String} name
  153  * @param {String} [desc] for git-style sub-commands
  154  * @return {Command} the new command
  155  * @api public
  156  */
  157 
  158 Command.prototype.command = function(name, desc, opts) {
  159   opts = opts || {};
  160   var args = name.split(/ +/);
  161   var cmd = new Command(args.shift());
  162 
  163   if (desc) {
  164     cmd.description(desc);
  165     this.executables = true;
  166     this._execs[cmd._name] = true;
  167     if (opts.isDefault) this.defaultExecutable = cmd._name;
  168   }
  169 
  170   cmd._noHelp = !!opts.noHelp;
  171   this.commands.push(cmd);
  172   cmd.parseExpectedArgs(args);
  173   cmd.parent = this;
  174 
  175   if (desc) return this;
  176   return cmd;
  177 };
  178 
  179 /**
  180  * Define argument syntax for the top-level command.
  181  *
  182  * @api public
  183  */
  184 
  185 Command.prototype.arguments = function (desc) {
  186   return this.parseExpectedArgs(desc.split(/ +/));
  187 };
  188 
  189 /**
  190  * Add an implicit `help [cmd]` subcommand
  191  * which invokes `--help` for the given command.
  192  *
  193  * @api private
  194  */
  195 
  196 Command.prototype.addImplicitHelpCommand = function() {
  197   this.command('help [cmd]', 'display help for [cmd]');
  198 };
  199 
  200 /**
  201  * Parse expected `args`.
  202  *
  203  * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`.
  204  *
  205  * @param {Array} args
  206  * @return {Command} for chaining
  207  * @api public
  208  */
  209 
  210 Command.prototype.parseExpectedArgs = function(args) {
  211   if (!args.length) return;
  212   var self = this;
  213   args.forEach(function(arg) {
  214     var argDetails = {
  215       required: false,
  216       name: '',
  217       variadic: false
  218     };
  219 
  220     switch (arg[0]) {
  221       case '<':
  222         argDetails.required = true;
  223         argDetails.name = arg.slice(1, -1);
  224         break;
  225       case '[':
  226         argDetails.name = arg.slice(1, -1);
  227         break;
  228     }
  229 
  230     if (argDetails.name.length > 3 && argDetails.name.slice(-3) === '...') {
  231       argDetails.variadic = true;
  232       argDetails.name = argDetails.name.slice(0, -3);
  233     }
  234     if (argDetails.name) {
  235       self._args.push(argDetails);
  236     }
  237   });
  238   return this;
  239 };
  240 
  241 /**
  242  * Register callback `fn` for the command.
  243  *
  244  * Examples:
  245  *
  246  *      program
  247  *        .command('help')
  248  *        .description('display verbose help')
  249  *        .action(function() {
  250  *           // output help here
  251  *        });
  252  *
  253  * @param {Function} fn
  254  * @return {Command} for chaining
  255  * @api public
  256  */
  257 
  258 Command.prototype.action = function(fn) {
  259   var self = this;
  260   var listener = function(args, unknown) {
  261     // Parse any so-far unknown options
  262     args = args || [];
  263     unknown = unknown || [];
  264 
  265     var parsed = self.parseOptions(unknown);
  266 
  267     // Output help if necessary
  268     outputHelpIfNecessary(self, parsed.unknown);
  269 
  270     // If there are still any unknown options, then we simply
  271     // die, unless someone asked for help, in which case we give it
  272     // to them, and then we die.
  273     if (parsed.unknown.length > 0) {
  274       self.unknownOption(parsed.unknown[0]);
  275     }
  276 
  277     // Leftover arguments need to be pushed back. Fixes issue #56
  278     if (parsed.args.length) args = parsed.args.concat(args);
  279 
  280     self._args.forEach(function(arg, i) {
  281       if (arg.required && null == args[i]) {
  282         self.missingArgument(arg.name);
  283       } else if (arg.variadic) {
  284         if (i !== self._args.length - 1) {
  285           self.variadicArgNotLast(arg.name);
  286         }
  287 
  288         args[i] = args.splice(i);
  289       }
  290     });
  291 
  292     // Always append ourselves to the end of the arguments,
  293     // to make sure we match the number of arguments the user
  294     // expects
  295     if (self._args.length) {
  296       args[self._args.length] = self;
  297     } else {
  298       args.push(self);
  299     }
  300 
  301     fn.apply(self, args);
  302   };
  303   var parent = this.parent || this;
  304   var name = parent === this ? '*' : this._name;
  305   parent.on(name, listener);
  306   if (this._alias) parent.on(this._alias, listener);
  307   return this;
  308 };
  309 
  310 /**
  311  * Define option with `flags`, `description` and optional
  312  * coercion `fn`.
  313  *
  314  * The `flags` string should contain both the short and long flags,
  315  * separated by comma, a pipe or space. The following are all valid
  316  * all will output this way when `--help` is used.
  317  *
  318  *    "-p, --pepper"
  319  *    "-p|--pepper"
  320  *    "-p --pepper"
  321  *
  322  * Examples:
  323  *
  324  *     // simple boolean defaulting to false
  325  *     program.option('-p, --pepper', 'add pepper');
  326  *
  327  *     --pepper
  328  *     program.pepper
  329  *     // => Boolean
  330  *
  331  *     // simple boolean defaulting to true
  332  *     program.option('-C, --no-cheese', 'remove cheese');
  333  *
  334  *     program.cheese
  335  *     // => true
  336  *
  337  *     --no-cheese
  338  *     program.cheese
  339  *     // => false
  340  *
  341  *     // required argument
  342  *     program.option('-C, --chdir <path>', 'change the working directory');
  343  *
  344  *     --chdir /tmp
  345  *     program.chdir
  346  *     // => "/tmp"
  347  *
  348  *     // optional argument
  349  *     program.option('-c, --cheese [type]', 'add cheese [marble]');
  350  *
  351  * @param {String} flags
  352  * @param {String} description
  353  * @param {Function|Mixed} fn or default
  354  * @param {Mixed} defaultValue
  355  * @return {Command} for chaining
  356  * @api public
  357  */
  358 
  359 Command.prototype.option = function(flags, description, fn, defaultValue) {
  360   var self = this
  361     , option = new Option(flags, description)
  362     , oname = option.name()
  363     , name = camelcase(oname);
  364 
  365   // default as 3rd arg
  366   if (typeof fn != 'function') {
  367     if (fn instanceof RegExp) {
  368       var regex = fn;
  369       fn = function(val, def) {
  370         var m = regex.exec(val);
  371         return m ? m[0] : def;
  372       }
  373     }
  374     else {
  375       defaultValue = fn;
  376       fn = null;
  377     }
  378   }
  379 
  380   // preassign default value only for --no-*, [optional], or <required>
  381   if (false == option.bool || option.optional || option.required) {
  382     // when --no-* we make sure default is true
  383     if (false == option.bool) defaultValue = true;
  384     // preassign only if we have a default
  385     if (undefined !== defaultValue) self[name] = defaultValue;
  386   }
  387 
  388   // register the option
  389   this.options.push(option);
  390 
  391   // when it's passed assign the value
  392   // and conditionally invoke the callback
  393   this.on(oname, function(val) {
  394     // coercion
  395     if (null !== val && fn) val = fn(val, undefined === self[name]
  396       ? defaultValue
  397       : self[name]);
  398 
  399     // unassigned or bool
  400     if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) {
  401       // if no value, bool true, and we have a default, then use it!
  402       if (null == val) {
  403         self[name] = option.bool
  404           ? defaultValue || true
  405           : false;
  406       } else {
  407         self[name] = val;
  408       }
  409     } else if (null !== val) {
  410       // reassign
  411       self[name] = val;
  412     }
  413   });
  414 
  415   return this;
  416 };
  417 
  418 /**
  419  * Allow unknown options on the command line.
  420  *
  421  * @param {Boolean} arg if `true` or omitted, no error will be thrown
  422  * for unknown options.
  423  * @api public
  424  */
  425 Command.prototype.allowUnknownOption = function(arg) {
  426     this._allowUnknownOption = arguments.length === 0 || arg;
  427     return this;
  428 };
  429 
  430 /**
  431  * Parse `argv`, settings options and invoking commands when defined.
  432  *
  433  * @param {Array} argv
  434  * @return {Command} for chaining
  435  * @api public
  436  */
  437 
  438 Command.prototype.parse = function(argv) {
  439   // implicit help
  440   if (this.executables) this.addImplicitHelpCommand();
  441 
  442   // store raw args
  443   this.rawArgs = argv;
  444 
  445   // guess name
  446   this._name = this._name || basename(argv[1], '.js');
  447 
  448   // github-style sub-commands with no sub-command
  449   if (this.executables && argv.length < 3 && !this.defaultExecutable) {
  450     // this user needs help
  451     argv.push('--help');
  452   }
  453 
  454   // process argv
  455   var parsed = this.parseOptions(this.normalize(argv.slice(2)));
  456   var args = this.args = parsed.args;
  457 
  458   var result = this.parseArgs(this.args, parsed.unknown);
  459 
  460   // executable sub-commands
  461   var name = result.args[0];
  462   if (this._execs[name] && typeof this._execs[name] != "function") {
  463     return this.executeSubCommand(argv, args, parsed.unknown);
  464   } else if (this.defaultExecutable) {
  465     // use the default subcommand
  466     args.unshift(name = this.defaultExecutable);
  467     return this.executeSubCommand(argv, args, parsed.unknown);
  468   }
  469 
  470   return result;
  471 };
  472 
  473 /**
  474  * Execute a sub-command executable.
  475  *
  476  * @param {Array} argv
  477  * @param {Array} args
  478  * @param {Array} unknown
  479  * @api private
  480  */
  481 
  482 Command.prototype.executeSubCommand = function(argv, args, unknown) {
  483   args = args.concat(unknown);
  484 
  485   if (!args.length) this.help();
  486   if ('help' == args[0] && 1 == args.length) this.help();
  487 
  488   // <cmd> --help
  489   if ('help' == args[0]) {
  490     args[0] = args[1];
  491     args[1] = '--help';
  492   }
  493 
  494   // executable
  495   var f = argv[1];
  496   // name of the subcommand, link `pm-install`
  497   var bin = basename(f, '.js') + '-' + args[0];
  498 
  499 
  500   // In case of globally installed, get the base dir where executable
  501   //  subcommand file should be located at
  502   var baseDir
  503     , link = readlink(f);
  504 
  505   // when symbolink is relative path
  506   if (link !== f && link.charAt(0) !== '/') {
  507     link = path.join(dirname(f), link)
  508   }
  509   baseDir = dirname(link);
  510 
  511   // prefer local `./<bin>` to bin in the $PATH
  512   var localBin = path.join(baseDir, bin);
  513 
  514   // whether bin file is a js script with explicit `.js` extension
  515   var isExplicitJS = false;
  516   if (exists(localBin + '.js')) {
  517     bin = localBin + '.js';
  518     isExplicitJS = true;
  519   } else if (exists(localBin)) {
  520     bin = localBin;
  521   }
  522 
  523   args = args.slice(1);
  524 
  525   var proc;
  526   if (process.platform !== 'win32') {
  527     if (isExplicitJS) {
  528       args.unshift(localBin);
  529       // add executable arguments to spawn
  530       args = (process.execArgv || []).concat(args);
  531 
  532       proc = spawn('node', args, { stdio: 'inherit', customFds: [0, 1, 2] });
  533     } else {
  534       proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] });
  535     }
  536   } else {
  537     args.unshift(localBin);
  538     proc = spawn(process.execPath, args, { stdio: 'inherit'});
  539   }
  540 
  541   proc.on('close', process.exit.bind(process));
  542   proc.on('error', function(err) {
  543     if (err.code == "ENOENT") {
  544       console.error('\n  %s(1) does not exist, try --help\n', bin);
  545     } else if (err.code == "EACCES") {
  546       console.error('\n  %s(1) not executable. try chmod or run with root\n', bin);
  547     }
  548     process.exit(1);
  549   });
  550 
  551   // Store the reference to the child process
  552   this.runningCommand = proc;
  553 };
  554 
  555 /**
  556  * Normalize `args`, splitting joined short flags. For example
  557  * the arg "-abc" is equivalent to "-a -b -c".
  558  * This also normalizes equal sign and splits "--abc=def" into "--abc def".
  559  *
  560  * @param {Array} args
  561  * @return {Array}
  562  * @api private
  563  */
  564 
  565 Command.prototype.normalize = function(args) {
  566   var ret = []
  567     , arg
  568     , lastOpt
  569     , index;
  570 
  571   for (var i = 0, len = args.length; i < len; ++i) {
  572     arg = args[i];
  573     if (i > 0) {
  574       lastOpt = this.optionFor(args[i-1]);
  575     }
  576 
  577     if (arg === '--') {
  578       // Honor option terminator
  579       ret = ret.concat(args.slice(i));
  580       break;
  581     } else if (lastOpt && lastOpt.required) {
  582       ret.push(arg);
  583     } else if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) {
  584       arg.slice(1).split('').forEach(function(c) {
  585         ret.push('-' + c);
  586       });
  587     } else if (/^--/.test(arg) && ~(index = arg.indexOf('='))) {
  588       ret.push(arg.slice(0, index), arg.slice(index + 1));
  589     } else {
  590       ret.push(arg);
  591     }
  592   }
  593 
  594   return ret;
  595 };
  596 
  597 /**
  598  * Parse command `args`.
  599  *
  600  * When listener(s) are available those
  601  * callbacks are invoked, otherwise the "*"
  602  * event is emitted and those actions are invoked.
  603  *
  604  * @param {Array} args
  605  * @return {Command} for chaining
  606  * @api private
  607  */
  608 
  609 Command.prototype.parseArgs = function(args, unknown) {
  610   var name;
  611 
  612   if (args.length) {
  613     name = args[0];
  614     if (this.listeners(name).length) {
  615       this.emit(args.shift(), args, unknown);
  616     } else {
  617       this.emit('*', args);
  618     }
  619   } else {
  620     outputHelpIfNecessary(this, unknown);
  621 
  622     // If there were no args and we have unknown options,
  623     // then they are extraneous and we need to error.
  624     if (unknown.length > 0) {
  625       this.unknownOption(unknown[0]);
  626     }
  627   }
  628 
  629   return this;
  630 };
  631 
  632 /**
  633  * Return an option matching `arg` if any.
  634  *
  635  * @param {String} arg
  636  * @return {Option}
  637  * @api private
  638  */
  639 
  640 Command.prototype.optionFor = function(arg) {
  641   for (var i = 0, len = this.options.length; i < len; ++i) {
  642     if (this.options[i].is(arg)) {
  643       return this.options[i];
  644     }
  645   }
  646 };
  647 
  648 /**
  649  * Parse options from `argv` returning `argv`
  650  * void of these options.
  651  *
  652  * @param {Array} argv
  653  * @return {Array}
  654  * @api public
  655  */
  656 
  657 Command.prototype.parseOptions = function(argv) {
  658   var args = []
  659     , len = argv.length
  660     , literal
  661     , option
  662     , arg;
  663 
  664   var unknownOptions = [];
  665 
  666   // parse options
  667   for (var i = 0; i < len; ++i) {
  668     arg = argv[i];
  669 
  670     // literal args after --
  671     if ('--' == arg) {
  672       literal = true;
  673       continue;
  674     }
  675 
  676     if (literal) {
  677       args.push(arg);
  678       continue;
  679     }
  680 
  681     // find matching Option
  682     option = this.optionFor(arg);
  683 
  684     // option is defined
  685     if (option) {
  686       // requires arg
  687       if (option.required) {
  688         arg = argv[++i];
  689         if (null == arg) return this.optionMissingArgument(option);
  690         this.emit(option.name(), arg);
  691       // optional arg
  692       } else if (option.optional) {
  693         arg = argv[i+1];
  694         if (null == arg || ('-' == arg[0] && '-' != arg)) {
  695           arg = null;
  696         } else {
  697           ++i;
  698         }
  699         this.emit(option.name(), arg);
  700       // bool
  701       } else {
  702         this.emit(option.name());
  703       }
  704       continue;
  705     }
  706 
  707     // looks like an option
  708     if (arg.length > 1 && '-' == arg[0]) {
  709       unknownOptions.push(arg);
  710 
  711       // If the next argument looks like it might be
  712       // an argument for this option, we pass it on.
  713       // If it isn't, then it'll simply be ignored
  714       if (argv[i+1] && '-' != argv[i+1][0]) {
  715         unknownOptions.push(argv[++i]);
  716       }
  717       continue;
  718     }
  719 
  720     // arg
  721     args.push(arg);
  722   }
  723 
  724   return { args: args, unknown: unknownOptions };
  725 };
  726 
  727 /**
  728  * Return an object containing options as key-value pairs
  729  *
  730  * @return {Object}
  731  * @api public
  732  */
  733 Command.prototype.opts = function() {
  734   var result = {}
  735     , len = this.options.length;
  736 
  737   for (var i = 0 ; i < len; i++) {
  738     var key = camelcase(this.options[i].name());
  739     result[key] = key === 'version' ? this._version : this[key];
  740   }
  741   return result;
  742 };
  743 
  744 /**
  745  * Argument `name` is missing.
  746  *
  747  * @param {String} name
  748  * @api private
  749  */
  750 
  751 Command.prototype.missingArgument = function(name) {
  752   console.error();
  753   console.error("  error: missing required argument `%s'", name);
  754   console.error();
  755   process.exit(1);
  756 };
  757 
  758 /**
  759  * `Option` is missing an argument, but received `flag` or nothing.
  760  *
  761  * @param {String} option
  762  * @param {String} flag
  763  * @api private
  764  */
  765 
  766 Command.prototype.optionMissingArgument = function(option, flag) {
  767   console.error();
  768   if (flag) {
  769     console.error("  error: option `%s' argument missing, got `%s'", option.flags, flag);
  770   } else {
  771     console.error("  error: option `%s' argument missing", option.flags);
  772   }
  773   console.error();
  774   process.exit(1);
  775 };
  776 
  777 /**
  778  * Unknown option `flag`.
  779  *
  780  * @param {String} flag
  781  * @api private
  782  */
  783 
  784 Command.prototype.unknownOption = function(flag) {
  785   if (this._allowUnknownOption) return;
  786   console.error();
  787   console.error("  error: unknown option `%s'", flag);
  788   console.error();
  789   process.exit(1);
  790 };
  791 
  792 /**
  793  * Variadic argument with `name` is not the last argument as required.
  794  *
  795  * @param {String} name
  796  * @api private
  797  */
  798 
  799 Command.prototype.variadicArgNotLast = function(name) {
  800   console.error();
  801   console.error("  error: variadic arguments must be last `%s'", name);
  802   console.error();
  803   process.exit(1);
  804 };
  805 
  806 /**
  807  * Set the program version to `str`.
  808  *
  809  * This method auto-registers the "-V, --version" flag
  810  * which will print the version number when passed.
  811  *
  812  * @param {String} str
  813  * @param {String} flags
  814  * @return {Command} for chaining
  815  * @api public
  816  */
  817 
  818 Command.prototype.version = function(str, flags) {
  819   if (0 == arguments.length) return this._version;
  820   this._version = str;
  821   flags = flags || '-V, --version';
  822   this.option(flags, 'output the version number');
  823   this.on('version', function() {
  824     process.stdout.write(str + '\n');
  825     process.exit(0);
  826   });
  827   return this;
  828 };
  829 
  830 /**
  831  * Set the description to `str`.
  832  *
  833  * @param {String} str
  834  * @return {String|Command}
  835  * @api public
  836  */
  837 
  838 Command.prototype.description = function(str) {
  839   if (0 === arguments.length) return this._description;
  840   this._description = str;
  841   return this;
  842 };
  843 
  844 /**
  845  * Set an alias for the command
  846  *
  847  * @param {String} alias
  848  * @return {String|Command}
  849  * @api public
  850  */
  851 
  852 Command.prototype.alias = function(alias) {
  853   if (0 == arguments.length) return this._alias;
  854   this._alias = alias;
  855   return this;
  856 };
  857 
  858 /**
  859  * Set / get the command usage `str`.
  860  *
  861  * @param {String} str
  862  * @return {String|Command}
  863  * @api public
  864  */
  865 
  866 Command.prototype.usage = function(str) {
  867   var args = this._args.map(function(arg) {
  868     return humanReadableArgName(arg);
  869   });
  870 
  871   var usage = '[options]'
  872     + (this.commands.length ? ' [command]' : '')
  873     + (this._args.length ? ' ' + args.join(' ') : '');
  874 
  875   if (0 == arguments.length) return this._usage || usage;
  876   this._usage = str;
  877 
  878   return this;
  879 };
  880 
  881 /**
  882  * Get the name of the command
  883  *
  884  * @param {String} name
  885  * @return {String|Command}
  886  * @api public
  887  */
  888 
  889 Command.prototype.name = function() {
  890   return this._name;
  891 };
  892 
  893 /**
  894  * Return the largest option length.
  895  *
  896  * @return {Number}
  897  * @api private
  898  */
  899 
  900 Command.prototype.largestOptionLength = function() {
  901   return this.options.reduce(function(max, option) {
  902     return Math.max(max, option.flags.length);
  903   }, 0);
  904 };
  905 
  906 /**
  907  * Return help for options.
  908  *
  909  * @return {String}
  910  * @api private
  911  */
  912 
  913 Command.prototype.optionHelp = function() {
  914   var width = this.largestOptionLength();
  915 
  916   // Prepend the help information
  917   return [pad('-h, --help', width) + '  ' + 'output usage information']
  918       .concat(this.options.map(function(option) {
  919         return pad(option.flags, width) + '  ' + option.description;
  920       }))
  921       .join('\n');
  922 };
  923 
  924 /**
  925  * Return command help documentation.
  926  *
  927  * @return {String}
  928  * @api private
  929  */
  930 
  931 Command.prototype.commandHelp = function() {
  932   if (!this.commands.length) return '';
  933 
  934   var commands = this.commands.filter(function(cmd) {
  935     return !cmd._noHelp;
  936   }).map(function(cmd) {
  937     var args = cmd._args.map(function(arg) {
  938       return humanReadableArgName(arg);
  939     }).join(' ');
  940 
  941     return [
  942       cmd._name
  943         + (cmd._alias ? '|' + cmd._alias : '')
  944         + (cmd.options.length ? ' [options]' : '')
  945         + ' ' + args
  946       , cmd.description()
  947     ];
  948   });
  949 
  950   var width = commands.reduce(function(max, command) {
  951     return Math.max(max, command[0].length);
  952   }, 0);
  953 
  954   return [
  955     ''
  956     , '  Commands:'
  957     , ''
  958     , commands.map(function(cmd) {
  959       var desc = cmd[1] ? '  ' + cmd[1] : '';
  960       return pad(cmd[0], width) + desc;
  961     }).join('\n').replace(/^/gm, '    ')
  962     , ''
  963   ].join('\n');
  964 };
  965 
  966 /**
  967  * Return program help documentation.
  968  *
  969  * @return {String}
  970  * @api private
  971  */
  972 
  973 Command.prototype.helpInformation = function() {
  974   var desc = [];
  975   if (this._description) {
  976     desc = [
  977       '  ' + this._description
  978       , ''
  979     ];
  980   }
  981 
  982   var cmdName = this._name;
  983   if (this._alias) {
  984     cmdName = cmdName + '|' + this._alias;
  985   }
  986   var usage = [
  987     ''
  988     ,'  Usage: ' + cmdName + ' ' + this.usage()
  989     , ''
  990   ];
  991 
  992   var cmds = [];
  993   var commandHelp = this.commandHelp();
  994   if (commandHelp) cmds = [commandHelp];
  995 
  996   var options = [
  997     '  Options:'
  998     , ''
  999     , '' + this.optionHelp().replace(/^/gm, '    ')
 1000     , ''
 1001     , ''
 1002   ];
 1003 
 1004   return usage
 1005     .concat(cmds)
 1006     .concat(desc)
 1007     .concat(options)
 1008     .join('\n');
 1009 };
 1010 
 1011 /**
 1012  * Output help information for this command
 1013  *
 1014  * @api public
 1015  */
 1016 
 1017 Command.prototype.outputHelp = function(cb) {
 1018   if (!cb) {
 1019     cb = function(passthru) {
 1020       return passthru;
 1021     }
 1022   }
 1023   process.stdout.write(cb(this.helpInformation()));
 1024   this.emit('--help');
 1025 };
 1026 
 1027 /**
 1028  * Output help information and exit.
 1029  *
 1030  * @api public
 1031  */
 1032 
 1033 Command.prototype.help = function(cb) {
 1034   this.outputHelp(cb);
 1035   process.exit();
 1036 };
 1037 
 1038 /**
 1039  * Camel-case the given `flag`
 1040  *
 1041  * @param {String} flag
 1042  * @return {String}
 1043  * @api private
 1044  */
 1045 
 1046 function camelcase(flag) {
 1047   return flag.split('-').reduce(function(str, word) {
 1048     return str + word[0].toUpperCase() + word.slice(1);
 1049   });
 1050 }
 1051 
 1052 /**
 1053  * Pad `str` to `width`.
 1054  *
 1055  * @param {String} str
 1056  * @param {Number} width
 1057  * @return {String}
 1058  * @api private
 1059  */
 1060 
 1061 function pad(str, width) {
 1062   var len = Math.max(0, width - str.length);
 1063   return str + Array(len + 1).join(' ');
 1064 }
 1065 
 1066 /**
 1067  * Output help information if necessary
 1068  *
 1069  * @param {Command} command to output help for
 1070  * @param {Array} array of options to search for -h or --help
 1071  * @api private
 1072  */
 1073 
 1074 function outputHelpIfNecessary(cmd, options) {
 1075   options = options || [];
 1076   for (var i = 0; i < options.length; i++) {
 1077     if (options[i] == '--help' || options[i] == '-h') {
 1078       cmd.outputHelp();
 1079       process.exit(0);
 1080     }
 1081   }
 1082 }
 1083 
 1084 /**
 1085  * Takes an argument an returns its human readable equivalent for help usage.
 1086  *
 1087  * @param {Object} arg
 1088  * @return {String}
 1089  * @api private
 1090  */
 1091 
 1092 function humanReadableArgName(arg) {
 1093   var nameOutput = arg.name + (arg.variadic === true ? '...' : '');
 1094 
 1095   return arg.required
 1096     ? '<' + nameOutput + '>'
 1097     : '[' + nameOutput + ']'
 1098 }
 1099 
 1100 // for versions before node v0.8 when there weren't `fs.existsSync`
 1101 function exists(file) {
 1102   try {
 1103     if (fs.statSync(file).isFile()) {
 1104       return true;
 1105     }
 1106   } catch (e) {
 1107     return false;
 1108   }
 1109 }
 1110