Comparing version 3.7.1 to 3.7.2
## Change Log | ||
### v3.7.2 (2015/04/13 11:52 -07:00) | ||
* [679fbbf](https://github.com/bcoe/yargs/commit/679fbbf55904030ccee8a2635e8e5f46551ab2f0) updated yargs to use the [standard](https://github.com/feross/standard) style guide (agokjr) | ||
* [22382ee](https://github.com/bcoe/yargs/commit/22382ee9f5b495bc2586c1758cd1091cec3647f9 various bug fixes for $0 (@nylen) | ||
### v3.7.1 (2015/04/10 11:06 -07:00) | ||
@@ -4,0 +9,0 @@ |
785
index.js
@@ -6,491 +6,476 @@ var assert = require('assert'), | ||
Usage = require('./lib/usage'), | ||
Validation = require('./lib/validation'); | ||
Validation = require('./lib/validation') | ||
Argv(process.argv.slice(2)); | ||
Argv(process.argv.slice(2)) | ||
var exports = module.exports = Argv; | ||
var exports = module.exports = Argv | ||
function Argv (processArgs, cwd) { | ||
processArgs = processArgs || []; // handle calling yargs(). | ||
processArgs = processArgs || [] // handle calling yargs(). | ||
var self = {}; | ||
var completion = null; | ||
var usage = null; | ||
var validation = null; | ||
var self = {} | ||
var completion = null | ||
var usage = null | ||
var validation = null | ||
if (!cwd) cwd = process.cwd(); | ||
if (!cwd) cwd = process.cwd() | ||
self.$0 = process.argv | ||
.slice(0,2) | ||
.map(function (x) { | ||
// ignore the node bin, specify this in your | ||
// bin file with #!/usr/bin/env node | ||
if (~x.indexOf('node') || ~x.indexOf('iojs')) return; | ||
var b = rebase(cwd, x); | ||
return x.match(/^\//) && b.length < x.length | ||
? b : x | ||
}) | ||
.join(' ').trim(); | ||
; | ||
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) + '/', '' | ||
); | ||
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: [] | ||
} | ||
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) | ||
usage = Usage(self); // handle usage output. | ||
validation = Validation(self, usage); // handle arg validation. | ||
completion = Completion(self, usage); | ||
demanded = {} | ||
demanded = {}; | ||
exitProcess = true | ||
strict = false | ||
helpOpt = null | ||
versionOpt = null | ||
completionOpt = null | ||
exitProcess = true; | ||
strict = false; | ||
helpOpt = null; | ||
versionOpt = null; | ||
completionOpt = null; | ||
return self | ||
} | ||
self.resetOptions() | ||
return self; | ||
}; | ||
self.resetOptions(); | ||
self.boolean = function (bools) { | ||
options.boolean.push.apply(options.boolean, [].concat(bools)) | ||
return self | ||
} | ||
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.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.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.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.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.example = function (cmd, description) { | ||
usage.example(cmd, description); | ||
return self; | ||
}; | ||
self.command = function (cmd, description) { | ||
usage.command(cmd, description) | ||
return self | ||
} | ||
self.command = function (cmd, description) { | ||
usage.command(cmd, description); | ||
return self; | ||
}; | ||
self.string = function (strings) { | ||
options.string.push.apply(options.string, [].concat(strings)) | ||
return self | ||
} | ||
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.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.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 | ||
} | ||
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 } | ||
} | ||
} | ||
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 | ||
} | ||
return self; | ||
}; | ||
self.getDemanded = function() { | ||
return demanded; | ||
}; | ||
self.requiresArg = function (requiresArgs) { | ||
options.requiresArg.push.apply(options.requiresArg, [].concat(requiresArgs)) | ||
return self | ||
} | ||
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.implies = function (key, value) { | ||
validation.implies(key, value); | ||
return self; | ||
}; | ||
self.usage = function (msg, opts) { | ||
if (!opts && typeof msg === 'object') { | ||
opts = msg | ||
msg = null | ||
} | ||
self.usage = function (msg, opts) { | ||
if (!opts && typeof msg === 'object') { | ||
opts = msg; | ||
msg = null; | ||
} | ||
usage.usage(msg) | ||
usage.usage(msg); | ||
if (opts) self.options(opts) | ||
if (opts) self.options(opts); | ||
return self | ||
} | ||
return self; | ||
}; | ||
self.epilogue = self.epilog = function (msg) { | ||
usage.epilog(msg) | ||
return self | ||
} | ||
self.epilogue = self.epilog = function (msg) { | ||
usage.epilog(msg); | ||
return self; | ||
}; | ||
self.fail = function (f) { | ||
usage.failFn(f) | ||
return self | ||
} | ||
self.fail = function (f) { | ||
usage.failFn(f); | ||
return self; | ||
}; | ||
self.check = function (f) { | ||
validation.check(f) | ||
return self | ||
} | ||
self.check = function (f) { | ||
validation.check(f); | ||
return self; | ||
}; | ||
self.defaults = self.default | ||
self.defaults = self.default; | ||
self.describe = function (key, desc) { | ||
options.key[key] = true | ||
usage.describe(key, desc) | ||
return self | ||
} | ||
self.describe = function (key, desc) { | ||
options.key[key] = true; | ||
usage.describe(key, desc); | ||
return self; | ||
}; | ||
self.parse = function (args) { | ||
return parseArgs(args) | ||
} | ||
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') | ||
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. | ||
options.key[key] = true; // track manually set keys. | ||
if (opt.alias) self.alias(key, opt.alias) | ||
if (opt.alias) self.alias(key, opt.alias); | ||
var demand = opt.demand || opt.required || opt.require | ||
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) | ||
} | ||
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) | ||
} | ||
var desc = opt.describe || opt.description || opt.desc; | ||
if (desc) { | ||
self.describe(key, desc); | ||
} | ||
if (opt.requiresArg) { | ||
self.requiresArg(key) | ||
} | ||
} | ||
if (opt.requiresArg) { | ||
self.requiresArg(key); | ||
} | ||
} | ||
return self | ||
} | ||
self.getOptions = function () { | ||
return options | ||
} | ||
return self; | ||
}; | ||
self.getOptions = function() { | ||
return options; | ||
}; | ||
self.wrap = function (cols) { | ||
usage.wrap(cols) | ||
return self | ||
} | ||
self.wrap = function (cols) { | ||
usage.wrap(cols); | ||
return self; | ||
}; | ||
var strict = false | ||
self.strict = function () { | ||
strict = true | ||
return self | ||
} | ||
self.getStrict = function () { | ||
return strict | ||
} | ||
var strict = false; | ||
self.strict = function () { | ||
strict = true; | ||
return self; | ||
}; | ||
self.getStrict = function () { | ||
return strict; | ||
} | ||
self.showHelp = function (fn) { | ||
if (!self.parsed) parseArgs(processArgs) // run parser, if it has not already been executed. | ||
usage.showHelp(fn) | ||
return self | ||
} | ||
self.showHelp = function (fn) { | ||
if (!self.parsed) parseArgs(processArgs); // run parser, if it has not already been executed. | ||
usage.showHelp(fn); | ||
return self; | ||
}; | ||
var versionOpt = null | ||
self.version = function (ver, opt, msg) { | ||
versionOpt = opt || 'version' | ||
usage.version(ver) | ||
self.describe(versionOpt, msg || 'Show version number') | ||
return self | ||
} | ||
var versionOpt = null; | ||
self.version = function (ver, opt, msg) { | ||
versionOpt = opt || 'version'; | ||
usage.version(ver); | ||
self.describe(versionOpt, msg || 'Show version number'); | ||
return self; | ||
}; | ||
var helpOpt = null | ||
self.addHelpOpt = function (opt, msg) { | ||
helpOpt = opt | ||
self.describe(opt, msg || 'Show help') | ||
return self | ||
} | ||
var helpOpt = null; | ||
self.addHelpOpt = function (opt, msg) { | ||
helpOpt = opt; | ||
self.describe(opt, msg || 'Show help'); | ||
return self; | ||
}; | ||
self.showHelpOnFail = function (enabled, message) { | ||
usage.showHelpOnFail(enabled, message) | ||
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; | ||
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); | ||
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. | ||
if (!self.parsed) parseArgs(processArgs) // run parser, if it has not already been executed. | ||
return usage.help(); | ||
}; | ||
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; | ||
} | ||
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'); | ||
// 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); | ||
// a function can be provided | ||
if (fn) completion.registerFunction(fn) | ||
return self; | ||
}; | ||
return self | ||
} | ||
self.showCompletionScript = function($0) { | ||
$0 = $0 || self.$0; | ||
console.log(completion.generateCompletionScript($0)); | ||
return self; | ||
}; | ||
self.showCompletionScript = function ($0) { | ||
$0 = $0 || self.$0 | ||
console.log(completion.generateCompletionScript($0)) | ||
return self | ||
} | ||
self.getUsageInstance = function () { | ||
return usage; | ||
}; | ||
self.getUsageInstance = function () { | ||
return usage | ||
} | ||
self.getValidationInstance = function () { | ||
return validation; | ||
} | ||
self.getValidationInstance = function () { | ||
return validation | ||
} | ||
Object.defineProperty(self, 'argv', { | ||
get : function () { | ||
var args = null; | ||
Object.defineProperty(self, 'argv', { | ||
get: function () { | ||
var args = null | ||
try { | ||
args = parseArgs(processArgs); | ||
} catch (err) { | ||
usage.fail(err.message); | ||
} | ||
try { | ||
args = parseArgs(processArgs) | ||
} catch (err) { | ||
usage.fail(err.message) | ||
} | ||
return args; | ||
}, | ||
enumerable : true | ||
}); | ||
return args | ||
}, | ||
enumerable: true | ||
}) | ||
function parseArgs (args) { | ||
var parsed = Parser(args, options), | ||
argv = parsed.argv, | ||
aliases = parsed.aliases; | ||
function parseArgs (args) { | ||
var parsed = Parser(args, options), | ||
argv = parsed.argv, | ||
aliases = parsed.aliases | ||
argv.$0 = self.$0; | ||
argv.$0 = self.$0 | ||
self.parsed = parsed; | ||
self.parsed = parsed | ||
// generate a completion script for adding to ~/.bashrc. | ||
if (completionCommand && ~argv._.indexOf(completionCommand)) { | ||
self.showCompletionScript(); | ||
if (exitProcess){ | ||
process.exit(0); | ||
} | ||
// generate a completion script for adding to ~/.bashrc. | ||
if (completionCommand && ~argv._.indexOf(completionCommand)) { | ||
self.showCompletionScript() | ||
if (exitProcess) { | ||
process.exit(0) | ||
} | ||
} | ||
Object.keys(argv).forEach(function (key) { | ||
if (key === helpOpt) { | ||
self.showHelp('log') | ||
if (exitProcess) { | ||
process.exit(0) | ||
} | ||
} else if (key === versionOpt) { | ||
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) | ||
}) | ||
Object.keys(argv).forEach(function(key) { | ||
if (key === helpOpt) { | ||
self.showHelp('log'); | ||
if (exitProcess){ | ||
process.exit(0); | ||
} | ||
} | ||
else if (key === versionOpt) { | ||
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 | ||
} | ||
}) | ||
if (exitProcess){ | ||
process.exit(0); | ||
} | ||
}); | ||
return; | ||
} | ||
}); | ||
validation.nonOptionCount(argv) | ||
validation.missingArgumentValue(argv) | ||
validation.requiredArguments(argv) | ||
validation.nonOptionCount(argv); | ||
validation.missingArgumentValue(argv); | ||
validation.requiredArguments(argv); | ||
if (strict) { | ||
validation.unknownArguments(argv, aliases) | ||
} | ||
if (strict) { | ||
validation.unknownArguments(argv, aliases); | ||
} | ||
validation.customChecks(argv, aliases) | ||
validation.implications(argv) | ||
setPlaceholderKeys(argv) | ||
validation.customChecks(argv, aliases); | ||
validation.implications(argv); | ||
setPlaceholderKeys(argv); | ||
return argv | ||
} | ||
return argv; | ||
} | ||
function setPlaceholderKeys (argv) { | ||
Object.keys(options.key).forEach(function (key) { | ||
if (typeof argv[key] === 'undefined') argv[key] = undefined | ||
}) | ||
} | ||
function setPlaceholderKeys (argv) { | ||
Object.keys(options.key).forEach(function(key) { | ||
if (typeof argv[key] === 'undefined') argv[key] = undefined; | ||
}); | ||
} | ||
sigletonify(self) | ||
return self | ||
} | ||
sigletonify(self); | ||
return self; | ||
}; | ||
// rebase an absolute path to a relative one with respect to a base directory | ||
// exported for tests | ||
exports.rebase = rebase; | ||
exports.rebase = rebase | ||
function rebase (base, dir) { | ||
return path.relative(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 | ||
require('yargs')(['--beeble=1','-z','zizzle']).argv | ||
to parse a list of args and | ||
require('yargs').argv | ||
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]; | ||
} | ||
}); | ||
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] | ||
} | ||
}) | ||
} |
var fs = require('fs'), | ||
path = require('path'); | ||
path = require('path') | ||
@@ -9,3 +9,3 @@ // add bash completions to your | ||
completionKey: 'get-yargs-completions' | ||
}; | ||
} | ||
@@ -15,5 +15,5 @@ // get a list of completion commands. | ||
var completions = [], | ||
current = process.argv[process.argv.length - 1], | ||
previous = process.argv.slice(process.argv.indexOf('--' + self.completionKey) + 1), | ||
argv = yargs.parse(previous); | ||
current = process.argv[process.argv.length - 1], | ||
previous = process.argv.slice(process.argv.indexOf('--' + self.completionKey) + 1), | ||
argv = yargs.parse(previous) | ||
@@ -25,8 +25,8 @@ // a custom completion function can be provided | ||
// synchronous completion function. | ||
return done(completionFunction(current, argv)); | ||
return done(completionFunction(current, argv)) | ||
} else { | ||
// asynchronous completion function | ||
return completionFunction(current, argv, function(completions) { | ||
done(completions); | ||
}); | ||
return completionFunction(current, argv, function (completions) { | ||
done(completions) | ||
}) | ||
} | ||
@@ -36,15 +36,15 @@ } | ||
if (!current.match(/^-/)) { | ||
usage.getCommands().forEach(function(command) { | ||
completions.push(command[0]); | ||
}); | ||
usage.getCommands().forEach(function (command) { | ||
completions.push(command[0]) | ||
}) | ||
} | ||
if (current.match(/^-/)) { | ||
Object.keys(yargs.getOptions().key).forEach(function(key) { | ||
completions.push('--' + key); | ||
}); | ||
Object.keys(yargs.getOptions().key).forEach(function (key) { | ||
completions.push('--' + key) | ||
}) | ||
} | ||
done(completions); | ||
}; | ||
done(completions) | ||
} | ||
@@ -54,13 +54,13 @@ // generate the completion script to add to your .bashrc. | ||
var script = fs.readFileSync( | ||
path.resolve(__dirname, '../completion.sh.hbs'), | ||
'utf-8' | ||
), | ||
name = path.basename($0); | ||
path.resolve(__dirname, '../completion.sh.hbs'), | ||
'utf-8' | ||
), | ||
name = path.basename($0) | ||
// add ./to applications not yet installed as bin. | ||
if ($0.match(/\.js$/)) $0 = './' + $0; | ||
if ($0.match(/\.js$/)) $0 = './' + $0 | ||
script = script.replace(/{{app_name}}/g, name); | ||
return script.replace(/{{app_path}}/g, $0); | ||
}; | ||
script = script.replace(/{{app_name}}/g, name) | ||
return script.replace(/{{app_path}}/g, $0) | ||
} | ||
@@ -70,8 +70,8 @@ // register a function to perform your own custom | ||
// synchrnous or asynchronous. | ||
var completionFunction = null; | ||
var completionFunction = null | ||
self.registerFunction = function (fn) { | ||
completionFunction = fn; | ||
completionFunction = fn | ||
} | ||
return self; | ||
}; | ||
return self | ||
} |
// fancy-pants parsing of argv, originally forked | ||
// from minimist: https://www.npmjs.com/package/minimist | ||
var camelCase = require('camelcase'), | ||
fs = require('fs'), | ||
path = require('path'); | ||
path = require('path') | ||
function increment (orig) { | ||
return orig !== undefined ? orig + 1 : 0; | ||
return orig !== undefined ? orig + 1 : 0 | ||
} | ||
module.exports = function (args, opts) { | ||
if (!opts) opts = {}; | ||
var flags = { arrays: {}, bools : {}, strings : {}, counts: {}, normalize: {}, configs: {} }; | ||
if (!opts) opts = {} | ||
var flags = { arrays: {}, bools: {}, strings: {}, counts: {}, normalize: {}, configs: {} } | ||
[].concat(opts['array']).filter(Boolean).forEach(function (key) { | ||
flags.arrays[key] = true; | ||
}); | ||
;[].concat(opts['array']).filter(Boolean).forEach(function (key) { | ||
flags.arrays[key] = true | ||
}) | ||
[].concat(opts['boolean']).filter(Boolean).forEach(function (key) { | ||
flags.bools[key] = true; | ||
}); | ||
;[].concat(opts['boolean']).filter(Boolean).forEach(function (key) { | ||
flags.bools[key] = true | ||
}) | ||
[].concat(opts.string).filter(Boolean).forEach(function (key) { | ||
flags.strings[key] = true; | ||
}); | ||
;[].concat(opts.string).filter(Boolean).forEach(function (key) { | ||
flags.strings[key] = true | ||
}) | ||
[].concat(opts.count).filter(Boolean).forEach(function (key) { | ||
flags.counts[key] = true; | ||
}); | ||
;[].concat(opts.count).filter(Boolean).forEach(function (key) { | ||
flags.counts[key] = true | ||
}) | ||
[].concat(opts.normalize).filter(Boolean).forEach(function (key) { | ||
flags.normalize[key] = true; | ||
}); | ||
;[].concat(opts.normalize).filter(Boolean).forEach(function (key) { | ||
flags.normalize[key] = true | ||
}) | ||
[].concat(opts.config).filter(Boolean).forEach(function (key) { | ||
flags.configs[key] = true; | ||
}); | ||
;[].concat(opts.config).filter(Boolean).forEach(function (key) { | ||
flags.configs[key] = true | ||
}) | ||
var aliases = {}, | ||
newAliases = {}; | ||
var aliases = {}, | ||
newAliases = {} | ||
extendAliases(opts.key); | ||
extendAliases(opts.alias); | ||
extendAliases(opts.key) | ||
extendAliases(opts.alias) | ||
var defaults = opts['default'] || {}; | ||
Object.keys(defaults).forEach(function (key) { | ||
if (/-/.test(key) && !opts.alias[key]) { | ||
var c = camelCase(key); | ||
aliases[key] = aliases[key] || []; | ||
} | ||
(aliases[key] || []).forEach(function (alias) { | ||
defaults[alias] = defaults[key]; | ||
}); | ||
}); | ||
var argv = { _ : [] }; | ||
Object.keys(flags.bools).forEach(function (key) { | ||
setArg(key, !(key in defaults) ? false : defaults[key]); | ||
}); | ||
var notFlags = []; | ||
if (args.indexOf('--') !== -1) { | ||
notFlags = args.slice(args.indexOf('--')+1); | ||
args = args.slice(0, args.indexOf('--')); | ||
var defaults = opts['default'] || {} | ||
Object.keys(defaults).forEach(function (key) { | ||
if (/-/.test(key) && !opts.alias[key]) { | ||
aliases[key] = aliases[key] || [] | ||
} | ||
(aliases[key] || []).forEach(function (alias) { | ||
defaults[alias] = defaults[key] | ||
}) | ||
}) | ||
for (var i = 0; i < args.length; i++) { | ||
var arg = args[i]; | ||
var argv = { _: [] } | ||
// -- seperated by = | ||
if (arg.match(/^--.+=/)) { | ||
// Using [\s\S] instead of . because js doesn't support the | ||
// 'dotall' regex modifier. See: | ||
// http://stackoverflow.com/a/1068308/13216 | ||
var m = arg.match(/^--([^=]+)=([\s\S]*)$/); | ||
setArg(m[1], m[2]); | ||
} | ||
else if (arg.match(/^--no-.+/)) { | ||
var key = arg.match(/^--no-(.+)/)[1]; | ||
setArg(key, false); | ||
} | ||
// -- seperated by space. | ||
else if (arg.match(/^--.+/)) { | ||
var key = arg.match(/^--(.+)/)[1]; | ||
Object.keys(flags.bools).forEach(function (key) { | ||
setArg(key, !(key in defaults) ? false : defaults[key]) | ||
}) | ||
if (checkAllAliases(key, opts.narg)) { | ||
i = eatNargs(i, key, args); | ||
} else { | ||
var next = args[i + 1]; | ||
var notFlags = [] | ||
if (args.indexOf('--') !== -1) { | ||
notFlags = args.slice(args.indexOf('--') + 1) | ||
args = args.slice(0, args.indexOf('--')) | ||
} | ||
if (next !== undefined && !next.match(/^-/) | ||
&& !checkAllAliases(key, flags.bools) | ||
&& !checkAllAliases(key, flags.counts)) { | ||
setArg(key, next); | ||
i++; | ||
} | ||
else if (/^(true|false)$/.test(next)) { | ||
setArg(key, next); | ||
i++; | ||
} | ||
else { | ||
setArg(key, defaultForType(guessType(key, flags))); | ||
} | ||
} | ||
} | ||
// dot-notation flag seperated by '='. | ||
else if (arg.match(/^-.\..+=/)) { | ||
var m = arg.match(/^-([^=]+)=([\s\S]*)$/); | ||
setArg(m[1], m[2]); | ||
} | ||
// dot-notation flag seperated by space. | ||
else if (arg.match(/^-.\..+/)) { | ||
var key = arg.match(/^-(.\..+)/)[1]; | ||
var next = args[i + 1]; | ||
if (next !== undefined && !next.match(/^-/) | ||
&& !checkAllAliases(key, flags.bools) | ||
&& !checkAllAliases(key, flags.counts)) { | ||
setArg(key, next); | ||
i++; | ||
} | ||
else { | ||
setArg(key, defaultForType(guessType(key, flags))); | ||
} | ||
} | ||
else if (arg.match(/^-[^-]+/)) { | ||
var letters = arg.slice(1,-1).split(''); | ||
for (var i = 0; i < args.length; i++) { | ||
var arg = args[i], | ||
broken, | ||
key, | ||
letters, | ||
m, | ||
next | ||
var broken = false; | ||
for (var j = 0; j < letters.length; j++) { | ||
var next = arg.slice(j+2); | ||
// -- seperated by = | ||
if (arg.match(/^--.+=/)) { | ||
// Using [\s\S] instead of . because js doesn't support the | ||
// 'dotall' regex modifier. See: | ||
// http://stackoverflow.com/a/1068308/13216 | ||
m = arg.match(/^--([^=]+)=([\s\S]*)$/) | ||
setArg(m[1], m[2]) | ||
} else if (arg.match(/^--no-.+/)) { | ||
key = arg.match(/^--no-(.+)/)[1] | ||
setArg(key, false) | ||
if (letters[j+1] && letters[j+1] === '=') { | ||
setArg(letters[j], arg.slice(j+3)); | ||
broken = true; | ||
break; | ||
} | ||
// -- seperated by space. | ||
} else if (arg.match(/^--.+/)) { | ||
key = arg.match(/^--(.+)/)[1] | ||
if (next === '-') { | ||
setArg(letters[j], next) | ||
continue; | ||
} | ||
if (/[A-Za-z]/.test(letters[j]) | ||
&& /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { | ||
setArg(letters[j], next); | ||
broken = true; | ||
break; | ||
} | ||
if (letters[j+1] && letters[j+1].match(/\W/)) { | ||
setArg(letters[j], arg.slice(j+2)); | ||
broken = true; | ||
break; | ||
} | ||
else { | ||
setArg(letters[j], defaultForType(guessType(letters[j], flags))); | ||
} | ||
} | ||
if (checkAllAliases(key, opts.narg)) { | ||
i = eatNargs(i, key, args) | ||
} else { | ||
next = args[i + 1] | ||
var key = arg.slice(-1)[0]; | ||
if (!broken && key !== '-') { | ||
if (checkAllAliases(key, opts.narg)) { | ||
i = eatNargs(i, key, args); | ||
} else { | ||
if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) | ||
&& !checkAllAliases(key, flags.bools) | ||
&& !checkAllAliases(key, flags.counts)) { | ||
setArg(key, args[i+1]); | ||
i++; | ||
} | ||
else if (args[i+1] && /true|false/.test(args[i+1])) { | ||
setArg(key, args[i+1]); | ||
i++; | ||
} | ||
else { | ||
setArg(key, defaultForType(guessType(key, flags))); | ||
} | ||
} | ||
} | ||
if (next !== undefined && !next.match(/^-/) | ||
&& !checkAllAliases(key, flags.bools) | ||
&& !checkAllAliases(key, flags.counts)) { | ||
setArg(key, next) | ||
i++ | ||
} else if (/^(true|false)$/.test(next)) { | ||
setArg(key, next) | ||
i++ | ||
} else { | ||
setArg(key, defaultForType(guessType(key, flags))) | ||
} | ||
else { | ||
argv._.push( | ||
flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) | ||
); | ||
} | ||
} | ||
} | ||
setConfig(argv); | ||
applyDefaultsAndAliases(argv, aliases, defaults); | ||
// dot-notation flag seperated by '='. | ||
} else if (arg.match(/^-.\..+=/)) { | ||
m = arg.match(/^-([^=]+)=([\s\S]*)$/) | ||
setArg(m[1], m[2]) | ||
Object.keys(flags.counts).forEach(function (key) { | ||
setArg(key, defaults[key]); | ||
}); | ||
// dot-notation flag seperated by space. | ||
} else if (arg.match(/^-.\..+/)) { | ||
next = args[i + 1] | ||
key = arg.match(/^-(.\..+)/)[1] | ||
notFlags.forEach(function(key) { | ||
argv._.push(key); | ||
}); | ||
if (next !== undefined && !next.match(/^-/) | ||
&& !checkAllAliases(key, flags.bools) | ||
&& !checkAllAliases(key, flags.counts)) { | ||
setArg(key, next) | ||
i++ | ||
} else { | ||
setArg(key, defaultForType(guessType(key, flags))) | ||
} | ||
} else if (arg.match(/^-[^-]+/)) { | ||
letters = arg.slice(1, -1).split('') | ||
broken = false | ||
// how many arguments should we consume, based | ||
// on the nargs option? | ||
function eatNargs (i, key, args) { | ||
var toEat = checkAllAliases(key, opts.narg); | ||
for (var j = 0; j < letters.length; j++) { | ||
next = arg.slice(j + 2) | ||
if (args.length - (i + 1) < toEat) throw Error('not enough arguments following: ' + key); | ||
if (letters[j + 1] && letters[j + 1] === '=') { | ||
setArg(letters[j], arg.slice(j + 3)) | ||
broken = true | ||
break | ||
} | ||
for (var ii = i + 1; ii < (toEat + i + 1); ii++) { | ||
setArg(key, args[ii]); | ||
if (next === '-') { | ||
setArg(letters[j], next) | ||
continue | ||
} | ||
return (i + toEat); | ||
} | ||
function setArg (key, val) { | ||
// handle parsing boolean arguments --foo=true --bar false. | ||
if (checkAllAliases(key, flags.bools) || checkAllAliases(key, flags.counts)) { | ||
if (typeof val === 'string') val = val === 'true'; | ||
if (/[A-Za-z]/.test(letters[j]) | ||
&& /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { | ||
setArg(letters[j], next) | ||
broken = true | ||
break | ||
} | ||
if (/-/.test(key) && !(aliases[key] && aliases[key].length)) { | ||
var c = camelCase(key); | ||
aliases[key] = [c]; | ||
newAliases[c] = true; | ||
if (letters[j + 1] && letters[j + 1].match(/\W/)) { | ||
setArg(letters[j], arg.slice(j + 2)) | ||
broken = true | ||
break | ||
} else { | ||
setArg(letters[j], defaultForType(guessType(letters[j], flags))) | ||
} | ||
} | ||
var value = !checkAllAliases(key, flags.strings) && isNumber(val) ? Number(val) : val; | ||
key = arg.slice(-1)[0] | ||
if (checkAllAliases(key, flags.counts)) { | ||
value = increment; | ||
if (!broken && key !== '-') { | ||
if (checkAllAliases(key, opts.narg)) { | ||
i = eatNargs(i, key, args) | ||
} else { | ||
if (args[i + 1] && !/^(-|--)[^-]/.test(args[i + 1]) | ||
&& !checkAllAliases(key, flags.bools) | ||
&& !checkAllAliases(key, flags.counts)) { | ||
setArg(key, args[i + 1]) | ||
i++ | ||
} else if (args[i + 1] && /true|false/.test(args[i + 1])) { | ||
setArg(key, args[i + 1]) | ||
i++ | ||
} else { | ||
setArg(key, defaultForType(guessType(key, flags))) | ||
} | ||
} | ||
} | ||
} else { | ||
argv._.push( | ||
flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) | ||
) | ||
} | ||
} | ||
var splitKey = key.split('.'); | ||
setKey(argv, splitKey, value); | ||
setConfig(argv) | ||
applyDefaultsAndAliases(argv, aliases, defaults) | ||
(aliases[splitKey[0]] || []).forEach(function (x) { | ||
x = x.split('.'); | ||
Object.keys(flags.counts).forEach(function (key) { | ||
setArg(key, defaults[key]) | ||
}) | ||
// handle populating dot notation for both | ||
// the key and its aliases. | ||
if (splitKey.length > 1) { | ||
var a = [].concat(splitKey); | ||
a.shift(); // nuke the old key. | ||
x = x.concat(a); | ||
} | ||
notFlags.forEach(function (key) { | ||
argv._.push(key) | ||
}) | ||
setKey(argv, x, value); | ||
}); | ||
// how many arguments should we consume, based | ||
// on the nargs option? | ||
function eatNargs (i, key, args) { | ||
var toEat = checkAllAliases(key, opts.narg) | ||
var keys = [key].concat(aliases[key] || []); | ||
for (var i = 0, l = keys.length; i < l; i++) { | ||
if (flags.normalize[keys[i]]) { | ||
keys.forEach(function(key) { | ||
argv.__defineSetter__(key, function(v) { | ||
val = path.normalize(v); | ||
}); | ||
if (args.length - (i + 1) < toEat) throw Error('not enough arguments following: ' + key) | ||
argv.__defineGetter__(key, function () { | ||
return typeof val === 'string' ? | ||
path.normalize(val) : val; | ||
}); | ||
}); | ||
break; | ||
} | ||
} | ||
for (var ii = i + 1; ii < (toEat + i + 1); ii++) { | ||
setArg(key, args[ii]) | ||
} | ||
// set args from config.json file, this should be | ||
// applied last so that defaults can be applied. | ||
function setConfig (argv) { | ||
var configLookup = {}; | ||
return (i + toEat) | ||
} | ||
// expand defaults/aliases, in-case any happen to reference | ||
// the config.json file. | ||
applyDefaultsAndAliases(configLookup, aliases, defaults); | ||
function setArg (key, val) { | ||
// handle parsing boolean arguments --foo=true --bar false. | ||
if (checkAllAliases(key, flags.bools) || checkAllAliases(key, flags.counts)) { | ||
if (typeof val === 'string') val = val === 'true' | ||
} | ||
Object.keys(flags.configs).forEach(function(configKey) { | ||
var configPath = argv[configKey] || configLookup[configKey]; | ||
if (configPath) { | ||
try { | ||
var config = require(path.resolve(process.cwd(), configPath)); | ||
Object.keys(config).forEach(function (key) { | ||
// setting arguments via CLI takes precedence over | ||
// values within the config file. | ||
if (argv[key] === undefined) { | ||
delete argv[key]; | ||
setArg(key, config[key]); | ||
} | ||
}); | ||
} catch (ex) { | ||
throw Error('invalid json config file: ' + configPath); | ||
} | ||
} | ||
}); | ||
if (/-/.test(key) && !(aliases[key] && aliases[key].length)) { | ||
var c = camelCase(key) | ||
aliases[key] = [c] | ||
newAliases[c] = true | ||
} | ||
function applyDefaultsAndAliases(obj, aliases, defaults) { | ||
Object.keys(defaults).forEach(function (key) { | ||
if (!hasKey(obj, key.split('.'))) { | ||
setKey(obj, key.split('.'), defaults[key]); | ||
var value = !checkAllAliases(key, flags.strings) && isNumber(val) ? Number(val) : val | ||
(aliases[key] || []).forEach(function (x) { | ||
setKey(obj, x.split('.'), defaults[key]); | ||
}); | ||
} | ||
}); | ||
if (checkAllAliases(key, flags.counts)) { | ||
value = increment | ||
} | ||
function hasKey (obj, keys) { | ||
var o = obj; | ||
keys.slice(0,-1).forEach(function (key) { | ||
o = (o[key] || {}); | ||
}); | ||
var splitKey = key.split('.') | ||
setKey(argv, splitKey, value) | ||
var key = keys[keys.length - 1]; | ||
return key in o; | ||
} | ||
;(aliases[splitKey[0]] || []).forEach(function (x) { | ||
x = x.split('.') | ||
function setKey (obj, keys, value) { | ||
var o = obj; | ||
keys.slice(0,-1).forEach(function (key) { | ||
if (o[key] === undefined) o[key] = {}; | ||
o = o[key]; | ||
}); | ||
// handle populating dot notation for both | ||
// the key and its aliases. | ||
if (splitKey.length > 1) { | ||
var a = [].concat(splitKey) | ||
a.shift() // nuke the old key. | ||
x = x.concat(a) | ||
} | ||
var key = keys[keys.length - 1]; | ||
if (value === increment) { | ||
o[key] = increment(o[key]); | ||
} | ||
else if (o[key] === undefined && checkAllAliases(key, flags.arrays)) { | ||
o[key] = Array.isArray(value) ? value : [value]; | ||
} | ||
else if (o[key] === undefined || typeof o[key] === 'boolean') { | ||
o[key] = value; | ||
} | ||
else if (Array.isArray(o[key])) { | ||
o[key].push(value); | ||
} | ||
else { | ||
o[key] = [ o[key], value ]; | ||
} | ||
setKey(argv, x, value) | ||
}) | ||
var keys = [key].concat(aliases[key] || []) | ||
for (var i = 0, l = keys.length; i < l; i++) { | ||
if (flags.normalize[keys[i]]) { | ||
keys.forEach(function (key) { | ||
argv.__defineSetter__(key, function (v) { | ||
val = path.normalize(v) | ||
}) | ||
argv.__defineGetter__(key, function () { | ||
return typeof val === 'string' ? | ||
path.normalize(val) : val | ||
}) | ||
}) | ||
break | ||
} | ||
} | ||
} | ||
// extend the aliases list with inferred aliases. | ||
function extendAliases (obj) { | ||
Object.keys(obj || {}).forEach(function(key) { | ||
aliases[key] = [].concat(opts.alias[key] || []); | ||
// For "--option-name", also set argv.optionName | ||
aliases[key].concat(key).forEach(function (x) { | ||
if (/-/.test(x)) { | ||
var c = camelCase(x); | ||
aliases[key].push(c); | ||
newAliases[c] = true; | ||
// set args from config.json file, this should be | ||
// applied last so that defaults can be applied. | ||
function setConfig (argv) { | ||
var configLookup = {} | ||
// expand defaults/aliases, in-case any happen to reference | ||
// the config.json file. | ||
applyDefaultsAndAliases(configLookup, aliases, defaults) | ||
Object.keys(flags.configs).forEach(function (configKey) { | ||
var configPath = argv[configKey] || configLookup[configKey] | ||
if (configPath) { | ||
try { | ||
var config = require(path.resolve(process.cwd(), configPath)) | ||
Object.keys(config).forEach(function (key) { | ||
// setting arguments via CLI takes precedence over | ||
// values within the config file. | ||
if (argv[key] === undefined) { | ||
delete argv[key] | ||
setArg(key, config[key]) | ||
} | ||
}); | ||
aliases[key].forEach(function (x) { | ||
aliases[x] = [key].concat(aliases[key].filter(function (y) { | ||
return x !== y; | ||
})); | ||
}); | ||
}); | ||
} | ||
}) | ||
} catch (ex) { | ||
throw Error('invalid json config file: ' + configPath) | ||
} | ||
} | ||
}) | ||
} | ||
// check if a flag is set for any of a key's aliases. | ||
function checkAllAliases (key, flag) { | ||
var isSet = false, | ||
toCheck = [].concat(aliases[key] || [], key); | ||
function applyDefaultsAndAliases (obj, aliases, defaults) { | ||
Object.keys(defaults).forEach(function (key) { | ||
if (!hasKey(obj, key.split('.'))) { | ||
setKey(obj, key.split('.'), defaults[key]) | ||
toCheck.forEach(function(key) { | ||
if (flag[key]) isSet = flag[key]; | ||
}); | ||
;(aliases[key] || []).forEach(function (x) { | ||
setKey(obj, x.split('.'), defaults[key]) | ||
}) | ||
} | ||
}) | ||
} | ||
return isSet; | ||
}; | ||
function hasKey (obj, keys) { | ||
var o = obj | ||
keys.slice(0, -1).forEach(function (key) { | ||
o = (o[key] || {}) | ||
}) | ||
// return a default value, given the type of a flag., | ||
// e.g., key of type 'string' will default to '', rather than 'true'. | ||
function defaultForType (type) { | ||
var def = { | ||
boolean: true, | ||
string: '', | ||
array: [] | ||
}; | ||
var key = keys[keys.length - 1] | ||
return key in o | ||
} | ||
return def[type]; | ||
function setKey (obj, keys, value) { | ||
var o = obj | ||
keys.slice(0, -1).forEach(function (key) { | ||
if (o[key] === undefined) o[key] = {} | ||
o = o[key] | ||
}) | ||
var key = keys[keys.length - 1] | ||
if (value === increment) { | ||
o[key] = increment(o[key]) | ||
} else if (o[key] === undefined && checkAllAliases(key, flags.arrays)) { | ||
o[key] = Array.isArray(value) ? value : [value] | ||
} else if (o[key] === undefined || typeof o[key] === 'boolean') { | ||
o[key] = value | ||
} else if (Array.isArray(o[key])) { | ||
o[key].push(value) | ||
} else { | ||
o[key] = [ o[key], value ] | ||
} | ||
} | ||
// given a flag, enforce a default type. | ||
function guessType (key, flags) { | ||
var type = 'boolean'; | ||
// extend the aliases list with inferred aliases. | ||
function extendAliases (obj) { | ||
Object.keys(obj || {}).forEach(function (key) { | ||
aliases[key] = [].concat(opts.alias[key] || []) | ||
// For "--option-name", also set argv.optionName | ||
aliases[key].concat(key).forEach(function (x) { | ||
if (/-/.test(x)) { | ||
var c = camelCase(x) | ||
aliases[key].push(c) | ||
newAliases[c] = true | ||
} | ||
}) | ||
aliases[key].forEach(function (x) { | ||
aliases[x] = [key].concat(aliases[key].filter(function (y) { | ||
return x !== y | ||
})) | ||
}) | ||
}) | ||
} | ||
if (flags.strings && flags.strings[key]) type = 'string'; | ||
else if (flags.arrays && flags.arrays[key]) type = 'array'; | ||
// check if a flag is set for any of a key's aliases. | ||
function checkAllAliases (key, flag) { | ||
var isSet = false, | ||
toCheck = [].concat(aliases[key] || [], key) | ||
return type; | ||
} | ||
toCheck.forEach(function (key) { | ||
if (flag[key]) isSet = flag[key] | ||
}) | ||
function isNumber (x) { | ||
if (typeof x === 'number') return true; | ||
if (/^0x[0-9a-f]+$/i.test(x)) return true; | ||
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); | ||
return isSet | ||
} | ||
// return a default value, given the type of a flag., | ||
// e.g., key of type 'string' will default to '', rather than 'true'. | ||
function defaultForType (type) { | ||
var def = { | ||
boolean: true, | ||
string: '', | ||
array: [] | ||
} | ||
return { | ||
argv: argv, | ||
aliases: aliases, | ||
newAliases: newAliases | ||
}; | ||
}; | ||
return def[type] | ||
} | ||
// given a flag, enforce a default type. | ||
function guessType (key, flags) { | ||
var type = 'boolean' | ||
if (flags.strings && flags.strings[key]) type = 'string' | ||
else if (flags.arrays && flags.arrays[key]) type = 'array' | ||
return type | ||
} | ||
function isNumber (x) { | ||
if (typeof x === 'number') return true | ||
if (/^0x[0-9a-f]+$/i.test(x)) return true | ||
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x) | ||
} | ||
return { | ||
argv: argv, | ||
aliases: aliases, | ||
newAliases: newAliases | ||
} | ||
} |
651
lib/usage.js
@@ -5,403 +5,398 @@ // this file handles outputting usage instructions, | ||
wordwrap = require('wordwrap'), | ||
wsize = require('window-size'); | ||
wsize = require('window-size') | ||
module.exports = function (yargs) { | ||
var self = {}; | ||
var self = {} | ||
// methods for ouputting/building failure message. | ||
var fails = []; | ||
self.failFn = function (f) { | ||
fails.push(f); | ||
}; | ||
// methods for ouputting/building failure message. | ||
var fails = [] | ||
self.failFn = function (f) { | ||
fails.push(f) | ||
} | ||
var failMessage = null; | ||
var showHelpOnFail = true; | ||
self.showHelpOnFail = function (enabled, message) { | ||
if (typeof enabled === 'string') { | ||
message = enabled; | ||
enabled = true; | ||
} | ||
else if (typeof enabled === 'undefined') { | ||
enabled = true; | ||
} | ||
failMessage = message; | ||
showHelpOnFail = enabled; | ||
return self; | ||
}; | ||
var failMessage = null | ||
var showHelpOnFail = true | ||
self.showHelpOnFail = function (enabled, message) { | ||
if (typeof enabled === 'string') { | ||
message = enabled | ||
enabled = true | ||
} else if (typeof enabled === 'undefined') { | ||
enabled = true | ||
} | ||
failMessage = message | ||
showHelpOnFail = enabled | ||
return self | ||
} | ||
self.fail = function (msg) { | ||
if (fails.length) { | ||
fails.forEach(function (f) { | ||
f(msg); | ||
}); | ||
} else { | ||
if (showHelpOnFail) yargs.showHelp("error"); | ||
if (msg) console.error(msg); | ||
if (failMessage) { | ||
if (msg) console.error(""); | ||
console.error(failMessage); | ||
} | ||
if (yargs.getExitProcess()){ | ||
process.exit(1); | ||
}else{ | ||
throw new Error(msg); | ||
} | ||
} | ||
}; | ||
self.fail = function (msg) { | ||
if (fails.length) { | ||
fails.forEach(function (f) { | ||
f(msg) | ||
}) | ||
} else { | ||
if (showHelpOnFail) yargs.showHelp('error') | ||
if (msg) console.error(msg) | ||
if (failMessage) { | ||
if (msg) console.error('') | ||
console.error(failMessage) | ||
} | ||
if (yargs.getExitProcess()) { | ||
process.exit(1) | ||
} else { | ||
throw new Error(msg) | ||
} | ||
} | ||
} | ||
// methods for ouputting/building help (usage) message. | ||
var usage; | ||
self.usage = function (msg) { | ||
usage = msg; | ||
}; | ||
// methods for ouputting/building help (usage) message. | ||
var usage | ||
self.usage = function (msg) { | ||
usage = msg | ||
} | ||
var examples = []; | ||
self.example = function (cmd, description) { | ||
examples.push([cmd, description || '']); | ||
}; | ||
var examples = [] | ||
self.example = function (cmd, description) { | ||
examples.push([cmd, description || '']) | ||
} | ||
var commands = []; | ||
self.command = function (cmd, description) { | ||
commands.push([cmd, description || '']); | ||
}; | ||
self.getCommands = function () { | ||
return commands; | ||
}; | ||
var commands = [] | ||
self.command = function (cmd, description) { | ||
commands.push([cmd, description || '']) | ||
} | ||
self.getCommands = function () { | ||
return commands | ||
} | ||
var descriptions = {}; | ||
self.describe = function (key, desc) { | ||
if (typeof key === 'object') { | ||
Object.keys(key).forEach(function (k) { | ||
self.describe(k, key[k]); | ||
}); | ||
} | ||
else { | ||
descriptions[key] = desc; | ||
} | ||
}; | ||
self.getDescriptions = function() { | ||
return descriptions; | ||
var descriptions = {} | ||
self.describe = function (key, desc) { | ||
if (typeof key === 'object') { | ||
Object.keys(key).forEach(function (k) { | ||
self.describe(k, key[k]) | ||
}) | ||
} else { | ||
descriptions[key] = desc | ||
} | ||
} | ||
self.getDescriptions = function () { | ||
return descriptions | ||
} | ||
var epilog; | ||
self.epilog = function (msg) { | ||
epilog = msg; | ||
}; | ||
var epilog | ||
self.epilog = function (msg) { | ||
epilog = msg | ||
} | ||
var wrap = windowWidth(); | ||
self.wrap = function (cols) { | ||
wrap = cols; | ||
}; | ||
var wrap = windowWidth() | ||
self.wrap = function (cols) { | ||
wrap = cols | ||
} | ||
self.help = function () { | ||
normalizeAliases(); | ||
self.help = function () { | ||
normalizeAliases() | ||
var demanded = yargs.getDemanded(), | ||
options = yargs.getOptions(), | ||
keys = Object.keys( | ||
Object.keys(descriptions) | ||
.concat(Object.keys(demanded)) | ||
.concat(Object.keys(options.default)) | ||
.reduce(function (acc, key) { | ||
if (key !== '_') acc[key] = true; | ||
return acc; | ||
}, {}) | ||
); | ||
var demanded = yargs.getDemanded(), | ||
options = yargs.getOptions(), | ||
keys = Object.keys( | ||
Object.keys(descriptions) | ||
.concat(Object.keys(demanded)) | ||
.concat(Object.keys(options.default)) | ||
.reduce(function (acc, key) { | ||
if (key !== '_') acc[key] = true | ||
return acc | ||
}, {}) | ||
) | ||
var help = keys.length ? [ 'Options:' ] : []; | ||
var help = keys.length ? [ 'Options:' ] : [] | ||
// your application's commands, i.e., non-option | ||
// arguments populated in '_'. | ||
if (commands.length) { | ||
help.unshift(''); | ||
// your application's commands, i.e., non-option | ||
// arguments populated in '_'. | ||
if (commands.length) { | ||
help.unshift('') | ||
var commandsTable = {}; | ||
commands.forEach(function(command) { | ||
commandsTable[command[0]] = { | ||
desc: command[1], | ||
extra: '' | ||
}; | ||
}); | ||
help = ['Commands:'].concat(formatTable(commandsTable, 5), help); | ||
var commandsTable = {} | ||
commands.forEach(function (command) { | ||
commandsTable[command[0]] = { | ||
desc: command[1], | ||
extra: '' | ||
} | ||
}) | ||
// the usage string. | ||
if (usage) { | ||
var u = usage.replace(/\$0/g, yargs.$0); | ||
if (wrap) u = wordwrap(0, wrap)(u); | ||
help.unshift(u, ''); | ||
} | ||
help = ['Commands:'].concat(formatTable(commandsTable, 5), help) | ||
} | ||
// the options table. | ||
var aliasKeys = (Object.keys(options.alias) || []) | ||
.concat(Object.keys(yargs.parsed.newAliases) || []); | ||
// the usage string. | ||
if (usage) { | ||
var u = usage.replace(/\$0/g, yargs.$0) | ||
if (wrap) u = wordwrap(0, wrap)(u) | ||
help.unshift(u, '') | ||
} | ||
keys = keys.filter(function(key) { | ||
return !yargs.parsed.newAliases[key] && aliasKeys.every(function(alias) { | ||
return -1 == (options.alias[alias] || []).indexOf(key); | ||
}); | ||
}); | ||
// the options table. | ||
var aliasKeys = (Object.keys(options.alias) || []) | ||
.concat(Object.keys(yargs.parsed.newAliases) || []) | ||
var switches = keys.reduce(function (acc, key) { | ||
acc[key] = [ key ].concat(options.alias[key] || []) | ||
.map(function (sw) { | ||
return (sw.length > 1 ? '--' : '-') + sw | ||
}) | ||
.join(', ') | ||
; | ||
return acc; | ||
}, {}); | ||
keys = keys.filter(function (key) { | ||
return !yargs.parsed.newAliases[key] && aliasKeys.every(function (alias) { | ||
return (options.alias[alias] || []).indexOf(key) === -1 | ||
}) | ||
}) | ||
var switchTable = {}; | ||
keys.forEach(function (key) { | ||
var kswitch = switches[key]; | ||
var desc = descriptions[key] || ''; | ||
var type = null; | ||
var switches = keys.reduce(function (acc, key) { | ||
acc[key] = [ key ].concat(options.alias[key] || []) | ||
.map(function (sw) { | ||
return (sw.length > 1 ? '--' : '-') + sw | ||
}) | ||
.join(', ') | ||
if (~options.boolean.indexOf(key)) type = '[boolean]'; | ||
if (~options.count.indexOf(key)) type = '[count]'; | ||
if (~options.string.indexOf(key)) type = '[string]'; | ||
if (~options.normalize.indexOf(key)) type = '[string]'; | ||
if (~options.array.indexOf(key)) type = '[array]'; | ||
return acc | ||
}, {}) | ||
var extra = [ | ||
type, | ||
demanded[key] | ||
? '[required]' | ||
: null | ||
, | ||
defaultString(options.default[key], options.defaultDescription[key]) | ||
].filter(Boolean).join(' '); | ||
var switchTable = {} | ||
keys.forEach(function (key) { | ||
var kswitch = switches[key] | ||
var desc = descriptions[key] || '' | ||
var type = null | ||
switchTable[kswitch] = { | ||
desc: desc, | ||
extra: extra | ||
}; | ||
}); | ||
help.push.apply(help, formatTable(switchTable, 3)); | ||
if (~options.boolean.indexOf(key)) type = '[boolean]' | ||
if (~options.count.indexOf(key)) type = '[count]' | ||
if (~options.string.indexOf(key)) type = '[string]' | ||
if (~options.normalize.indexOf(key)) type = '[string]' | ||
if (~options.array.indexOf(key)) type = '[array]' | ||
if (keys.length) help.push(''); | ||
var extra = [ | ||
type, | ||
demanded[key] ? '[required]' : null, | ||
defaultString(options.default[key], options.defaultDescription[key]) | ||
].filter(Boolean).join(' ') | ||
// describe some common use-cases for your application. | ||
if (examples.length) { | ||
examples.forEach(function (example) { | ||
example[0] = example[0].replace(/\$0/g, yargs.$0); | ||
}); | ||
switchTable[kswitch] = { | ||
desc: desc, | ||
extra: extra | ||
} | ||
}) | ||
help.push.apply(help, formatTable(switchTable, 3)) | ||
var examplesTable = {}; | ||
examples.forEach(function(example) { | ||
examplesTable[example[0]] = { | ||
desc: example[1], | ||
extra: '' | ||
}; | ||
}); | ||
if (keys.length) help.push('') | ||
help.push.apply(help, ['Examples:'].concat(formatTable(examplesTable, 5), '')); | ||
} | ||
// describe some common use-cases for your application. | ||
if (examples.length) { | ||
examples.forEach(function (example) { | ||
example[0] = example[0].replace(/\$0/g, yargs.$0) | ||
}) | ||
// the usage string. | ||
if (epilog) { | ||
var e = epilog.replace(/\$0/g, yargs.$0); | ||
if (wrap) e = wordwrap(0, wrap)(e); | ||
help.push(e, ''); | ||
var examplesTable = {} | ||
examples.forEach(function (example) { | ||
examplesTable[example[0]] = { | ||
desc: example[1], | ||
extra: '' | ||
} | ||
}) | ||
return help.join('\n'); | ||
}; | ||
help.push.apply(help, ['Examples:'].concat(formatTable(examplesTable, 5), '')) | ||
} | ||
// make sure any options set for aliases, | ||
// are copied to the keys being aliased. | ||
function normalizeAliases () { | ||
var options = yargs.getOptions(), | ||
demanded = yargs.getDemanded(); | ||
// the usage string. | ||
if (epilog) { | ||
var e = epilog.replace(/\$0/g, yargs.$0) | ||
if (wrap) e = wordwrap(0, wrap)(e) | ||
help.push(e, '') | ||
} | ||
(Object.keys(options.alias) || []).forEach(function(key) { | ||
options.alias[key].forEach(function(alias) { | ||
// copy descriptions. | ||
if (descriptions[alias]) self.describe(key, descriptions[alias]); | ||
// copy demanded. | ||
if (demanded[alias]) yargs.demand(key, demanded[alias].msg); | ||
return help.join('\n') | ||
} | ||
// type messages. | ||
if (~options.boolean.indexOf(alias)) yargs.boolean(key); | ||
if (~options.count.indexOf(alias)) yargs.count(key); | ||
if (~options.string.indexOf(alias)) yargs.string(key); | ||
if (~options.normalize.indexOf(alias)) yargs.normalize(key); | ||
if (~options.array.indexOf(alias)) yargs.array(key); | ||
}); | ||
}); | ||
}; | ||
// make sure any options set for aliases, | ||
// are copied to the keys being aliased. | ||
function normalizeAliases () { | ||
var options = yargs.getOptions(), | ||
demanded = yargs.getDemanded() | ||
self.showHelp = function (level) { | ||
level = level || 'error'; | ||
console[level](self.help()); | ||
} | ||
;(Object.keys(options.alias) || []).forEach(function (key) { | ||
options.alias[key].forEach(function (alias) { | ||
// copy descriptions. | ||
if (descriptions[alias]) self.describe(key, descriptions[alias]) | ||
// copy demanded. | ||
if (demanded[alias]) yargs.demand(key, demanded[alias].msg) | ||
self.functionDescription = function (fn, defaultDescription) { | ||
if (defaultDescription) { | ||
return defaultDescription; | ||
} | ||
var description = fn.name ? decamelize(fn.name, '-') : 'generated-value'; | ||
return ['(', description, ')'].join(''); | ||
// type messages. | ||
if (~options.boolean.indexOf(alias)) yargs.boolean(key) | ||
if (~options.count.indexOf(alias)) yargs.count(key) | ||
if (~options.string.indexOf(alias)) yargs.string(key) | ||
if (~options.normalize.indexOf(alias)) yargs.normalize(key) | ||
if (~options.array.indexOf(alias)) yargs.array(key) | ||
}) | ||
}) | ||
} | ||
self.showHelp = function (level) { | ||
level = level || 'error' | ||
console[level](self.help()) | ||
} | ||
self.functionDescription = function (fn, defaultDescription) { | ||
if (defaultDescription) { | ||
return defaultDescription | ||
} | ||
var description = fn.name ? decamelize(fn.name, '-') : 'generated-value' | ||
return ['(', description, ')'].join('') | ||
} | ||
// format the default-value-string displayed in | ||
// the right-hand column. | ||
function defaultString(value, defaultDescription) { | ||
var string = '[default: '; | ||
// format the default-value-string displayed in | ||
// the right-hand column. | ||
function defaultString (value, defaultDescription) { | ||
var string = '[default: ' | ||
if (value === undefined) return null; | ||
if (value === undefined) return null | ||
if (defaultDescription) { | ||
string += defaultDescription; | ||
} else { | ||
switch (typeof value) { | ||
case 'string': | ||
string += JSON.stringify(value); | ||
break; | ||
case 'object': | ||
string += JSON.stringify(value); | ||
break; | ||
default: | ||
string += value; | ||
} | ||
} | ||
return string + ']'; | ||
if (defaultDescription) { | ||
string += defaultDescription | ||
} else { | ||
switch (typeof value) { | ||
case 'string': | ||
string += JSON.stringify(value) | ||
break | ||
case 'object': | ||
string += JSON.stringify(value) | ||
break | ||
default: | ||
string += value | ||
} | ||
} | ||
// word-wrapped two-column layout used by | ||
// examples, options, commands. | ||
function formatTable (table, padding) { | ||
var output = []; | ||
return string + ']' | ||
} | ||
// size of left-hand-column. | ||
var llen = longest(Object.keys(table)); | ||
// word-wrapped two-column layout used by | ||
// examples, options, commands. | ||
function formatTable (table, padding) { | ||
var output = [] | ||
// don't allow the left-column to take up | ||
// more than half of the screen. | ||
if (wrap) { | ||
llen = Math.min(llen, parseInt(wrap / 2)); | ||
} | ||
// size of left-hand-column. | ||
var llen = longest(Object.keys(table)) | ||
// size of right-column. | ||
var desclen = longest(Object.keys(table).map(function (k) { | ||
return table[k].desc; | ||
})); | ||
// don't allow the left-column to take up | ||
// more than half of the screen. | ||
if (wrap) { | ||
llen = Math.min(llen, parseInt(wrap / 2, 10)) | ||
} | ||
Object.keys(table).forEach(function(left) { | ||
var desc = table[left].desc, | ||
extra = table[left].extra, | ||
leftLines = null; | ||
// size of right-column. | ||
var desclen = longest(Object.keys(table).map(function (k) { | ||
return table[k].desc | ||
})) | ||
if (wrap) { | ||
desc = wordwrap(llen + padding + 1, wrap)(desc) | ||
.slice(llen + padding + 1); | ||
} | ||
Object.keys(table).forEach(function (left) { | ||
var desc = table[left].desc, | ||
extra = table[left].extra, | ||
leftLines = null | ||
// if we need to wrap the left-hand-column, | ||
// split it on to multiple lines. | ||
if (wrap && left.length > llen) { | ||
leftLines = wordwrap(2, llen)(left.trim()).split('\n'); | ||
left = ''; | ||
} | ||
if (wrap) { | ||
desc = wordwrap(llen + padding + 1, wrap)(desc) | ||
.slice(llen + padding + 1) | ||
} | ||
var lpadding = new Array( | ||
Math.max(llen - left.length + padding, 0) | ||
).join(' '); | ||
// if we need to wrap the left-hand-column, | ||
// split it on to multiple lines. | ||
if (wrap && left.length > llen) { | ||
leftLines = wordwrap(2, llen)(left.trim()).split('\n') | ||
left = '' | ||
} | ||
var dpadding = new Array( | ||
Math.max(desclen - desc.length + 1, 0) | ||
).join(' '); | ||
var lpadding = new Array( | ||
Math.max(llen - left.length + padding, 0) | ||
).join(' ') | ||
if (!wrap && dpadding.length > 0) { | ||
desc += dpadding; | ||
} | ||
var dpadding = new Array( | ||
Math.max(desclen - desc.length + 1, 0) | ||
).join(' ') | ||
var prelude = ' ' + left + lpadding; | ||
if (!wrap && dpadding.length > 0) { | ||
desc += dpadding | ||
} | ||
var body = [ desc, extra ].filter(Boolean).join(' '); | ||
var prelude = ' ' + left + lpadding | ||
if (wrap) { | ||
var dlines = desc.split('\n'); | ||
var dlen = dlines.slice(-1)[0].length | ||
+ (dlines.length === 1 ? prelude.length : 0) | ||
var body = [ desc, extra ].filter(Boolean).join(' ') | ||
if (extra.length > wrap) { | ||
body = desc + '\n' + wordwrap(llen + 4, wrap)(extra) | ||
} else { | ||
body = desc + (dlen + extra.length > wrap - 2 | ||
? '\n' | ||
+ new Array(wrap - extra.length + 1).join(' ') | ||
+ extra | ||
: new Array(wrap - extra.length - dlen + 1).join(' ') | ||
+ extra | ||
); | ||
} | ||
} | ||
if (wrap) { | ||
var dlines = desc.split('\n') | ||
var dlen = dlines.slice(-1)[0].length | ||
+ (dlines.length === 1 ? prelude.length : 0) | ||
if (leftLines) { // handle word-wrapping the left-hand-column. | ||
var rightLines = body.split('\n'), | ||
firstLine = prelude + rightLines[0], | ||
lineCount = Math.max(leftLines.length, rightLines.length); | ||
if (extra.length > wrap) { | ||
body = desc + '\n' + wordwrap(llen + 4, wrap)(extra) | ||
} else { | ||
body = desc + (dlen + extra.length > wrap - 2 | ||
? '\n' | ||
+ new Array(wrap - extra.length + 1).join(' ') | ||
+ extra | ||
: new Array(wrap - extra.length - dlen + 1).join(' ') | ||
+ extra | ||
) | ||
} | ||
} | ||
for (var i = 0; i < lineCount; i++) { | ||
var left = leftLines[i], | ||
right = i ? rightLines[i] : firstLine; | ||
if (leftLines) { // handle word-wrapping the left-hand-column. | ||
var rightLines = body.split('\n'), | ||
firstLine = prelude + rightLines[0], | ||
lineCount = Math.max(leftLines.length, rightLines.length) | ||
output.push(strcpy(left, right, firstLine.length)); | ||
} | ||
} else { | ||
output.push(prelude + body); | ||
} | ||
}); | ||
for (var i = 0; i < lineCount; i++) { | ||
var l = leftLines[i], | ||
r = i ? rightLines[i] : firstLine | ||
return output; | ||
} | ||
output.push(strcpy(l, r, firstLine.length)) | ||
} | ||
} else { | ||
output.push(prelude + body) | ||
} | ||
}) | ||
// find longest string in array of strings. | ||
function longest (xs) { | ||
return Math.max.apply( | ||
null, | ||
xs.map(function (x) { return x.length }) | ||
); | ||
} | ||
return output | ||
} | ||
// copy one string into another, used when | ||
// formatting usage table. | ||
function strcpy (source, destination, width) { | ||
var str = '' | ||
// find longest string in array of strings. | ||
function longest (xs) { | ||
return Math.max.apply( | ||
null, | ||
xs.map(function (x) { return x.length }) | ||
) | ||
} | ||
source = source || ''; | ||
destination = destination || new Array(width).join(' '); | ||
// copy one string into another, used when | ||
// formatting usage table. | ||
function strcpy (source, destination, width) { | ||
var str = '' | ||
for (var i = 0; i < destination.length; i++) { | ||
var char = destination.charAt(i); | ||
source = source || '' | ||
destination = destination || new Array(width).join(' ') | ||
if (char === ' ') char = source.charAt(i) || char; | ||
for (var i = 0; i < destination.length; i++) { | ||
var char = destination.charAt(i) | ||
str += char; | ||
} | ||
if (char === ' ') char = source.charAt(i) || char | ||
return str; | ||
str += char | ||
} | ||
// guess the width of the console window, max-width 100. | ||
function windowWidth() { | ||
return wsize.width ? Math.min(80, wsize.width) : null; | ||
} | ||
return str | ||
} | ||
// logic for displaying application version. | ||
var version = null; | ||
self.version = function (ver, opt, msg) { | ||
version = ver; | ||
}; | ||
// guess the width of the console window, max-width 100. | ||
function windowWidth () { | ||
return wsize.width ? Math.min(80, wsize.width) : null | ||
} | ||
self.showVersion = function() { | ||
if (typeof version === 'function') console.log(version()); | ||
else console.log(version); | ||
}; | ||
// logic for displaying application version. | ||
var version = null | ||
self.version = function (ver, opt, msg) { | ||
version = ver | ||
} | ||
return self; | ||
self.showVersion = function () { | ||
if (typeof version === 'function') console.log(version()) | ||
else console.log(version) | ||
} | ||
return self | ||
} |
// validation-type-stuff, missing params, | ||
// bad implications, custom checks. | ||
module.exports = function (yargs, usage) { | ||
var self = {}; | ||
var self = {} | ||
// validate appropriate # of non-option | ||
// arguments were provided, i.e., '_'. | ||
self.nonOptionCount = function(argv) { | ||
var demanded = yargs.getDemanded(); | ||
// validate appropriate # of non-option | ||
// arguments were provided, i.e., '_'. | ||
self.nonOptionCount = function (argv) { | ||
var demanded = yargs.getDemanded() | ||
if (demanded._ && argv._.length < demanded._.count) { | ||
if (demanded._.msg !== undefined) { | ||
usage.fail(demanded._.msg); | ||
} else { | ||
usage.fail('Not enough non-option arguments: got ' | ||
+ argv._.length + ', need at least ' + demanded._.count | ||
); | ||
} | ||
} | ||
}; | ||
if (demanded._ && argv._.length < demanded._.count) { | ||
if (demanded._.msg !== undefined) { | ||
usage.fail(demanded._.msg) | ||
} else { | ||
usage.fail('Not enough non-option arguments: got ' | ||
+ argv._.length + ', need at least ' + demanded._.count | ||
) | ||
} | ||
} | ||
} | ||
// make sure that any args that require an | ||
// value (--foo=bar), have a value. | ||
self.missingArgumentValue = function(argv) { | ||
var options = yargs.getOptions(), | ||
defaultValues = [true, false, '']; | ||
// make sure that any args that require an | ||
// value (--foo=bar), have a value. | ||
self.missingArgumentValue = function (argv) { | ||
var options = yargs.getOptions(), | ||
defaultValues = [true, false, ''] | ||
if (options.requiresArg.length > 0) { | ||
var missingRequiredArgs = []; | ||
if (options.requiresArg.length > 0) { | ||
var missingRequiredArgs = [] | ||
options.requiresArg.forEach(function(key) { | ||
var value = argv[key]; | ||
options.requiresArg.forEach(function (key) { | ||
var value = argv[key] | ||
// if a value is explicitly requested, | ||
// flag argument as missing if it does not | ||
// look like foo=bar was entered. | ||
if (~defaultValues.indexOf(value) | ||
|| (Array.isArray(value) && !value.length)) { | ||
missingRequiredArgs.push(key); | ||
} | ||
}); | ||
if (missingRequiredArgs.length == 1) { | ||
usage.fail("Missing argument value: " + missingRequiredArgs[0]); | ||
} | ||
else if (missingRequiredArgs.length > 1) { | ||
var message = "Missing argument values: " + missingRequiredArgs.join(", "); | ||
usage.fail(message); | ||
} | ||
// if a value is explicitly requested, | ||
// flag argument as missing if it does not | ||
// look like foo=bar was entered. | ||
if (~defaultValues.indexOf(value) | ||
|| (Array.isArray(value) && !value.length)) { | ||
missingRequiredArgs.push(key) | ||
} | ||
}; | ||
}) | ||
// make sure all the required arguments are present. | ||
self.requiredArguments = function(argv) { | ||
var demanded = yargs.getDemanded(), | ||
missing = null; | ||
if (missingRequiredArgs.length === 1) { | ||
usage.fail('Missing argument value: ' + missingRequiredArgs[0]) | ||
} else if (missingRequiredArgs.length > 1) { | ||
var message = 'Missing argument values: ' + missingRequiredArgs.join(', ') | ||
usage.fail(message) | ||
} | ||
} | ||
} | ||
Object.keys(demanded).forEach(function (key) { | ||
if (!argv.hasOwnProperty(key)) { | ||
missing = missing || {}; | ||
missing[key] = demanded[key]; | ||
} | ||
}); | ||
// make sure all the required arguments are present. | ||
self.requiredArguments = function (argv) { | ||
var demanded = yargs.getDemanded(), | ||
missing = null | ||
if (missing) { | ||
var customMsgs = []; | ||
Object.keys(missing).forEach(function(key) { | ||
var msg = missing[key].msg; | ||
if (msg && customMsgs.indexOf(msg) < 0) { | ||
customMsgs.push(msg); | ||
} | ||
}); | ||
var customMsg = customMsgs.length ? '\n' + customMsgs.join('\n') : ''; | ||
Object.keys(demanded).forEach(function (key) { | ||
if (!argv.hasOwnProperty(key)) { | ||
missing = missing || {} | ||
missing[key] = demanded[key] | ||
} | ||
}) | ||
usage.fail('Missing required arguments: ' + Object.keys(missing).join(', ') + customMsg); | ||
if (missing) { | ||
var customMsgs = [] | ||
Object.keys(missing).forEach(function (key) { | ||
var msg = missing[key].msg | ||
if (msg && customMsgs.indexOf(msg) < 0) { | ||
customMsgs.push(msg) | ||
} | ||
}; | ||
}) | ||
// check for unknown arguments (strict-mode). | ||
self.unknownArguments = function(argv, aliases) { | ||
var descriptions = usage.getDescriptions(), | ||
demanded = yargs.getDemanded(), | ||
unknown = [], | ||
aliasLookup = {}; | ||
var customMsg = customMsgs.length ? '\n' + customMsgs.join('\n') : '' | ||
usage.fail('Missing required arguments: ' + Object.keys(missing).join(', ') + customMsg) | ||
} | ||
} | ||
Object.keys(aliases).forEach(function (key) { | ||
aliases[key].forEach(function (alias) { | ||
aliasLookup[alias] = key; | ||
}); | ||
}); | ||
// check for unknown arguments (strict-mode). | ||
self.unknownArguments = function (argv, aliases) { | ||
var descriptions = usage.getDescriptions(), | ||
demanded = yargs.getDemanded(), | ||
unknown = [], | ||
aliasLookup = {} | ||
Object.keys(argv).forEach(function (key) { | ||
if (key !== "$0" && key !== "_" && | ||
!descriptions.hasOwnProperty(key) && | ||
!demanded.hasOwnProperty(key) && | ||
!aliasLookup.hasOwnProperty(key)) { | ||
unknown.push(key); | ||
} | ||
}); | ||
Object.keys(aliases).forEach(function (key) { | ||
aliases[key].forEach(function (alias) { | ||
aliasLookup[alias] = key | ||
}) | ||
}) | ||
if (unknown.length == 1) { | ||
usage.fail("Unknown argument: " + unknown[0]); | ||
} | ||
else if (unknown.length > 1) { | ||
usage.fail("Unknown arguments: " + unknown.join(", ")); | ||
} | ||
}; | ||
Object.keys(argv).forEach(function (key) { | ||
if (key !== '$0' && key !== '_' && | ||
!descriptions.hasOwnProperty(key) && | ||
!demanded.hasOwnProperty(key) && | ||
!aliasLookup.hasOwnProperty(key)) { | ||
unknown.push(key) | ||
} | ||
}) | ||
// custom checks, added using the `check` option on yargs. | ||
var checks = []; | ||
self.check = function (f) { | ||
checks.push(f); | ||
}; | ||
if (unknown.length === 1) { | ||
usage.fail('Unknown argument: ' + unknown[0]) | ||
} else if (unknown.length > 1) { | ||
usage.fail('Unknown arguments: ' + unknown.join(', ')) | ||
} | ||
} | ||
self.customChecks = function(argv, aliases) { | ||
checks.forEach(function (f) { | ||
try { | ||
var result = f(argv, aliases); | ||
if (!result) { | ||
usage.fail('Argument check failed: ' + f.toString()); | ||
} else if (typeof result === 'string') { | ||
usage.fail(result); | ||
} | ||
} | ||
catch (err) { | ||
usage.fail(err) | ||
} | ||
}); | ||
}; | ||
// custom checks, added using the `check` option on yargs. | ||
var checks = [] | ||
self.check = function (f) { | ||
checks.push(f) | ||
} | ||
// check implications, argument foo implies => argument bar. | ||
var implied = {}; | ||
self.implies = function (key, value) { | ||
if (typeof key === 'object') { | ||
Object.keys(key).forEach(function (k) { | ||
self.implies(k, key[k]); | ||
}); | ||
} else { | ||
implied[key] = value; | ||
self.customChecks = function (argv, aliases) { | ||
checks.forEach(function (f) { | ||
try { | ||
var result = f(argv, aliases) | ||
if (!result) { | ||
usage.fail('Argument check failed: ' + f.toString()) | ||
} else if (typeof result === 'string') { | ||
usage.fail(result) | ||
} | ||
}; | ||
self.getImplied = function() { | ||
return implied; | ||
} catch (err) { | ||
usage.fail(err.message ? err.message : err) | ||
} | ||
}) | ||
} | ||
// check implications, argument foo implies => argument bar. | ||
var implied = {} | ||
self.implies = function (key, value) { | ||
if (typeof key === 'object') { | ||
Object.keys(key).forEach(function (k) { | ||
self.implies(k, key[k]) | ||
}) | ||
} else { | ||
implied[key] = value | ||
} | ||
} | ||
self.getImplied = function () { | ||
return implied | ||
} | ||
self.implications = function(argv) { | ||
var implyFail = []; | ||
self.implications = function (argv) { | ||
var implyFail = [] | ||
Object.keys(implied).forEach(function (key) { | ||
var num, origKey = key, value = implied[key]; | ||
Object.keys(implied).forEach(function (key) { | ||
var num, | ||
origKey = key, | ||
value = implied[key] | ||
// convert string '1' to number 1 | ||
var num = Number(key); | ||
key = isNaN(num) ? key : num; | ||
// convert string '1' to number 1 | ||
num = Number(key) | ||
key = isNaN(num) ? key : num | ||
if (typeof key === 'number') { | ||
// check length of argv._ | ||
key = argv._.length >= key; | ||
} else if (key.match(/^--no-.+/)) { | ||
// check if key doesn't exist | ||
key = key.match(/^--no-(.+)/)[1]; | ||
key = !argv[key]; | ||
} else { | ||
// check if key exists | ||
key = argv[key]; | ||
} | ||
if (typeof key === 'number') { | ||
// check length of argv._ | ||
key = argv._.length >= key | ||
} else if (key.match(/^--no-.+/)) { | ||
// check if key doesn't exist | ||
key = key.match(/^--no-(.+)/)[1] | ||
key = !argv[key] | ||
} else { | ||
// check if key exists | ||
key = argv[key] | ||
} | ||
num = Number(value); | ||
value = isNaN(num) ? value : num; | ||
num = Number(value) | ||
value = isNaN(num) ? value : num | ||
if (typeof value === 'number') { | ||
value = argv._.length >= value; | ||
} else if (value.match(/^--no-.+/)) { | ||
value = value.match(/^--no-(.+)/)[1]; | ||
value = !argv[value]; | ||
} else { | ||
value = argv[value]; | ||
} | ||
if (typeof value === 'number') { | ||
value = argv._.length >= value | ||
} else if (value.match(/^--no-.+/)) { | ||
value = value.match(/^--no-(.+)/)[1] | ||
value = !argv[value] | ||
} else { | ||
value = argv[value] | ||
} | ||
if (key && !value) { | ||
implyFail.push(origKey); | ||
} | ||
}); | ||
if (key && !value) { | ||
implyFail.push(origKey) | ||
} | ||
}) | ||
if (implyFail.length) { | ||
var msg = 'Implications failed:\n'; | ||
if (implyFail.length) { | ||
var msg = 'Implications failed:\n' | ||
implyFail.forEach(function (key) { | ||
msg += (' ' + key + ' -> ' + implied[key]); | ||
}); | ||
implyFail.forEach(function (key) { | ||
msg += (' ' + key + ' -> ' + implied[key]) | ||
}) | ||
usage.fail(msg); | ||
} | ||
usage.fail(msg) | ||
} | ||
} | ||
return self; | ||
return self | ||
} |
{ | ||
"name": "yargs", | ||
"version": "3.7.1", | ||
"version": "3.7.2", | ||
"description": "Light-weight option parsing with an argv hash. No optstrings attached.", | ||
@@ -25,6 +25,7 @@ "main": "./index.js", | ||
"mocoverage": "^1.0.0", | ||
"patched-blanket": "^1.0.1" | ||
"patched-blanket": "^1.0.1", | ||
"standard": "^3.6.0" | ||
}, | ||
"scripts": { | ||
"test": "mocha --check-leaks --ui exports --require patched-blanket -R mocoverage" | ||
"test": "standard && mocha --check-leaks --ui exports --require patched-blanket -R mocoverage" | ||
}, | ||
@@ -48,2 +49,10 @@ "repository": { | ||
}, | ||
"standard": { | ||
"ignore": [ | ||
"**/example/**" | ||
], | ||
"globals": [ | ||
"it" | ||
] | ||
}, | ||
"keywords": [ | ||
@@ -50,0 +59,0 @@ "argument", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
5
100866
8
1295
1