| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 | var assert = require('assert'),  path = require('path'),  Completion = require('./lib/completion'),  Parser = require('./lib/parser'),  Usage = require('./lib/usage'),  Validation = require('./lib/validation')Argv(process.argv.slice(2))var exports = module.exports = Argvfunction Argv (processArgs, cwd) {  processArgs = processArgs || [] // handle calling yargs().  var self = {}  var completion = null  var usage = null  var validation = null  if (!cwd) cwd = process.cwd()  self.$0 = process.argv    .slice(0, 2)    .map(function (x, i) {      // ignore the node bin, specify this in your      // bin file with #!/usr/bin/env node      if (i === 0 && /\b(node|iojs)$/.test(x)) return      var b = rebase(cwd, x)      return x.match(/^\//) && b.length < x.length      ? b : x    })    .join(' ').trim()  if (process.env._ !== undefined && process.argv[1] === process.env._) {    self.$0 = process.env._.replace(      path.dirname(process.execPath) + '/', ''    )  }  var options  self.resetOptions = self.reset = function () {    // put yargs back into its initial    // state, this is useful for creating a    // nested CLI.    options = {      array: [],      boolean: [],      string: [],      narg: {},      key: {},      alias: {},      default: {},      defaultDescription: {},      requiresArg: [],      count: [],      normalize: [],      config: []    }    usage = Usage(self) // handle usage output.    validation = Validation(self, usage) // handle arg validation.    completion = Completion(self, usage)    demanded = {}    exitProcess = true    strict = false    helpOpt = null    versionOpt = null    completionOpt = null    commandHandlers = {}    self.parsed = false    return self  }  self.resetOptions()  self.boolean = function (bools) {    options.boolean.push.apply(options.boolean, [].concat(bools))    return self  }  self.array = function (arrays) {    options.array.push.apply(options.array, [].concat(arrays))    return self  }  self.nargs = function (key, n) {    if (typeof key === 'object') {      Object.keys(key).forEach(function (k) {        self.nargs(k, key[k])      })    } else {      options.narg[key] = n    }    return self  }  self.normalize = function (strings) {    options.normalize.push.apply(options.normalize, [].concat(strings))    return self  }  self.config = function (configs) {    options.config.push.apply(options.config, [].concat(configs))    return self  }  self.example = function (cmd, description) {    usage.example(cmd, description)    return self  }  self.command = function (cmd, description, fn) {    usage.command(cmd, description)    if (fn) commandHandlers[cmd] = fn    return self  }  var commandHandlers = {}  self.getCommandHandlers = function () {    return commandHandlers  }  self.string = function (strings) {    options.string.push.apply(options.string, [].concat(strings))    return self  }  self.default = function (key, value, defaultDescription) {    if (typeof key === 'object') {      Object.keys(key).forEach(function (k) {        self.default(k, key[k])      })    } else {      if (typeof value === 'function') {        defaultDescription = usage.functionDescription(value, defaultDescription)        value = value.call()      }      options.defaultDescription[key] = defaultDescription      options.default[key] = value    }    return self  }  self.alias = function (x, y) {    if (typeof x === 'object') {      Object.keys(x).forEach(function (key) {        self.alias(key, x[key])      })    } else {      options.alias[x] = (options.alias[x] || []).concat(y)    }    return self  }  self.count = function (counts) {    options.count.push.apply(options.count, [].concat(counts))    return self  }  var demanded = {}  self.demand = self.required = self.require = function (keys, msg) {    if (typeof keys === 'number') {      if (!demanded._) demanded._ = { count: 0, msg: null }      demanded._.count += keys      demanded._.msg = msg    } else if (Array.isArray(keys)) {      keys.forEach(function (key) {        self.demand(key, msg)      })    } else {      if (typeof msg === 'string') {        demanded[keys] = { msg: msg }      } else if (msg === true || typeof msg === 'undefined') {        demanded[keys] = { msg: undefined }      }    }    return self  }  self.getDemanded = function () {    return demanded  }  self.requiresArg = function (requiresArgs) {    options.requiresArg.push.apply(options.requiresArg, [].concat(requiresArgs))    return self  }  self.implies = function (key, value) {    validation.implies(key, value)    return self  }  self.usage = function (msg, opts) {    if (!opts && typeof msg === 'object') {      opts = msg      msg = null    }    usage.usage(msg)    if (opts) self.options(opts)    return self  }  self.epilogue = self.epilog = function (msg) {    usage.epilog(msg)    return self  }  self.fail = function (f) {    usage.failFn(f)    return self  }  self.check = function (f) {    validation.check(f)    return self  }  self.defaults = self.default  self.describe = function (key, desc) {    options.key[key] = true    usage.describe(key, desc)    return self  }  self.parse = function (args) {    return parseArgs(args)  }  self.option = self.options = function (key, opt) {    if (typeof key === 'object') {      Object.keys(key).forEach(function (k) {        self.options(k, key[k])      })    } else {      assert(typeof opt === 'object', 'second argument to option must be an object')      options.key[key] = true // track manually set keys.      if (opt.alias) self.alias(key, opt.alias)      var demand = opt.demand || opt.required || opt.require      if (demand) {        self.demand(key, demand)      } if ('default' in opt) {        self.default(key, opt.default)      } if ('nargs' in opt) {        self.nargs(key, opt.nargs)      } if (opt.boolean || opt.type === 'boolean') {        self.boolean(key)        if (opt.alias) self.boolean(opt.alias)      } if (opt.array || opt.type === 'array') {        self.array(key)        if (opt.alias) self.array(opt.alias)      } if (opt.string || opt.type === 'string') {        self.string(key)        if (opt.alias) self.string(opt.alias)      } if (opt.count || opt.type === 'count') {        self.count(key)      }      var desc = opt.describe || opt.description || opt.desc      if (desc) {        self.describe(key, desc)      }      if (opt.requiresArg) {        self.requiresArg(key)      }    }    return self  }  self.getOptions = function () {    return options  }  self.wrap = function (cols) {    usage.wrap(cols)    return self  }  var strict = false  self.strict = function () {    strict = true    return self  }  self.getStrict = function () {    return strict  }  self.showHelp = function (level) {    if (!self.parsed) parseArgs(processArgs) // run parser, if it has not already been executed.    usage.showHelp(level)    return self  }  var versionOpt = null  self.version = function (ver, opt, msg) {    versionOpt = opt || 'version'    usage.version(ver)    self.boolean(versionOpt)    self.describe(versionOpt, msg || 'Show version number')    return self  }  var helpOpt = null  self.addHelpOpt = function (opt, msg) {    helpOpt = opt    self.boolean(opt)    self.describe(opt, msg || 'Show help')    return self  }  self.showHelpOnFail = function (enabled, message) {    usage.showHelpOnFail(enabled, message)    return self  }  var exitProcess = true  self.exitProcess = function (enabled) {    if (typeof enabled !== 'boolean') {      enabled = true    }    exitProcess = enabled    return self  }  self.getExitProcess = function () {    return exitProcess  }  self.help = function () {    if (arguments.length > 0) return self.addHelpOpt.apply(self, arguments)    if (!self.parsed) parseArgs(processArgs) // run parser, if it has not already been executed.    return usage.help()  }  var completionOpt = null,  completionCommand = null  self.completion = function (cmd, desc, fn) {    // a function to execute when generating    // completions can be provided as the second    // or third argument to completion.    if (typeof desc === 'function') {      fn = desc      desc = null    }    // register the completion command.    completionCommand = cmd    completionOpt = completion.completionKey    self.command(completionCommand, desc || 'generate bash completion script')    // a function can be provided    if (fn) completion.registerFunction(fn)    return self  }  self.showCompletionScript = function ($0) {    $0 = $0 || self.$0    console.log(completion.generateCompletionScript($0))    return self  }  self.getUsageInstance = function () {    return usage  }  self.getValidationInstance = function () {    return validation  }  self.terminalWidth = function () {    return require('window-size').width  }  Object.defineProperty(self, 'argv', {    get: function () {      var args = null      try {        args = parseArgs(processArgs)      } catch (err) {        usage.fail(err.message)      }      return args    },    enumerable: true  })  function parseArgs (args) {    var parsed = Parser(args, options),      argv = parsed.argv,      aliases = parsed.aliases    argv.$0 = self.$0    self.parsed = parsed    // generate a completion script for adding to ~/.bashrc.    if (completionCommand && ~argv._.indexOf(completionCommand)) {      self.showCompletionScript()      if (exitProcess) {        process.exit(0)      }    }    // if there's a handler associated with a    // command defer processing to it.    var handlerKeys = Object.keys(self.getCommandHandlers())    for (var i = 0, command; (command = handlerKeys[i]) !== undefined; i++) {      if (~argv._.indexOf(command)) {        self.getCommandHandlers()[command](self.reset())        return self.argv      }    }    Object.keys(argv).forEach(function (key) {      if (key === helpOpt && argv[key]) {        self.showHelp('log')        if (exitProcess) {          process.exit(0)        }      } else if (key === versionOpt && argv[key]) {        usage.showVersion()        if (exitProcess) {          process.exit(0)        }      } else if (key === completionOpt) {        // we allow for asynchronous completions,        // e.g., loading in a list of commands from an API.        completion.getCompletion(function (completions) {          ;(completions || []).forEach(function (completion) {            console.log(completion)          })          if (exitProcess) {            process.exit(0)          }        })        return      }    })    validation.nonOptionCount(argv)    validation.missingArgumentValue(argv)    validation.requiredArguments(argv)    if (strict) {      validation.unknownArguments(argv, aliases)    }    validation.customChecks(argv, aliases)    validation.implications(argv)    setPlaceholderKeys(argv)    return argv  }  function setPlaceholderKeys (argv) {    Object.keys(options.key).forEach(function (key) {      if (typeof argv[key] === 'undefined') argv[key] = undefined    })  }  sigletonify(self)  return self}// rebase an absolute path to a relative one with respect to a base directory// exported for testsexports.rebase = rebasefunction rebase (base, dir) {  return path.relative(base, dir)}/*  Hack an instance of Argv with process.argv into Argv    so people can do    require('yargs')(['--beeble=1','-z','zizzle']).argv    to parse a list of args and    require('yargs').argv    to get a parsed version of process.argv.*/function sigletonify (inst) {  Object.keys(inst).forEach(function (key) {    if (key === 'argv') {      Argv.__defineGetter__(key, inst.__lookupGetter__(key))    } else {      Argv[key] = typeof inst[key] === 'function'      ? inst[key].bind(inst)      : inst[key]    }  })}
 |