Вход Регистрация
Файл: error-kitty/node_modules/mocha/node_modules/commander/index.js
Строк: 924
<?php
/**
 * Module dependencies.
 */

var EventEmitter = require('events').EventEmitter;
var 
spawn = require('child_process').spawn;
var 
fs = require('fs');
var 
exists fs.existsSync;
var 
path = require('path');
var 
dirname path.dirname;
var 
basename path.basename;

/**
 * Expose the root command.
 */

exports module.exports = new Command;

/**
 * Expose `Command`.
 */

exports.Command Command;

/**
 * Expose `Option`.
 */

exports.Option Option;

/**
 * Initialize a new `Option` with the given `flags` and `description`.
 *
 * @param {String} flags
 * @param {String} description
 * @api public
 */

function Option(flagsdescription) {
  
this.flags flags;
  
this.required = ~flags.indexOf('<');
  
this.optional = ~flags.indexOf('[');
  
this.bool = !~flags.indexOf('-no-');
  
flags flags.split(/[ ,|]+/);
  if (
flags.length && !/^[[<]/.test(flags[1])) this.short flags.shift();
  
this.long flags.shift();
  
this.description description || '';
}

/**
 * Return option name.
 *
 * @return {String}
 * @api private
 */

Option.prototype.name = function(){
  return 
this.long
    
.replace('--''')
    .
replace('no-''');
};

/**
 * Check if `arg` matches the short or long flag.
 *
 * @param {String} arg
 * @return {Boolean}
 * @api private
 */

Option.prototype.is = function(arg){
  return 
arg == this.short
    
|| arg == this.long;
};

/**
 * Initialize a new `Command`.
 *
 * @param {String} name
 * @api public
 */

function Command(name) {
  
this.commands = [];
  
this.options = [];
  
this._execs = [];
  
this._args = [];
  
this._name name;
}

/**
 * Inherit from `EventEmitter.prototype`.
 */

Command.prototype.__proto__ EventEmitter.prototype;

/**
 * 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);
  *
 * @param {String} name
 * @param {String} [desc]
 * @return {Command} the new command
 * @api public
 */

Command.prototype.command = function(namedesc){
  var 
args name.split(/ +/);
  var 
cmd = new Command(args.shift());
  if (
desccmd.description(desc);
  if (
descthis.executables true;
  if (
descthis._execs[cmd._name] = true;
  
this.commands.push(cmd);
  
cmd.parseExpectedArgs(args);
  
cmd.parent this;
  if (
desc) return this;
  return 
cmd;
};

/**
 * Add an implicit `help [cmd]` subcommand
 * which invokes `--help` for the given command.
 *
 * @api private
 */

Command.prototype.addImplicitHelpCommand = function() {
  
this.command('help [cmd]''display help for [cmd]');
};

/**
 * Parse expected `args`.
 *
 * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`.
 *
 * @param {Array} args
 * @return {Command} for chaining
 * @api public
 */

Command.prototype.parseExpectedArgs = function(args){
  if (!
args.length) return;
  var 
self this;
  
args.forEach(function(arg){
    switch (
arg[0]) {
      case 
'<':
        
self._args.push({ requiredtruenamearg.slice(1, -1) });
        break;
      case 
'[':
        
self._args.push({ requiredfalsenamearg.slice(1, -1) });
        break;
    }
  });
  return 
this;
};

/**
 * Register callback `fn` for the command.
 *
 * Examples:
 *
 *      program
 *        .command('help')
 *        .description('display verbose help')
 *        .action(function(){
 *           // output help here
 *        });
 *
 * @param {Function} fn
 * @return {Command} for chaining
 * @api public
 */

Command.prototype.action = function(fn){
  var 
self this;
  
this.parent.on(this._name, function(argsunknown){    
    
// Parse any so-far unknown options
    
unknown unknown || [];
    var 
parsed self.parseOptions(unknown);
    
    
// Output help if necessary
    
outputHelpIfNecessary(selfparsed.unknown);
    
    
// If there are still any unknown options, then we simply 
    // 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]);
    }
    
    
// Leftover arguments need to be pushed back. Fixes issue #56
    
if (parsed.args.lengthargs parsed.args.concat(args);
    
    
self._args.forEach(function(argi){
      if (
arg.required && null == args[i]) {
        
self.missingArgument(arg.name);
      }
    });
    
    
// Always append ourselves to the end of the arguments,
    // to make sure we match the number of arguments the user
    // expects
    
if (self._args.length) {
      
args[self._args.length] = self;
    } else {
      
args.push(self);
    }
    
    
fn.apply(thisargs);
  });
  return 
this;
};

/**
 * 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]');
 *
 * @param {String} flags
 * @param {String} description
 * @param {Function|Mixed} fn or default
 * @param {Mixed} defaultValue
 * @return {Command} for chaining
 * @api public
 */

Command.prototype.option = function(flagsdescriptionfndefaultValue){
  var 
self this
    
option = new Option(flagsdescription)
    , 
oname option.name()
    , 
name camelcase(oname);

  
// default as 3rd arg
  
if ('function' != typeof fndefaultValue fnfn null;

  
// preassign default value only for --no-*, [optional], or <required>
  
if (false == option.bool || option.optional || option.required) {
    
// when --no-* we make sure default is true
    
if (false == option.booldefaultValue true;
    
// preassign only if we have a default
    
if (undefined !== defaultValueself[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 && fnval 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;
};

/**
 * Parse `argv`, settings options and invoking commands when defined.
 *
 * @param {Array} argv
 * @return {Command} for chaining
 * @api public
 */

Command.prototype.parse = function(argv){
  
// implicit help
  
if (this.executablesthis.addImplicitHelpCommand();

  
// store raw args
  
this.rawArgs argv;

  
// guess name
  
this._name this._name || basename(argv[1]);

  
// process argv
  
var parsed this.parseOptions(this.normalize(argv.slice(2)));
  var 
args this.args parsed.args;
 
  var 
result this.parseArgs(this.argsparsed.unknown);

  
// executable sub-commands
  
var name result.args[0];
  if (
this._execs[name]) return this.executeSubCommand(argvargsparsed.unknown);

  return 
result;
};

/**
 * Execute a sub-command executable.
 *
 * @param {Array} argv
 * @param {Array} args
 * @param {Array} unknown
 * @api private
 */

Command.prototype.executeSubCommand = function(argvargsunknown) {
  
args args.concat(unknown);

  if (!
args.lengththis.help();
  if (
'help' == args[0] && == args.lengththis.help();

  
// <cmd> --help
  
if ('help' == args[0]) {
    
args[0] = args[1];
    
args[1] = '--help';
  }

  
// executable
  
var dir dirname(argv[1]);
  var 
bin basename(argv[1]) + '-' args[0];

  
// check for ./<bin> first
  
var local path.join(dirbin);

  
// run it
  
args args.slice(1);
  var 
proc spawn(localargs, { stdio'inherit'customFds: [012] });
  
proc.on('error', function(err){
    if (
err.code == "ENOENT") {
      
console.error('n  %s(1) does not exist, try --helpn'bin);
    } else if (
err.code == "EACCES") {
      
console.error('n  %s(1) not executable. try chmod or run with rootn'bin);
    }
  });

  
this.runningCommand proc;
};

/**
 * Normalize `args`, splitting joined short flags. For example
 * the arg "-abc" is equivalent to "-a -b -c".
 * This also normalizes equal sign and splits "--abc=def" into "--abc def".
 *
 * @param {Array} args
 * @return {Array}
 * @api private
 */

Command.prototype.normalize = function(args){
  var 
ret = []
    , 
arg
    
index;

  for (var 
0len args.lengthlen; ++i) {
    
arg args[i];
    if (
arg.length && '-' == arg[0] && '-' != arg[1]) {
      
arg.slice(1).split('').forEach(function(c){
        
ret.push('-' c);
      });
    } else if (/^--/.
test(arg) && ~(index arg.indexOf('='))) {
      
ret.push(arg.slice(0index), arg.slice(index 1));
    } else {
      
ret.push(arg);
    }
  }

  return 
ret;
};

/**
 * Parse command `args`.
 *
 * When listener(s) are available those
 * callbacks are invoked, otherwise the "*"
 * event is emitted and those actions are invoked.
 *
 * @param {Array} args
 * @return {Command} for chaining
 * @api private
 */

Command.prototype.parseArgs = function(argsunknown){
  var 
cmds this.commands
    
len cmds.length
    
name;

  if (
args.length) {
    
name args[0];
    if (
this.listeners(name).length) {
      
this.emit(args.shift(), argsunknown);
    } else {
      
this.emit('*'args);
    }
  } else {
    
outputHelpIfNecessary(thisunknown);
    
    
// If there were no args and we have unknown options,
    // then they are extraneous and we need to error.
    
if (unknown.length 0) {      
      
this.unknownOption(unknown[0]);
    }
  }

  return 
this;
};

/**
 * Return an option matching `arg` if any.
 *
 * @param {String} arg
 * @return {Option}
 * @api private
 */

Command.prototype.optionFor = function(arg){
  for (var 
0len this.options.lengthlen; ++i) {
    if (
this.options[i].is(arg)) {
      return 
this.options[i];
    }
  }
};

/**
 * Parse options from `argv` returning `argv`
 * void of these options.
 *
 * @param {Array} argv
 * @return {Array}
 * @api public
 */

Command.prototype.parseOptions = function(argv){
  var 
args = []
    , 
len argv.length
    
literal
    
option
    
arg;

  var 
unknownOptions = [];

  
// parse options
  
for (var 0len; ++i) {
    
arg argv[i];

    
// literal args after --
    
if ('--' == arg) {
      
literal true;
      continue;
    }

    if (
literal) {
      
args.push(arg);
      continue;
    }

    
// find matching Option
    
option this.optionFor(arg);

    
// option is defined
    
if (option) {
      
// requires arg
      
if (option.required) {
        
arg argv[++i];
        if (
null == arg) return this.optionMissingArgument(option);
        if (
'-' == arg[0] && '-' != arg) return this.optionMissingArgument(optionarg);
        
this.emit(option.name(), arg);
      
// optional arg
      
} else if (option.optional) {
        
arg argv[i+1];
        if (
null == arg || ('-' == arg[0] && '-' != arg)) {
          
arg null;
        } else {
          ++
i;
        }
        
this.emit(option.name(), arg);
      
// bool
      
} else {
        
this.emit(option.name());
      }
      continue;
    }
    
    
// looks like an option
    
if (arg.length && '-' == arg[0]) {
      
unknownOptions.push(arg);
      
      
// 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]) {
        
unknownOptions.push(argv[++i]);
      }
      continue;
    }
    
    
// arg
    
args.push(arg);
  }
  
  return { 
argsargsunknownunknownOptions };
};

/**
 * Argument `name` is missing.
 *
 * @param {String} name
 * @api private
 */

Command.prototype.missingArgument = function(name){
  
console.error();
  
console.error("  error: missing required argument `%s'"name);
  
console.error();
  
process.exit(1);
};

/**
 * `Option` is missing an argument, but received `flag` or nothing.
 *
 * @param {String} option
 * @param {String} flag
 * @api private
 */

Command.prototype.optionMissingArgument = function(optionflag){
  
console.error();
  if (
flag) {
    
console.error("  error: option `%s' argument missing, got `%s'"option.flagsflag);
  } else {
    
console.error("  error: option `%s' argument missing"option.flags);
  }
  
console.error();
  
process.exit(1);
};

/**
 * Unknown option `flag`.
 *
 * @param {String} flag
 * @api private
 */

Command.prototype.unknownOption = function(flag){
  
console.error();
  
console.error("  error: unknown option `%s'"flag);
  
console.error();
  
process.exit(1);
};


/**
 * Set the program version to `str`.
 *
 * This method auto-registers the "-V, --version" flag
 * which will print the version number when passed.
 *
 * @param {String} str
 * @param {String} flags
 * @return {Command} for chaining
 * @api public
 */

Command.prototype.version = function(strflags){
  if (
== arguments.length) return this._version;
  
this._version str;
  
flags flags || '-V, --version';
  
this.option(flags'output the version number');
  
this.on('version', function(){
    
console.log(str);
    
process.exit(0);
  });
  return 
this;
};

/**
 * Set the description `str`.
 *
 * @param {String} str
 * @return {String|Command}
 * @api public
 */

Command.prototype.description = function(str){
  if (
== arguments.length) return this._description;
  
this._description str;
  return 
this;
};

/**
 * Set / get the command usage `str`.
 *
 * @param {String} str
 * @return {String|Command}
 * @api public
 */

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 (
== arguments.length) return this._usage || usage;
  
this._usage str;

  return 
this;
};

/**
 * Return the largest option length.
 *
 * @return {Number}
 * @api private
 */

Command.prototype.largestOptionLength = function(){
  return 
this.options.reduce(function(maxoption){
    return 
Math.max(maxoption.flags.length);
  }, 
0);
};

/**
 * Return help for options.
 *
 * @return {String}
 * @api private
 */

Command.prototype.optionHelp = function(){
  var 
width this.largestOptionLength();
  
  
// Prepend the help information
  
return [pad('-h, --help'width) + '  ' 'output usage information']
    .
concat(this.options.map(function(option){
      return 
pad(option.flagswidth)
        + 
'  ' option.description;
      }))
    .
join('n');
};

/**
 * Return command help documentation.
 *
 * @return {String}
 * @api private
 */

Command.prototype.commandHelp = function(){
  if (!
this.commands.length) return '';
  return [
      
''
    
'  Commands:'
    
''
    
this.commands.map(function(cmd){
      var 
args cmd._args.map(function(arg){
        return 
arg.required
          
'<' arg.name '>'
          
'[' arg.name ']';
      }).
join(' ');

      return 
pad(cmd._name
        
+ (cmd.options.length 
          
' [options]'
          
'') + ' ' args22)
        + (
cmd.description()
          ? 
' ' cmd.description()
          : 
'');
    }).
join('n').replace(/^/gm'    ')
    , 
''
  
].join('n');
};

/**
 * Return program help documentation.
 *
 * @return {String}
 * @api private
 */

Command.prototype.helpInformation = function(){
  return [
      
''
    
'  Usage: ' this._name ' ' this.usage()
    , 
'' this.commandHelp()
    , 
'  Options:'
    
''
    
'' this.optionHelp().replace(/^/gm'    ')
    , 
''
    
''
  
].join('n');
};

/**
 * Output help information for this command
 *
 * @api public
 */

Command.prototype.outputHelp = function(){
  
process.stdout.write(this.helpInformation());
  
this.emit('--help');
};

/**
 * Output help information and exit.
 *
 * @api public
 */

Command.prototype.help = function(){
  
this.outputHelp();
  
process.exit();
};

/**
 * Camel-case the given `flag`
 *
 * @param {String} flag
 * @return {String}
 * @api private
 */

function camelcase(flag) {
  return 
flag.split('-').reduce(function(strword){
    return 
str word[0].toUpperCase() + word.slice(1);
  });
}

/**
 * Pad `str` to `width`.
 *
 * @param {String} str
 * @param {Number} width
 * @return {String}
 * @api private
 */

function pad(strwidth) {
  var 
len Math.max(0width str.length);
  return 
str + Array(len 1).join(' ');
}

/**
 * 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
 */

function outputHelpIfNecessary(cmdoptions) {
  
options options || [];
  for (var 
0options.lengthi++) {
    if (
options[i] == '--help' || options[i] == '-h') {
      
cmd.outputHelp();
      
process.exit(0);
    }
  }
}
?>
Онлайн: 0
Реклама