diff options
Diffstat (limited to 'node_modules/yargs/lib/command.js')
-rw-r--r-- | node_modules/yargs/lib/command.js | 115 |
1 files changed, 93 insertions, 22 deletions
diff --git a/node_modules/yargs/lib/command.js b/node_modules/yargs/lib/command.js index c1afc1c55..3567cf953 100644 --- a/node_modules/yargs/lib/command.js +++ b/node_modules/yargs/lib/command.js @@ -2,6 +2,8 @@ const path = require('path') const inspect = require('util').inspect const camelCase = require('camelcase') +const DEFAULT_MARKER = '*' + // handles parsing positional arguments, // and populating argv with said positional // arguments. @@ -10,8 +12,11 @@ module.exports = function (yargs, usage, validation) { var handlers = {} var aliasMap = {} + var defaultCommand self.addHandler = function (cmd, description, builder, handler) { var aliases = [] + handler = handler || function () {} + if (Array.isArray(cmd)) { aliases = cmd.slice(1) cmd = cmd[0] @@ -28,15 +33,50 @@ module.exports = function (yargs, usage, validation) { return } - var parsedCommand = parseCommand(cmd) + // parse positionals out of cmd string + var parsedCommand = self.parseCommand(cmd) + + // remove positional args from aliases only aliases = aliases.map(function (alias) { - alias = parseCommand(alias).cmd // remove positional args + return self.parseCommand(alias).cmd + }) + + // check for default and filter out '*'' + var isDefault = false + var parsedAliases = [parsedCommand.cmd].concat(aliases).filter(function (c) { + if (c === DEFAULT_MARKER) { + isDefault = true + return false + } + return true + }) + + // short-circuit if default with no aliases + if (isDefault && parsedAliases.length === 0) { + defaultCommand = { + original: cmd.replace(DEFAULT_MARKER, '').trim(), + handler: handler, + builder: builder || {}, + demanded: parsedCommand.demanded, + optional: parsedCommand.optional + } + return + } + + // shift cmd and aliases after filtering out '*' + if (isDefault) { + parsedCommand.cmd = parsedAliases[0] + aliases = parsedAliases.slice(1) + cmd = cmd.replace(DEFAULT_MARKER, parsedCommand.cmd) + } + + // populate aliasMap + aliases.forEach(function (alias) { aliasMap[alias] = parsedCommand.cmd - return alias }) if (description !== false) { - usage.command(cmd, description, aliases) + usage.command(cmd, description, isDefault, aliases) } handlers[parsedCommand.cmd] = { @@ -46,6 +86,8 @@ module.exports = function (yargs, usage, validation) { demanded: parsedCommand.demanded, optional: parsedCommand.optional } + + if (isDefault) defaultCommand = handlers[parsedCommand.cmd] } self.addDirectory = function (dir, context, req, callerFile, opts) { @@ -94,7 +136,7 @@ module.exports = function (yargs, usage, validation) { return false } - function parseCommand (cmd) { + self.parseCommand = function (cmd) { var extraSpacesStrippedCommand = cmd.replace(/\s{2,}/g, ' ') var splitCommand = extraSpacesStrippedCommand.split(/\s+(?![^[]*]|[^<]*>)/) var bregex = /\.*[\][<>]/g @@ -130,48 +172,71 @@ module.exports = function (yargs, usage, validation) { return handlers } - self.runCommand = function (command, yargs, parsed) { - var argv = parsed.argv - var commandHandler = handlers[command] || handlers[aliasMap[command]] - var innerArgv = argv + self.hasDefaultCommand = function () { + return !!defaultCommand + } + + self.runCommand = function (command, yargs, parsed, commandIndex) { + var aliases = parsed.aliases + var commandHandler = handlers[command] || handlers[aliasMap[command]] || defaultCommand var currentContext = yargs.getContext() var numFiles = currentContext.files.length var parentCommands = currentContext.commands.slice() - currentContext.commands.push(command) + + // what does yargs look like after the buidler is run? + var innerArgv = parsed.argv + var innerYargs = null + var positionalMap = {} + + if (command) currentContext.commands.push(command) if (typeof commandHandler.builder === 'function') { // a function can be provided, which builds // up a yargs chain and possibly returns it. - innerArgv = commandHandler.builder(yargs.reset(parsed.aliases)) + innerYargs = commandHandler.builder(yargs.reset(parsed.aliases)) // if the builder function did not yet parse argv with reset yargs // and did not explicitly set a usage() string, then apply the // original command string as usage() for consistent behavior with - // options object below + // options object below. if (yargs.parsed === false) { if (typeof yargs.getUsageInstance().getUsage() === 'undefined') { yargs.usage('$0 ' + (parentCommands.length ? parentCommands.join(' ') + ' ' : '') + commandHandler.original) } - innerArgv = innerArgv ? innerArgv.argv : yargs.argv + innerArgv = innerYargs ? innerYargs._parseArgs(null, null, true, commandIndex) : yargs._parseArgs(null, null, true, commandIndex) } else { innerArgv = yargs.parsed.argv } + + if (innerYargs && yargs.parsed === false) aliases = innerYargs.parsed.aliases + else aliases = yargs.parsed.aliases } else if (typeof commandHandler.builder === 'object') { // as a short hand, an object can instead be provided, specifying // the options that a command takes. - innerArgv = yargs.reset(parsed.aliases) - innerArgv.usage('$0 ' + (parentCommands.length ? parentCommands.join(' ') + ' ' : '') + commandHandler.original) + innerYargs = yargs.reset(parsed.aliases) + innerYargs.usage('$0 ' + (parentCommands.length ? parentCommands.join(' ') + ' ' : '') + commandHandler.original) Object.keys(commandHandler.builder).forEach(function (key) { - innerArgv.option(key, commandHandler.builder[key]) + innerYargs.option(key, commandHandler.builder[key]) }) - innerArgv = innerArgv.argv + innerArgv = innerYargs._parseArgs(null, null, true, commandIndex) + aliases = innerYargs.parsed.aliases + } + + if (!yargs._hasOutput()) { + positionalMap = populatePositionals(commandHandler, innerArgv, currentContext, yargs) } - if (!yargs._hasOutput()) populatePositionals(commandHandler, innerArgv, currentContext, yargs) + + // we apply validation post-hoc, so that custom + // checks get passed populated positional arguments. + if (!yargs._hasOutput()) yargs._runValidation(innerArgv, aliases, positionalMap, yargs.parsed.error) if (commandHandler.handler && !yargs._hasOutput()) { + yargs._setHasOutput() commandHandler.handler(innerArgv) } - currentContext.commands.pop() + + if (command) currentContext.commands.pop() numFiles = currentContext.files.length - numFiles if (numFiles > 0) currentContext.files.splice(numFiles * -1, numFiles) + return innerArgv } @@ -181,25 +246,27 @@ module.exports = function (yargs, usage, validation) { argv._ = argv._.slice(context.commands.length) // nuke the current commands var demanded = commandHandler.demanded.slice(0) var optional = commandHandler.optional.slice(0) + var positionalMap = {} validation.positionalCount(demanded.length, argv._.length) while (demanded.length) { var demand = demanded.shift() - populatePositional(demand, argv, yargs) + populatePositional(demand, argv, yargs, positionalMap) } while (optional.length) { var maybe = optional.shift() - populatePositional(maybe, argv, yargs) + populatePositional(maybe, argv, yargs, positionalMap) } argv._ = context.commands.concat(argv._) + return positionalMap } // populate a single positional argument and its // aliases onto argv. - function populatePositional (positional, argv, yargs) { + function populatePositional (positional, argv, yargs, positionalMap) { // "positional" consists of the positional.cmd, an array representing // the positional's name and aliases, and positional.variadic // indicating whether or not it is a variadic array. @@ -214,6 +281,7 @@ module.exports = function (yargs, usage, validation) { if (value) argv[cmd] = value else argv[cmd] = value = argv._.shift() } + positionalMap[cmd] = true postProcessPositional(yargs, argv, cmd) addCamelCaseExpansions(argv, cmd) } @@ -242,6 +310,7 @@ module.exports = function (yargs, usage, validation) { self.reset = function () { handlers = {} aliasMap = {} + defaultCommand = undefined return self } @@ -254,10 +323,12 @@ module.exports = function (yargs, usage, validation) { frozen = {} frozen.handlers = handlers frozen.aliasMap = aliasMap + frozen.defaultCommand = defaultCommand } self.unfreeze = function () { handlers = frozen.handlers aliasMap = frozen.aliasMap + defaultCommand = frozen.defaultCommand frozen = undefined } |