Project rename

This commit is contained in:
2019-03-24 08:28:57 +01:00
parent 1728e0e6e1
commit 7926230faf
7262 changed files with 0 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
node_modules
+20
View File
@@ -0,0 +1,20 @@
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.
+325
View File
@@ -0,0 +1,325 @@
# 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 <path>... [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.
+584
View File
@@ -0,0 +1,584 @@
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;
+31
View File
@@ -0,0 +1,31 @@
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();
};
+
+
+90
View File
@@ -0,0 +1,90 @@
{
"_args": [
[
{
"raw": "nomnom@^1.5.x",
"scope": null,
"escapedName": "nomnom",
"name": "nomnom",
"rawSpec": "^1.5.x",
"spec": ">=1.5.0 <2.0.0",
"type": "range"
},
"/Users/gerrit/Documents/dev/nodejs/rentfor.camp/html/RentForCamp/node_modules/jsonlint"
]
],
"_from": "nomnom@>=1.5.0 <2.0.0",
"_id": "nomnom@1.8.1",
"_inCache": true,
"_location": "/nomnom",
"_npmUser": {
"name": "harth",
"email": "fayearthur@gmail.com"
},
"_npmVersion": "1.4.3",
"_phantomChildren": {},
"_requested": {
"raw": "nomnom@^1.5.x",
"scope": null,
"escapedName": "nomnom",
"name": "nomnom",
"rawSpec": "^1.5.x",
"spec": ">=1.5.0 <2.0.0",
"type": "range"
},
"_requiredBy": [
"/jsonlint"
],
"_resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz",
"_shasum": "2151f722472ba79e50a76fc125bb8c8f2e4dc2a7",
"_shrinkwrap": null,
"_spec": "nomnom@^1.5.x",
"_where": "/Users/gerrit/Documents/dev/nodejs/rentfor.camp/html/RentForCamp/node_modules/jsonlint",
"author": {
"name": "Heather Arthur",
"email": "fayearthur@gmail.com"
},
"bugs": {
"url": "https://github.com/harthur/nomnom/issues"
},
"dependencies": {
"chalk": "~0.4.0",
"underscore": "~1.6.0"
},
"deprecated": "Package no longer supported. Contact support@npmjs.com for more info.",
"description": "Option parser with generated usage and commands",
"devDependencies": {
"nodeunit": "~0.7.4"
},
"directories": {},
"dist": {
"shasum": "2151f722472ba79e50a76fc125bb8c8f2e4dc2a7",
"tarball": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz"
},
"homepage": "https://github.com/harthur/nomnom",
"keywords": [
"arguments",
"option parser",
"command line",
"options",
"parser"
],
"main": "./nomnom",
"maintainers": [
{
"name": "harth",
"email": "fayearthur@gmail.com"
}
],
"name": "nomnom",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/harthur/nomnom.git"
},
"scripts": {
"test": "nodeunit test/*.js"
},
"version": "1.8.1"
}
+23
View File
@@ -0,0 +1,23 @@
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")
}
+33
View File
@@ -0,0 +1,33 @@
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"]);
}
+120
View File
@@ -0,0 +1,120 @@
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();
}
+60
View File
@@ -0,0 +1,60 @@
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();
}
+70
View File
@@ -0,0 +1,70 @@
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();
}
+44
View File
@@ -0,0 +1,44 @@
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();
}
+65
View File
@@ -0,0 +1,65 @@
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();
};
+121
View File
@@ -0,0 +1,121 @@
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<foo>[bar]fooThefoobarThebar"), strip(string))
test.done();
})
.nocolors()
.parse(["-h"]);
}
+75
View File
@@ -0,0 +1,75 @@
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();
}