yargs
Advanced tools
Comparing version 3.0.0 to 3.0.1
429
index.js
var path = require('path'); | ||
var minimist = require('./lib/minimist'); | ||
var wordwrap = require('./lib/wordwrap'); | ||
var Parser = require('./lib/parser'); | ||
var Usage = require('./lib/usage'); | ||
var Validation = require('./lib/validation'); | ||
@@ -23,2 +24,5 @@ /* Hack an instance of Argv with process.argv into Argv | ||
var self = {}; | ||
var usage = Usage(self); | ||
var validation = Validation(self, usage); | ||
if (!cwd) cwd = process.cwd(); | ||
@@ -45,2 +49,3 @@ | ||
options = { | ||
array: [], | ||
boolean: [], | ||
@@ -64,2 +69,7 @@ string: [], | ||
self.array = function (arrays) { | ||
options.array.push.apply(options.array, [].concat(arrays)); | ||
return self; | ||
} | ||
self.normalize = function (strings) { | ||
@@ -75,8 +85,12 @@ options.normalize.push.apply(options.normalize, [].concat(strings)); | ||
var examples = []; | ||
self.example = function (cmd, description) { | ||
examples.push([cmd, description]); | ||
usage.example(cmd, description); | ||
return self; | ||
}; | ||
self.command = function (cmd, description) { | ||
usage.command(cmd, description); | ||
return self; | ||
}; | ||
self.string = function (strings) { | ||
@@ -139,2 +153,5 @@ options.string.push.apply(options.string, [].concat(strings)); | ||
}; | ||
self.getDemanded = function() { | ||
return demanded; | ||
}; | ||
@@ -146,15 +163,7 @@ self.requiresArg = function (requiresArgs) { | ||
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; | ||
} | ||
validation.implies(key, value); | ||
return self; | ||
}; | ||
var usage; | ||
self.usage = function (msg, opts) { | ||
@@ -166,3 +175,3 @@ if (!opts && typeof msg === 'object') { | ||
usage = msg; | ||
usage.usage(msg); | ||
@@ -174,35 +183,14 @@ if (opts) self.options(opts); | ||
var fails = []; | ||
self.epilogue = self.epilog = function (msg) { | ||
usage.epilog(msg); | ||
return self; | ||
}; | ||
self.fail = function (f) { | ||
fails.push(f); | ||
usage.failFn(f); | ||
return self; | ||
}; | ||
function fail (msg) { | ||
if (fails.length) { | ||
fails.forEach(function (f) { | ||
f(msg); | ||
}); | ||
} else { | ||
if (showHelpOnFail) { | ||
self.showHelp(); | ||
} | ||
if (msg) console.error(msg); | ||
if (failMessage) { | ||
if (msg) { | ||
console.error(""); | ||
} | ||
console.error(failMessage); | ||
} | ||
if (exitProcess){ | ||
process.exit(1); | ||
}else{ | ||
throw new Error(msg); | ||
} | ||
} | ||
} | ||
var checks = []; | ||
self.check = function (f) { | ||
checks.push(f); | ||
validation.check(f); | ||
return self; | ||
@@ -213,12 +201,4 @@ }; | ||
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; | ||
} | ||
usage.describe(key, desc); | ||
return self; | ||
@@ -244,7 +224,5 @@ }; | ||
} | ||
if (typeof opt.default !== 'undefined') { | ||
if ('default' in opt) { | ||
self.default(key, opt.default); | ||
} | ||
if (opt.boolean || opt.type === 'boolean') { | ||
@@ -254,2 +232,6 @@ self.boolean(key); | ||
} | ||
if (opt.array || opt.type === 'array') { | ||
self.array(key); | ||
if (opt.alias) self.array(opt.alias); | ||
} | ||
if (opt.string || opt.type === 'string') { | ||
@@ -275,6 +257,8 @@ self.string(key); | ||
}; | ||
self.getOptions = function() { | ||
return options; | ||
}; | ||
var wrap = null; | ||
self.wrap = function (cols) { | ||
wrap = cols; | ||
usage.wrap(cols); | ||
return self; | ||
@@ -290,12 +274,10 @@ }; | ||
self.showHelp = function (fn) { | ||
if (!fn) fn = console.error.bind(console); | ||
fn(self.help()); | ||
usage.showHelp(fn); | ||
return self; | ||
}; | ||
var version = null; | ||
var versionOpt = null; | ||
self.version = function (ver, opt, msg) { | ||
version = ver; | ||
versionOpt = opt; | ||
usage.version(ver); | ||
self.describe(opt, msg || 'Show version number'); | ||
@@ -312,14 +294,4 @@ return self; | ||
var failMessage = null; | ||
var showHelpOnFail = true; | ||
self.showHelpOnFail = function (enabled, message) { | ||
if (typeof enabled === 'string') { | ||
enabled = true; | ||
message = enabled; | ||
} | ||
else if (typeof enabled === 'undefined') { | ||
enabled = true; | ||
} | ||
failMessage = message; | ||
showHelpOnFail = enabled; | ||
usage.showHelpOnFail(enabled, message); | ||
return self; | ||
@@ -336,141 +308,26 @@ }; | ||
}; | ||
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. | ||
if (arguments.length > 0) { | ||
return self.addHelpOpt.apply(self, arguments); | ||
} | ||
return usage.help(); | ||
}; | ||
var 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; | ||
}, {}) | ||
); | ||
Object.defineProperty(self, 'argv', { | ||
get : function () { | ||
var args = null; | ||
var help = keys.length ? [ 'Options:' ] : []; | ||
try { | ||
args = parseArgs(processArgs); | ||
} catch (err) { | ||
usage.fail(err.message); | ||
} | ||
if (examples.length) { | ||
help.unshift(''); | ||
examples.forEach(function (example) { | ||
example[0] = example[0].replace(/\$0/g, self.$0); | ||
}); | ||
var commandlen = longest(examples.map(function (a) { | ||
return a[0]; | ||
})); | ||
var exampleLines = examples.map(function(example) { | ||
var command = example[0]; | ||
var description = example[1]; | ||
command += Array(commandlen + 5 - command.length).join(' '); | ||
return ' ' + command + description; | ||
}); | ||
exampleLines.push(''); | ||
help = exampleLines.concat(help); | ||
help.unshift('Examples:'); | ||
} | ||
if (usage) { | ||
help.unshift(usage.replace(/\$0/g, self.$0), ''); | ||
} | ||
var aliasKeys = (Object.keys(options.alias) || []) | ||
.concat(Object.keys(self.parsed.newAliases) || []); | ||
keys = keys.filter(function(key) { | ||
return !self.parsed.newAliases[key] && aliasKeys.every(function(alias) { | ||
return -1 == (options.alias[alias] || []).indexOf(key); | ||
}); | ||
}); | ||
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; | ||
}, {}); | ||
var switchlen = longest(Object.keys(switches).map(function (s) { | ||
return switches[s] || ''; | ||
})); | ||
var desclen = longest(Object.keys(descriptions).map(function (d) { | ||
return descriptions[d] || ''; | ||
})); | ||
keys.forEach(function (key) { | ||
var kswitch = switches[key]; | ||
var desc = descriptions[key] || ''; | ||
if (wrap) { | ||
desc = wordwrap(switchlen + 4, wrap)(desc) | ||
.slice(switchlen + 4) | ||
; | ||
} | ||
var spadding = new Array( | ||
Math.max(switchlen - kswitch.length + 3, 0) | ||
).join(' '); | ||
var dpadding = new Array( | ||
Math.max(desclen - desc.length + 1, 0) | ||
).join(' '); | ||
var type = null; | ||
if (options.boolean[key]) type = '[boolean]'; | ||
if (options.count[key]) type = '[count]'; | ||
if (options.string[key]) type = '[string]'; | ||
if (options.normalize[key]) type = '[string]'; | ||
if (!wrap && dpadding.length > 0) { | ||
desc += dpadding; | ||
} | ||
var prelude = ' ' + kswitch + spadding; | ||
var extra = [ | ||
type, | ||
demanded[key] | ||
? '[required]' | ||
: null | ||
, | ||
options.default[key] !== undefined | ||
? '[default: ' + (typeof options.default[key] === 'string' ? | ||
JSON.stringify : String)(options.default[key]) + ']' | ||
: null | ||
].filter(Boolean).join(' '); | ||
var body = [ desc, extra ].filter(Boolean).join(' '); | ||
if (wrap) { | ||
var dlines = desc.split('\n'); | ||
var dlen = dlines.slice(-1)[0].length | ||
+ (dlines.length === 1 ? prelude.length : 0) | ||
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 | ||
); | ||
} | ||
help.push(prelude + body); | ||
}); | ||
if (keys.length) help.push(''); | ||
return help.join('\n'); | ||
}; | ||
Object.defineProperty(self, 'argv', { | ||
get : function () { return parseArgs(processArgs) }, | ||
return args; | ||
}, | ||
enumerable : true | ||
@@ -480,3 +337,3 @@ }); | ||
function parseArgs (args) { | ||
var parsed = minimist(args, options), | ||
var parsed = Parser(args, options), | ||
argv = parsed.argv, | ||
@@ -491,3 +348,3 @@ aliases = parsed.aliases; | ||
if (key === helpOpt) { | ||
self.showHelp(console.log); | ||
self.showHelp('log'); | ||
if (exitProcess){ | ||
@@ -498,3 +355,3 @@ process.exit(0); | ||
else if (key === versionOpt) { | ||
process.stdout.write(version); | ||
usage.showVersion(); | ||
if (exitProcess){ | ||
@@ -506,153 +363,16 @@ process.exit(0); | ||
if (demanded._ && argv._.length < demanded._.count) { | ||
if (demanded._.msg) { | ||
fail(demanded._.msg); | ||
} else { | ||
fail('Not enough non-option arguments: got ' | ||
+ argv._.length + ', need at least ' + demanded._.count | ||
); | ||
} | ||
} | ||
validation.nonOptionCount(argv); | ||
validation.missingArgumentValue(argv); | ||
validation.requiredArguments(argv); | ||
if (options.requiresArg.length > 0) { | ||
var missingRequiredArgs = []; | ||
options.requiresArg.forEach(function(key) { | ||
var value = argv[key]; | ||
// minimist sets --foo value to true / --no-foo to false | ||
if (value === true || value === false) { | ||
missingRequiredArgs.push(key); | ||
} | ||
}); | ||
if (missingRequiredArgs.length == 1) { | ||
fail("Missing argument value: " + missingRequiredArgs[0]); | ||
} | ||
else if (missingRequiredArgs.length > 1) { | ||
var message = "Missing argument values: " + missingRequiredArgs.join(", "); | ||
fail(message); | ||
} | ||
} | ||
var missing = null; | ||
Object.keys(demanded).forEach(function (key) { | ||
if (!argv.hasOwnProperty(key)) { | ||
missing = missing || {}; | ||
missing[key] = demanded[key]; | ||
} | ||
}); | ||
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') : ''; | ||
fail('Missing required arguments: ' + Object.keys(missing).join(', ') + customMsg); | ||
} | ||
if (strict) { | ||
var unknown = []; | ||
var aliases = {}; | ||
Object.keys(parsed.aliases).forEach(function (key) { | ||
parsed.aliases[key].forEach(function (alias) { | ||
aliases[alias] = key; | ||
}); | ||
}); | ||
Object.keys(argv).forEach(function (key) { | ||
if (key !== "$0" && key !== "_" && | ||
!descriptions.hasOwnProperty(key) && | ||
!demanded.hasOwnProperty(key) && | ||
!aliases.hasOwnProperty(key)) { | ||
unknown.push(key); | ||
} | ||
}); | ||
if (unknown.length == 1) { | ||
fail("Unknown argument: " + unknown[0]); | ||
} | ||
else if (unknown.length > 1) { | ||
fail("Unknown arguments: " + unknown.join(", ")); | ||
} | ||
validation.unknownArguments(argv, aliases); | ||
} | ||
checks.forEach(function (f) { | ||
try { | ||
var result = f(argv, aliases); | ||
if (result === false) { | ||
fail('Argument check failed: ' + f.toString()); | ||
} else if (typeof result === 'string') { | ||
fail(result); | ||
} | ||
} | ||
catch (err) { | ||
fail(err) | ||
} | ||
}); | ||
validation.customChecks(argv, aliases); | ||
validation.implications(argv); | ||
var implyFail = []; | ||
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; | ||
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; | ||
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 (implyFail.length) { | ||
var msg = 'Implications failed:\n'; | ||
implyFail.forEach(function (key) { | ||
msg += (' ' + key + ' -> ' + implied[key] + '\n'); | ||
}); | ||
fail(msg); | ||
} | ||
return argv; | ||
} | ||
function longest (xs) { | ||
return Math.max.apply( | ||
null, | ||
xs.map(function (x) { return x.length }) | ||
); | ||
} | ||
return self; | ||
@@ -665,12 +385,3 @@ }; | ||
function rebase (base, dir) { | ||
var ds = path.normalize(dir).split('/').slice(1); | ||
var bs = path.normalize(base).split('/').slice(1); | ||
for (var i = 0; ds[i] && ds[i] == bs[i]; i++); | ||
ds.splice(0, i); bs.splice(0, i); | ||
var p = path.normalize( | ||
bs.map(function () { return '..' }).concat(ds).join('/') | ||
).replace(/\/$/,'').replace(/^$/, '.'); | ||
return p.match(/^[.\/]/) ? p : './' + p; | ||
return path.relative(base, dir); | ||
}; |
{ | ||
"name": "yargs", | ||
"version": "3.0.0", | ||
"version": "3.0.1", | ||
"description": "Light-weight option parsing with an argv hash. No optstrings attached.", | ||
@@ -11,8 +11,13 @@ "main": "./index.js", | ||
], | ||
"dependencies": {}, | ||
"dependencies": { | ||
"window-size": "0.1.0", | ||
"wordwrap": "0.0.2" | ||
}, | ||
"devDependencies": { | ||
"blanket": "^1.1.6", | ||
"chai": "^1.10.0", | ||
"coveralls": "^2.11.2", | ||
"hashish": "0.0.4", | ||
"mocha": "^2.1.0", | ||
"mocha-lcov-reporter": "0.0.1", | ||
"mocoverage": "^1.0.0" | ||
@@ -19,0 +24,0 @@ }, |
113
README.md
@@ -11,7 +11,6 @@ yargs | ||
[![NPM version](https://badge.fury.io/js/yargs.png)](http://badge.fury.io/js/yargs) | ||
[![Coverage Status](https://coveralls.io/repos/chevex/yargs/badge.svg?branch=)](https://coveralls.io/r/chevex/yargs?branch=) | ||
> ~~NOTE: Yargs is a fork of [optimist](https://github.com/substack/node-optimist) by [substack (James Halliday)](https://github.com/substack). It is obvious that substack is stretched pretty thin maintaining over 300 modules on npm at the time of this writing. So rather than complain in the project issue tracker I thought I'd just pick up the torch and maintain a proper fork. Currently the project is totally backward compatible with optimist but this may change in the future (if it does I will update this notice to inform you of this). For now though, enjoy optimist with about 5 months worth of fixes and updates rolled in, most of them pulled from optimist's own [stale pull requests](https://github.com/substack/node-optimist/pulls).~~ | ||
> Yargs is the official successor to optimist. Please feel free to submit issues and pull requests. If you'd like to contribute and don't know where to start, have a look at [the issue list](https://github.com/chevex/yargs/issues) :) | ||
> UPDATE: Yargs is now the official successor to optimist. Please feel free to submit issues and pull requests. While I personally don't have the time to pore over all the issues and fix all of them on a regular basis, I'm more than happy to look over pull requests, test them, and merge them in. If you'd like to contribute and don't know where to start, have a look at [the issue list](https://github.com/chevex/yargs/issues) :) | ||
examples | ||
@@ -41,3 +40,3 @@ ======== | ||
Plunder more riffiwobbles! | ||
$ ./xup.js --rif 12 --xup 8.1 | ||
@@ -50,3 +49,3 @@ Drop the xupptumblers! | ||
------------------------------------------------- | ||
short.js: | ||
@@ -87,3 +86,3 @@ | ||
The parrot says: squawk | ||
$ ./bool.js -sp | ||
@@ -97,3 +96,3 @@ The parrot says: squawk! | ||
------------------------------------------------- | ||
nonopt.js: | ||
@@ -113,3 +112,3 @@ | ||
[ 'rum' ] | ||
$ ./nonopt.js "me hearties" -x 0.54 yo -y 1.12 ho | ||
@@ -176,6 +175,6 @@ (0.54,1.12) | ||
*** | ||
$ ./divide.js -x 55 -y 11 | ||
5 | ||
$ node ./divide.js -x 4.91 -z 2.51 | ||
@@ -268,4 +267,4 @@ Usage: node ./divide.js -x [num] -y [num] | ||
[ 'me hearties', 'yo', 'ho' ] | ||
boolean_double.js | ||
@@ -335,6 +334,6 @@ | ||
$ node line_count.js --file line_count.js | ||
$ node line_count.js --file line_count.js | ||
20 | ||
$ node line_count.js -f line_count.js | ||
$ node line_count.js -f line_count.js | ||
20 | ||
@@ -415,2 +414,9 @@ | ||
.implies(x, y) | ||
-------------- | ||
Given the key `x` is set, it is required that the key `y` is set. | ||
implies can also accept an object specifying multiple implications. | ||
.describe(key, desc) | ||
@@ -428,3 +434,3 @@ -------------------- | ||
Instead of chaining together `.alias().demand().default()`, you can specify | ||
Instead of chaining together `.alias().demand().default().describe().string()`, you can specify | ||
keys in `opt` for each of the chainable methods. | ||
@@ -438,3 +444,6 @@ | ||
alias : 'file', | ||
default : '/etc/passwd', | ||
demand: true, | ||
default: '/etc/passwd', | ||
describe: 'x marks the spot', | ||
type: 'string' | ||
}) | ||
@@ -457,2 +466,17 @@ .argv | ||
````javascript | ||
var argv = require('yargs') | ||
.options({ | ||
'f': { | ||
alias: 'file', | ||
demand: true, | ||
default: '/etc/passwd', | ||
describe: 'x marks the spot', | ||
type: 'string' | ||
} | ||
}) | ||
.argv | ||
; | ||
```` | ||
.usage(message, opts) | ||
@@ -467,2 +491,17 @@ --------------------- | ||
.command(cmd, desc) | ||
------------------- | ||
Document the commands exposed by your application (stored in the `_` variable). | ||
As an example, here's how the npm cli might document some of its commands: | ||
```js | ||
var argv = require('yargs') | ||
.usage('npm <command>') | ||
.command('install', 'tis a mighty fine package to install') | ||
.command('publish', 'shiver me timbers, should you be sharing all that') | ||
.argv; | ||
``` | ||
.example(cmd, desc) | ||
@@ -476,2 +515,13 @@ ------------------- | ||
.epilogue(str) | ||
-------------- | ||
A message to print at the end of the usage instructions, e.g., | ||
```js | ||
var argv = require('yargs') | ||
.epilogue('for more information, find our manual at http://example.com'); | ||
``` | ||
.check(fn) | ||
@@ -484,5 +534,12 @@ ---------- | ||
If `fn` throws or returns `false`, show the thrown error, usage information, and | ||
If `fn` throws or returns a non-truthy value, show the thrown error, usage information, and | ||
exit. | ||
.fail(fn) | ||
--------- | ||
Method to execute when a failure occurs, rather then printing the failure message. | ||
`fn` is called with the failure message that would have been printed. | ||
.boolean(key) | ||
@@ -494,4 +551,4 @@ ------------- | ||
If `key` never shows up as a flag in `process.arguments`, `argv[key]` will be | ||
`false`. | ||
`key` will default to `false`, unless an `default(key, undefined)` is | ||
explicitly set. | ||
@@ -508,2 +565,11 @@ If `key` is an Array, interpret all the elements as booleans. | ||
`.string('_')` will result in non-hyphenated arguments being interpreted as strings, | ||
regardless of whether they resemble numbers. | ||
.array(key) | ||
---------- | ||
Tell the parser to interpret `key` as an array. If `.array('foo')` is set, | ||
`--foo bar` will be parsed as `['bar']` rather than as `'bar'`. | ||
.config(key) | ||
@@ -520,2 +586,5 @@ ------------ | ||
By default wrap will be set to `Math.min(80, windowWidth)`. Use `.wrap(null)` to | ||
specify no column limit. | ||
.strict() | ||
@@ -693,3 +762,3 @@ --------- | ||
npm install yargs | ||
or clone this project on github: | ||
@@ -701,6 +770,6 @@ | ||
just do: | ||
expresso | ||
inspired By | ||
inspired by | ||
=========== | ||
@@ -707,0 +776,0 @@ |
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
55641
7
1022
758
2
7
1
+ Addedwindow-size@0.1.0
+ Addedwordwrap@0.0.2
+ Addedwindow-size@0.1.0(transitive)
+ Addedwordwrap@0.0.2(transitive)