package/package.json000644 000765 000024 0000001114 12427206304013012 0ustar00000000 000000 { "name": "nomnom", "description": "Option parser with generated usage and commands", "version": "1.8.1", "author": "Heather Arthur ", "scripts": { "test": "./node_modules/.bin/nodeunit test/*.js" }, "repository": { "type": "git", "url": "http://github.com/harthur/nomnom.git" }, "main": "./nomnom", "keywords": [ "arguments", "option parser", "command line", "options", "parser" ], "dependencies": { "underscore": "~1.6.0", "chalk": "~0.4.0" }, "devDependencies": { "nodeunit": "~0.7.4" } } package/.npmignore000644 000765 000024 0000000015 12341107516012522 0ustar00000000 000000 node_modules package/README.md000644 000765 000024 0000017530 12413224556012020 0ustar00000000 000000 # nomnom nomnom is an option parser for node. It noms your args and gives them back to you in a hash. ```javascript var opts = require("nomnom") .option('debug', { abbr: 'd', flag: true, help: 'Print debugging info' }) .option('config', { abbr: 'c', default: 'config.json', help: 'JSON file with tests to run' }) .option('version', { flag: true, help: 'print version and exit', callback: function() { return "version 1.2.4"; } }) .parse(); if (opts.debug) // do stuff ``` You don't have to specify anything if you don't want to: ```javascript var opts = require("nomnom").parse(); var url = opts[0]; // get the first positional arg var file = opts.file // see if --file was specified var verbose = opts.v // see if -v was specified var extras = opts._ // get an array of the unmatched, positional args ``` # Install for [node.js](http://nodejs.org/) and [npm](http://github.com/isaacs/npm): npm install nomnom # More Details Nomnom supports args like `-d`, `--debug`, `--no-debug`, `--file=test.txt`, `--file test.txt`, `-f test.txt`, `-xvf`, and positionals. Positionals are arguments that don't fit the `-a` or `--atomic` format and aren't attached to an option. Values are JSON parsed, so `--debug=true --count=3 --file=log.txt` would give you: ``` { "debug": true, "count": 3, "file": "log.txt" } ``` # Commands Nomnom supports command-based interfaces (e.g. with git: `git add -p` and `git rebase -i` where `add` and `rebase` are the commands): ```javascript var parser = require("nomnom"); parser.command('browser') .callback(function(opts) { runBrowser(opts.url); }) .help("run browser tests"); parser.command('sanity') .option('outfile', { abbr: 'o', help: "file to write results to" }) .option('config', { abbr: 'c', default: 'config.json', help: "json manifest of tests to run" }) .callback(function(opts) { runSanity(opts.filename); }) .help("run the sanity tests") parser.parse(); ``` Each command generates its own usage message when `-h` or `--help` is specified with the command. # Usage Nomnom prints out a usage message if `--help` or `-h` is an argument. Usage for these options in `test.js`: ```javascript var opts = require("nomnom") .script("runtests") .options({ path: { position: 0, help: "Test file to run", list: true }, config: { abbr: 'c', metavar: 'FILE', help: "Config file with tests to run" }, debug: { abbr: 'd', flag: true, help: "Print debugging info" } }).parse(); ``` ...would look like this: usage: runtests ... [options] path Test file to run options: -c FILE, --config FILE Config file with tests to run -d, --debug Print debugging info # Options You can either add a specification for an option with `nomnom.option('name', spec)` or pass the specifications to `nomnom.options()` as a hash keyed on option name. Each option specification can have the following fields: #### abbr and full `abbr` is the single character string to match to this option, `full` is the full-length string (defaults to the name of the option). This option matches `-d` and `--debug` on the command line: ```javascript nomnom.option('debug', { abbr: 'd' }) ``` This option matches `-n 3`, `--num-lines 12` on the command line: ```javascript nomnom.option('numLines', { abbr: 'n', full: 'num-lines' }) ``` #### flag If this is set to true, the option acts as a flag and doesn't swallow the next value on the command line. Default is `false`, so normally if you had a command line `--config test.js`, `config` would get a value of `test.js` in the options hash. Whereas if you specify: ```javascript nomnom.option('config', { flag: true }) ``` `config` would get a value of `true` in the options hash, and `test.js` would be a free positional arg. #### metavar `metavar` is used in the usage printout e.g. `"PATH"` in `"-f PATH, --file PATH"`. #### string A shorthand for `abbr`, `full`, and `metavar`. For example, to attach an option to `-c` and `--config` use a `string: "-c FILE, --config=FILE"` #### help A string description of the option for the usage printout. #### default The value to give the option if it's not specified in the arguments. #### type If you don't want the option JSON-parsed, specify type `"string"`. #### callback A callback that will be executed as soon as the option is encountered. If the callback returns a string it will print the string and exit: ```javascript nomnom.option('count', { callback: function(count) { if (count != parseInt(count)) { return "count must be an integer"; } } }) ``` #### position The position of the option if it's a positional argument. If the option should be matched to the first positional arg use position `0`, etc. #### list Specifies that the option is a list. Appending can be achieved by specifying the arg more than once on the command line: node test.js --file=test1.js --file=test2.js If the option has a `position` and `list` is `true`, all positional args including and after `position` will be appended to the array. #### required If this is set to `true` and the option isn't in the args, a message will be printed and the program will exit. #### choices A list of the possible values for the option (e.g. `['run', 'test', 'open']`). If the parsed value isn't in the list a message will be printed and the program will exit. #### transform A function that takes the value of the option as entered and returns a new value that will be seen as the value of the option. ```javascript nomnom.option('date', { abbr: 'd', transform: function(timestamp) { return new Date(timestamp); } }) ``` #### hidden Option won't be printed in the usage # Parser interface `require("nomnom")` will give you the option parser. You can also make an instance of a parser with `require("nomnom")()`. You can chain any of these functions off of a parser: #### option Add an option specification with the given name: ```javascript nomnom.option('debug', { abbr: 'd', flag: true, help: "Print debugging info" }) ``` #### options Add options as a hash keyed by option name, good for a cli with tons of options like [this example](http://github.com/harthur/replace/blob/master/bin/replace.js): ```javascript nomnom.options({ debug: { abbr: 'd', flag: true, help: "Print debugging info" }, fruit: { help: "Fruit to buy" } }) ``` #### usage The string that will override the default generated usage message. #### help A string that is appended to the usage. #### script Nomnom can't detect the alias used to run your script. You can use `script` to provide the correct name for the usage printout instead of e.g. `node test.js`. #### printer Overrides the usage printing function. #### command Takes a command name and gives you a command object on which you can chain command options. #### nocommand Gives a command object that will be used when no command is called. #### nocolors Disables coloring of the usage message. #### parse Parses node's `process.argv` and returns the parsed options hash. You can also provide argv: ```javascript var opts = nomnom.parse(["-xvf", "--atomic=true"]) ``` #### nom The same as `parse()`. # Command interface A command is specified with `nomnom.command('name')`. All these functions can be chained on a command: #### option Add an option specifically for this command. #### options Add options for this command as a hash of options keyed by name. #### callback A callback that will be called with the parsed options when the command is used. #### help A help string describing the function of this command. #### usage Override the default generated usage string for this command. package/LICENSE000644 000765 000024 0000002042 12341107516011532 0ustar00000000 000000 Copyright (c) 2010 Heather Arthur Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package/nomnom.js000644 000765 000024 0000033544 12427204320012375 0ustar00000000 000000 var _ = require("underscore"), chalk = require('chalk'); function ArgParser() { this.commands = {}; // expected commands this.specs = {}; // option specifications } ArgParser.prototype = { /* Add a command to the expected commands */ command : function(name) { var command; if (name) { command = this.commands[name] = { name: name, specs: {} }; } else { command = this.fallback = { specs: {} }; } // facilitates command('name').options().cb().help() var chain = { options : function(specs) { command.specs = specs; return chain; }, opts : function(specs) { // old API return this.options(specs); }, option : function(name, spec) { command.specs[name] = spec; return chain; }, callback : function(cb) { command.cb = cb; return chain; }, help : function(help) { command.help = help; return chain; }, usage : function(usage) { command._usage = usage; return chain; } }; return chain; }, nocommand : function() { return this.command(); }, options : function(specs) { this.specs = specs; return this; }, opts : function(specs) { // old API return this.options(specs); }, globalOpts : function(specs) { // old API return this.options(specs); }, option : function(name, spec) { this.specs[name] = spec; return this; }, usage : function(usage) { this._usage = usage; return this; }, printer : function(print) { this.print = print; return this; }, script : function(script) { this._script = script; return this; }, scriptName : function(script) { // old API return this.script(script); }, help : function(help) { this._help = help; return this; }, colors: function() { // deprecated - colors are on by default now return this; }, nocolors : function() { this._nocolors = true; return this; }, parseArgs : function(argv) { // old API return this.parse(argv); }, nom : function(argv) { return this.parse(argv); }, parse : function(argv) { this.print = this.print || function(str, code) { console.log(str); process.exit(code || 0); }; this._help = this._help || ""; this._script = this._script || process.argv[0] + " " + require('path').basename(process.argv[1]); this.specs = this.specs || {}; var argv = argv || process.argv.slice(2); var arg = Arg(argv[0]).isValue && argv[0], command = arg && this.commands[arg], commandExpected = !_(this.commands).isEmpty(); if (commandExpected) { if (command) { _(this.specs).extend(command.specs); this._script += " " + command.name; if (command.help) { this._help = command.help; } this.command = command; } else if (arg) { return this.print(this._script + ": no such command '" + arg + "'", 1); } else { // no command but command expected e.g. 'git -v' var helpStringBuilder = { list : function() { return 'one of: ' + _(this.commands).keys().join(", "); }, twoColumn : function() { // find the longest command name to ensure horizontal alignment var maxLength = _(this.commands).max(function (cmd) { return cmd.name.length; }).name.length; // create the two column text strings var cmdHelp = _.map(this.commands, function(cmd, name) { var diff = maxLength - name.length; var pad = new Array(diff + 4).join(" "); return " " + [ name, pad, cmd.help ].join(" "); }); return "\n" + cmdHelp.join("\n"); } }; // if there are a small number of commands and all have help strings, // display them in a two column table; otherwise use the brief version. // The arbitrary choice of "20" comes from the number commands git // displays as "common commands" var helpType = 'list'; if (_(this.commands).size() <= 20) { if (_(this.commands).every(function (cmd) { return cmd.help; })) { helpType = 'twoColumn'; } } this.specs.command = { position: 0, help: helpStringBuilder[helpType].call(this) } if (this.fallback) { _(this.specs).extend(this.fallback.specs); this._help = this.fallback.help; } else { this.specs.command.required = true; } } } if (this.specs.length === undefined) { // specs is a hash not an array this.specs = _(this.specs).map(function(opt, name) { opt.name = name; return opt; }); } this.specs = this.specs.map(function(opt) { return Opt(opt); }); if (argv.indexOf("--help") >= 0 || argv.indexOf("-h") >= 0) { return this.print(this.getUsage()); } var options = {}; var args = argv.map(function(arg) { return Arg(arg); }) .concat(Arg()); var positionals = []; /* parse the args */ var that = this; args.reduce(function(arg, val) { /* positional */ if (arg.isValue) { positionals.push(arg.value); } else if (arg.chars) { var last = arg.chars.pop(); /* -cfv */ (arg.chars).forEach(function(ch) { that.setOption(options, ch, true); }); /* -v key */ if (!that.opt(last).flag) { if (val.isValue) { that.setOption(options, last, val.value); return Arg(); // skip next turn - swallow arg } else { that.print("'-" + (that.opt(last).name || last) + "'" + " expects a value\n\n" + that.getUsage(), 1); } } else { /* -v */ that.setOption(options, last, true); } } else if (arg.full) { var value = arg.value; /* --key */ if (value === undefined) { /* --key value */ if (!that.opt(arg.full).flag) { if (val.isValue) { that.setOption(options, arg.full, val.value); return Arg(); } else { that.print("'--" + (that.opt(arg.full).name || arg.full) + "'" + " expects a value\n\n" + that.getUsage(), 1); } } else { /* --flag */ value = true; } } that.setOption(options, arg.full, value); } return val; }); positionals.forEach(function(pos, index) { this.setOption(options, index, pos); }, this); options._ = positionals; this.specs.forEach(function(opt) { if (opt.default !== undefined && options[opt.name] === undefined) { options[opt.name] = opt.default; } }, this); // exit if required arg isn't present this.specs.forEach(function(opt) { if (opt.required && options[opt.name] === undefined) { var msg = opt.name + " argument is required"; msg = this._nocolors ? msg : chalk.red(msg); this.print("\n" + msg + "\n" + this.getUsage(), 1); } }, this); if (command && command.cb) { command.cb(options); } else if (this.fallback && this.fallback.cb) { this.fallback.cb(options); } return options; }, getUsage : function() { if (this.command && this.command._usage) { return this.command._usage; } else if (this.fallback && this.fallback._usage) { return this.fallback._usage; } if (this._usage) { return this._usage; } // todo: use a template var str = "\n" if (!this._nocolors) { str += chalk.bold("Usage:"); } else { str += "Usage:"; } str += " " + this._script; var positionals = _(this.specs).select(function(opt) { return opt.position != undefined; }) positionals = _(positionals).sortBy(function(opt) { return opt.position; }); var options = _(this.specs).select(function(opt) { return opt.position === undefined; }); // assume there are no gaps in the specified pos. args positionals.forEach(function(pos) { str += " "; var posStr = pos.string; if (!posStr) { posStr = pos.name || "arg" + pos.position; if (pos.required) { posStr = "<" + posStr + ">"; } else { posStr = "[" + posStr + "]"; } if (pos.list) { posStr += "..."; } } str += posStr; }); if (options.length) { if (!this._nocolors) { // must be a better way to do this str += chalk.blue(" [options]"); } else { str += " [options]"; } } if (options.length || positionals.length) { str += "\n\n"; } function spaces(length) { var spaces = ""; for (var i = 0; i < length; i++) { spaces += " "; } return spaces; } var longest = positionals.reduce(function(max, pos) { return pos.name.length > max ? pos.name.length : max; }, 0); positionals.forEach(function(pos) { var posStr = pos.string || pos.name; str += posStr + spaces(longest - posStr.length) + " "; if (!this._nocolors) { str += chalk.grey(pos.help || "") } else { str += (pos.help || "") } str += "\n"; }, this); if (positionals.length && options.length) { str += "\n"; } if (options.length) { if (!this._nocolors) { str += chalk.blue("Options:"); } else { str += "Options:"; } str += "\n" var longest = options.reduce(function(max, opt) { return opt.string.length > max && !opt.hidden ? opt.string.length : max; }, 0); options.forEach(function(opt) { if (!opt.hidden) { str += " " + opt.string + spaces(longest - opt.string.length) + " "; var defaults = (opt.default != null ? " [" + opt.default + "]" : ""); var help = opt.help ? opt.help + defaults : ""; str += this._nocolors ? help: chalk.grey(help); str += "\n"; } }, this); } if (this._help) { str += "\n" + this._help; } return str; } }; ArgParser.prototype.opt = function(arg) { // get the specified opt for this parsed arg var match = Opt({}); this.specs.forEach(function(opt) { if (opt.matches(arg)) { match = opt; } }); return match; }; ArgParser.prototype.setOption = function(options, arg, value) { var option = this.opt(arg); if (option.callback) { var message = option.callback(value); if (typeof message == "string") { this.print(message, 1); } } if (option.type != "string") { try { // infer type by JSON parsing the string value = JSON.parse(value) } catch(e) {} } if (option.transform) { value = option.transform(value); } var name = option.name || arg; if (option.choices && option.choices.indexOf(value) == -1) { this.print(name + " must be one of: " + option.choices.join(", "), 1); } if (option.list) { if (!options[name]) { options[name] = [value]; } else { options[name].push(value); } } else { options[name] = value; } }; /* an arg is an item that's actually parsed from the command line e.g. "-l", "log.txt", or "--logfile=log.txt" */ var Arg = function(str) { var abbrRegex = /^\-(\w+?)$/, fullRegex = /^\-\-(no\-)?(.+?)(?:=(.+))?$/, valRegex = /^[^\-].*/; var charMatch = abbrRegex.exec(str), chars = charMatch && charMatch[1].split(""); var fullMatch = fullRegex.exec(str), full = fullMatch && fullMatch[2]; var isValue = str !== undefined && (str === "" || valRegex.test(str)); var value; if (isValue) { value = str; } else if (full) { value = fullMatch[1] ? false : fullMatch[3]; } return { str: str, chars: chars, full: full, value: value, isValue: isValue } } /* an opt is what's specified by the user in opts hash */ var Opt = function(opt) { var strings = (opt.string || "").split(","), abbr, full, metavar; for (var i = 0; i < strings.length; i++) { var string = strings[i].trim(), matches; if (matches = string.match(/^\-([^-])(?:\s+(.*))?$/)) { abbr = matches[1]; metavar = matches[2]; } else if (matches = string.match(/^\-\-(.+?)(?:[=\s]+(.+))?$/)) { full = matches[1]; metavar = metavar || matches[2]; } } matches = matches || []; var abbr = opt.abbr || abbr, // e.g. v from -v full = opt.full || full, // e.g. verbose from --verbose metavar = opt.metavar || metavar; // e.g. PATH from '--config=PATH' var string; if (opt.string) { string = opt.string; } else if (opt.position === undefined) { string = ""; if (abbr) { string += "-" + abbr; if (metavar) string += " " + metavar string += ", "; } string += "--" + (full || opt.name); if (metavar) { string += " " + metavar; } } opt = _(opt).extend({ name: opt.name || full || abbr, string: string, abbr: abbr, full: full, metavar: metavar, matches: function(arg) { return opt.full == arg || opt.abbr == arg || opt.position == arg || opt.name == arg || (opt.list && arg >= opt.position); } }); return opt; } var createParser = function() { return new ArgParser(); } var nomnom = createParser(); for (var i in nomnom) { if (typeof nomnom[i] == "function") { createParser[i] = _(nomnom[i]).bind(nomnom); } } module.exports = createParser; package/test.js000644 000765 000024 0000000714 11654277223012057 0ustar00000000 000000 var opts = require("./nomnom") .option('debug', { abbr: 'd', flag: true, help: 'Print debugging info' }) .option('config', { abbr: 'c', default: 'config.json', help: 'JSON file with tests to run' }) .option('version', { flag: true, help: 'print version and exit', callback: function() { return "version 1.2.4"; } }) .parse(); if (opts.debug) { console.log("debug") } package/num-vals-fix.diff000644 000765 000024 0000001307 12427204300013702 0ustar00000000 000000 diff --git a/test/values.js b/test/values.js index efad789..7fa1078 100644 --- a/test/values.js +++ b/test/values.js @@ -26,6 +26,12 @@ var opts = { }, def2: { default: "val1" + }, + "2d": { + flag: true + }, + "3d": { + abbr: "3" } } @@ -80,8 +86,12 @@ exports.testDash = function(test) { }; exports.testNumbers = function(test) { - var options = parser.parseArgs(['sum', '-1', '2.5', '-3.5', '4']); + var options = parser.parseArgs(['sum', '-1', '2.5', '-3.5', '4', '--2d', '-3', 'test']); test.deepEqual(options.list3, ['-1', '2.5', '-3.5', '4']); + test.strictEqual(options['2d'], true); + test.strictEqual(options['3d'], "test") test.done(); }; + + package/test/callback.js000644 000765 000024 0000001213 11654300035013572 0ustar00000000 000000 var nomnom = require("../nomnom"); exports.testVersion = function(test) { test.expect(1); nomnom().options({ date: { callback: function(date) { test.equal(date, "2010-02-03", "date should match value") } } }).parse(["--date=2010-02-03"]); test.done(); } exports.testReturnString = function(test) { test.expect(1); nomnom().options({ version: { flag: true, callback: function() { return "v0.3"; } } }) .printer(function(string) { test.equal(0, string.indexOf("v0.3")) test.done(); }) .parse(["--version"]); }package/test/commands.js000644 000765 000024 0000004727 12341107516013657 0ustar00000000 000000 var nomnom = require("../nomnom"); function strip(str) { return str.replace(/\s+/g, ''); } exports.testCallback = function(test) { test.expect(1); var parser = nomnom(); parser.command('run').callback(function(options) { test.equal(options.v, 3); }); parser.command('other').callback(function() { test.ok(false, "callback for other command shouldn't be called"); }); parser.parse(["run","-v", "3"]); test.done(); } exports.testMissingCommand = function(test) { test.expect(1); var parser = nomnom().scriptName("test"); parser.command('run'); parser.printer(function(string) { test.equal(string, "test: no such command 'other'"); test.done(); }); parser.parse(["other"]); } exports.testNoCommand = function(test) { test.expect(2); var parser = nomnom(); parser.nocommand() .options({ version: { flag: true } }) .callback(function(options) { test.strictEqual(options.version, true); }) .usage("fallback usage"); parser.command('run'); var options = parser.parse(["--version"]); test.strictEqual(options.version, true); test.done(); } function createParser() { var parser = nomnom().scriptName("test") .options({ debug: { flag: true } }); parser.command('run') .options({ file: { help: 'file to run' } }) .help("run all"); parser.command('test').usage("test usage"); parser.nocommand() .options({ verbose: { flag: true } }) .help("nocommand"); return parser; } exports.testUsage = function(test) { test.expect(4); var parser = createParser(); parser.printer(function(string) { test.equal(strip(string), "testusage"); }); parser.parse(["test", "-h"]); parser = createParser().nocolors(); parser.printer(function(string) { test.equal(strip(string), "Usage:testrun[options]Options:--debug--filefiletorunrunall"); }); parser.parse(["run", "-h"]); parser = createParser().nocolors(); parser.printer(function(string) { test.equal(strip(string), "Usage:test[command][options]commandoneof:run,testOptions:--debug--verbosenocommand"); }); parser.parse(["-h"]); parser = createParser().nocolors(); parser.nocommand() .usage("fallback"); parser.printer(function(string) { test.equal(strip(string), "fallback"); }); parser.parse(["-h"]); test.done(); } package/test/expected.js000644 000765 000024 0000002156 12341107516013651 0ustar00000000 000000 var nomnom = require("../nomnom"); var opts = { file: { position: 0, required: true } } var parser = nomnom().options(opts); exports.testFlag = function(test) { test.expect(1); nomnom().options({ file: { position: 0, } }) .printer(function(string) { test.equal(0, string.indexOf("'--key1' expects a value")) test.done(); }) .parse(["--key1"]); } exports.testRequired = function(test) { test.expect(1); nomnom().options({ file: { required: true } }) .printer(function(string) { test.equal(0, string.trim().indexOf("file argument is required")) test.done(); }) .nocolors() .parse([]); } exports.testChoices = function(test) { test.expect(2); var parser = nomnom().options({ color: { choices: ['green', 'blue'] } }) .printer(function(string) { test.equal(0, string.indexOf("color must be one of: green, blue")) }); parser.parse(['--color', 'red']); var options = parser.parse(['--color', 'green']); test.equal(options.color, 'green'); test.done(); } package/test/matching.js000644 000765 000024 0000002707 11654146456013660 0ustar00000000 000000 var nomnom = require("../nomnom"); var opts = { pos1: { position: 0 }, pos2: { position: 1 }, flag1: { flag: true }, debug: { abbr: 'd' }, numLines: { abbr: 'n', full: 'num-lines' }, version: { string: '-v, --version' }, config: { string: '-c FILE, --config=FILE' }, skey : { string: '-k val' }, skey2: { string: '-k2 val2, --key2 val2' }, skey3: { string: '--key3=val' }, skey4: { string: '--key4=val, -y val' } } var parser = nomnom().options(opts); exports.testPositional = function(test) { var options = parser.parse(["--flag1", "val1", "--config", "file", "val2"]); test.equal(options.pos1, "val1"); test.equal(options.pos2, "val2"); test.deepEqual(options._, ["val1", "val2"]) test.done(); } exports.testAbbr = function(test) { var options = parser.parse(["-d", "yes", "--num-lines", "3"]); test.equal(options.debug, "yes") test.equal(options.numLines, 3) test.done(); } exports.testString = function(test) { var options = parser.parse(["-k", "val", "--config=test.js", "--key2", "val2", "--key3", "val3", "--key4=val4", "-v", "v0.3"]); test.equal(options.version, "v0.3") test.equal(options.config, "test.js") test.equal(options.skey, "val") test.equal(options.skey2, "val2") test.equal(options.skey3, "val3") test.equal(options.skey4, "val4") test.done(); } package/test/option.js000644 000765 000024 0000001577 11654266023013373 0ustar00000000 000000 var nomnom = require("../nomnom"); var parser = nomnom() .option('debug', { abbr: 'x', flag: true, help: 'Print debugging info' }) .option('config', { abbr: 'c', default: 'config.json', help: 'JSON file with tests to run' }) .option('version', { flag: true, help: 'print version and exit', callback: function() { return "version 1.2.4"; } }); exports.testOption = function(test) { var opts = parser.parse(["-x", "--no-verbose"]); test.strictEqual(opts.debug, true); test.equal(opts.config, "config.json"); test.done(); } exports.testCommandOption = function(test) { var parser = nomnom() parser.command('test') .option('fruit', { abbr: 'f', flag: true }) var opts = parser.parse(["test", "-f"]); test.strictEqual(opts.fruit, true); test.done(); } package/test/transform.js000644 000765 000024 0000003042 12341111655014055 0ustar00000000 000000 var nomnom = require("../nomnom"); var parser = nomnom() .option("addr", { abbr: "a", help: "host:port address", transform: function(value) { var parts = value.split(":"); return {host: parts[0], port: Number(parts[1])}; } }) .option("string", { abbr: "s", help: "always a string", transform: function(value) { return value.toString(); } }); exports.testTransformComplexValue = function(test) { var opts = parser.parse(["-a", "localhost:1234"]); test.strictEqual(opts.addr.host, "localhost"); test.strictEqual(opts.addr.port, 1234); test.done(); }; exports.testTransformString = function(test) { var opts = parser.parse(["-s", "3"]); test.strictEqual(opts.string, "3"); test.done(); }; exports.testTransformCommand = function(test) { test.expect(1); var parser = nomnom().scriptName("test") .options({ addr: { transform: function(value) { var parts = value.split(":"); return {host: parts[0], port: Number(parts[1])}; } } }); parser.command("run") .options({ string: { transform: function(value) { return value.toString(); } } }) .callback(function(options) { test.strictEqual(options.string, "true"); }); parser.parse(["run", "--string=true"]); test.done(); }; package/test/usage.js000644 000765 000024 0000004326 12341107516013155 0ustar00000000 000000 var nomnom = require("../nomnom"); function strip(str) { return str.replace(/\s+/g, ''); }; var opts = { apple: { abbr: 'a', help: 'how many apples' }, banana: { full: "b-nana" }, carrot: { string: '-c NUM, --carrots=NUM' }, dill: { metavar: 'PICKLE' }, egg: { position: 0, help: 'robin' } } var parser = nomnom().options(opts).help("all the best foods").scriptName("test").nocolors(); var expected = "Usage:test[egg][options]eggrobinOptions:-a,--applehowmanyapples--b-nana-cNUM,--carrots=NUM--dillPICKLEallthebestfoods" exports.testH = function(test) { test.expect(1); parser.printer(function(string) { test.equal(strip(string), expected) test.done(); }) .nocolors() .parse(["-h"]); } exports.testHelp = function(test) { test.expect(1); parser.printer(function(string) { test.equal(strip(string), expected) test.done(); }) .nocolors() .parse(["--help"]); } exports.testScriptName = function(test) { test.expect(1); nomnom() .script("test") .printer(function(string) { test.equal(strip(string),"Usage:test") test.done(); }) .nocolors() .parse(["-h"]); } exports.testUsage = function(test) { test.expect(1); parser .usage("test usage") .printer(function(string) { test.equal(string, "test usage") test.done(); }) .nocolors() .parse(["--help"]); } exports.testHidden = function(test) { test.expect(1); nomnom().options({ file: { hidden: true } }) .scriptName("test") .printer(function(string) { test.equal(strip("Usage:test[options]Options:"), strip(string)) test.done(); }) .nocolors() .parse(["-h"]); } exports.testRequiredOptional = function(test) { test.expect(1); nomnom().options({ foo: { position: 0, required: true, help: 'The foo' }, bar: { position: 1, help: 'The bar' } }) .scriptName("test") .printer(function(string) { test.equal(strip("Usage:test[bar]fooThefoobarThebar"), strip(string)) test.done(); }) .nocolors() .parse(["-h"]); } package/test/values.js000644 000765 000024 0000003147 12427204320013344 0ustar00000000 000000 var nomnom = require("../nomnom"); var opts = { debug: { flag: true }, verbose: { flag: true, default: true }, list1: { list: true }, list2: { list: true }, list3: { position: 1, list: true }, num1: { type: "string" }, def1: { default: "val1" }, def2: { default: "val1" } } var parser = nomnom().options(opts); exports.testFlag = function(test) { var options = parser.parse(["--debug", "pos0", "--no-verbose"]); test.strictEqual(options.debug, true); test.strictEqual(options.verbose, false); test.equal(options[0], "pos0"); test.equal(options._[0], "pos0"); test.done(); } exports.testList = function(test) { var options = parser.parse(["pos0", "pos1", "--list1=val0", "--list2", "val1", "--list2", "val2", "pos2"]); test.deepEqual(options.list1, ["val0"]); test.deepEqual(options.list2, ["val1", "val2"]); test.deepEqual(options.list3, ["pos1", "pos2"]); test.done(); } exports.testDefault = function(test) { var options = parser.parse(["--def2", "val2", "--def3", "val3"]); test.strictEqual(options.def1, "val1"); test.strictEqual(options.def2, "val2"); test.strictEqual(options.def3, "val3"); test.done(); } exports.testTypes = function(test) { var options = parser.parseArgs(["", "-x", "3.14", "-w", "true", "-q", "120", "--num1", "4"]); test.strictEqual(options[0], ""); test.strictEqual(options.x, 3.14); test.strictEqual(options.w, true); test.strictEqual(options.q, 120); test.strictEqual(options.num1, "4"); test.done(); }