Skip to content
Browse files

change parser options hash into chainable functions

  • Loading branch information...
1 parent 80a9cde commit 98697eb4f64e2d38c2ff5ac09ca64f708b5afae5 @harthur committed Apr 15, 2011
Showing with 177 additions and 81 deletions.
  1. +50 −35 README.md
  2. +85 −40 lib/nomnom.js
  3. +3 −3 package.json
  4. +36 −0 test/chain.js
  5. +1 −1 test/hash.js
  6. +2 −2 test/help.js
View
85 README.md
@@ -1,28 +1,26 @@
# nomnom
-nomnom is an option parser for node and CommonJS. It just noms your args and gives them back to you in a hash.
+nomnom is an option parser for node and CommonJS. It noms your args and gives them back to you in a hash.
- var nomnom = require("nomnom");
-
- var opts = {
- config: {
- string: '-c PATH, --config=PATH',
- default: 'config.json',
- help: 'JSON file with tests to run'
- },
- debug: {
- string: '-d',
- help: 'Use debug mode'
- }
- };
-
- var options = nomnom.parseArgs(opts);
+ var options = require("nomnom")
+ .opts({
+ config: {
+ string: '-c PATH, --config=PATH',
+ default: 'config.json',
+ help: 'JSON file with tests to run'
+ },
+ debug: {
+ string: '-d, --debug',
+ help: 'Print debugging info'
+ }
+ })
+ .parseArgs();
if(options.debug)
// do stuff
-You don't even have to specify anything if you don't want to:
+You don't have to specify anything if you don't want to:
- var options = nomnom.parseArgs();
+ var options = require("nomnom").parseArgs();
var url = options[0]; // get the first positional arg
var debug = options.debug // see if --debug was specified
@@ -36,7 +34,13 @@ for [node.js](http://nodejs.org/) and [npm](http://github.com/isaacs/npm):
# Commands
Nomnom supports command-based interfaces, e.g. with git: `git add -p` and `git rebase -i` where `add` and `rebase` are the commands:
- var parser = nomnom();
+ var parser = require("nomnom")
+ .opts({ // global opts
+ debug: {
+ string: '-d, --debug',
+ help: 'print debugging info'
+ }
+ });
parser.command('sanity')
.opts({
@@ -59,12 +63,12 @@ Nomnom supports command-based interfaces, e.g. with git: `git add -p` and `git r
.callback(runBrowser)
.help("run browser tests");
- parser.parseArgs(globalOpts);
+ parser.parseArgs();
# More Details
By default, nomnom parses [node](http://nodejs.org/)'s `process.argv`. You can also pass in the args:
- var options = nomnom.parseArgs(opts, { argv: ["-xvf", "--atomic=true"] })
+ var options = nomnom.parseArgs(["-xvf", "--atomic=true"])
Values are JSON parsed, so `--debug=true --count=3 --file=log.txt` would give you:
@@ -76,24 +80,35 @@ Values are JSON parsed, so `--debug=true --count=3 --file=log.txt` would give yo
### positional args
All parsed arguments that don't fit the `-a` or `--atomic` format and aren't attached to an option are positional and can be matched on via the `position`:
- var opts = {
- filename: {
- position: 0,
- help: 'file to edit'
- }
- };
- var options = nomnom.parseArgs(opts);
+ var options = require("nomnom")
+ .opts({
+ filename: {
+ position: 0,
+ help: 'file to edit'
+ }
+ })
+ .parseArgs();
- sys.puts(options.filename);
+ console.log(options.filename);
### printing usage
-Nomnom prints out a usage message if `--help` or `-h` is an argument. You can disable this with the `printHelp` flag and specify the printing function with `printFunc`:
+Nomnom prints out a usage message if `--help` or `-h` is an argument. You can override the usage string with `usage`:
- nomnom.parseArgs(opts, { printHelp: false });
+ nomnom.usage("node test.js <filename> --debug");
+
+override the printing function with `printFunc`:
+
+ nomnom.printFunc(function(usage) {
+ console.log(usage);
+ });
+
+and add a line to the usage with `help`:
+
+ nomnom.help("runtests.js will run all the tests in the current directory");
Usage for these options in `test.js`:
- var options = {
+ var options = nomnom.opts({
command: {
position: 0,
help: "either 'test', 'run', or 'xpi'"
@@ -106,7 +121,7 @@ Usage for these options in `test.js`:
string: '-d, --debug',
help: 'use debug mode'
}
- }
+ }).parseArgs();
...would look like this:
@@ -118,6 +133,6 @@ Usage for these options in `test.js`:
-c FILE, --config=FILE json file with tests to run
-d, --debug use debug mode
-Nomnom can't detect the alias used to run your script. You can use the `script` option to print the correct name instead of e.g. `node test.js`:
+Nomnom can't detect the alias used to run your script. You can use the `scriptName` option to print the correct name instead of e.g. `node test.js`:
- nomnom.parseArgs(opts, { script : "test" });
+ nomnom.scriptName("runtests");
View
125 lib/nomnom.js
@@ -3,15 +3,18 @@ var _ = require("underscore")._;
module.exports = ArgParser;
// for nomnom.parseArgs()
-var parser = ArgParser();
-ArgParser.parseArgs = parser.parseArgs.bind(parser);
+var argParser = ArgParser();
+for(var i in argParser) {
+ if(typeof argParser[i] == "function")
+ ArgParser[i] = argParser[i];
+}
function ArgParser() {
function opt(arg) {
// get the specified opt for this parsed arg
var match = Opt({});
- parser.opts.forEach(function(opt) {
+ parser.specs.forEach(function(opt) {
if(opt.matches(arg))
match = opt;
});
@@ -23,18 +26,19 @@ function ArgParser() {
};
var parser = {
- commands : {},
+ commands : {},
+ specs: [],
command : function(name) {
var command = parser.commands[name] = {
name: name,
- opts: {}
+ specs: {}
};
// facilitates command('name').opts().callback().help()
return new (function(){
- this.opts = function(opts) {
- command.opts = opts;
+ this.opts = function(specs) {
+ command.specs = specs;
return this;
};
this.callback = function(callback) {
@@ -47,22 +51,56 @@ function ArgParser() {
};
});
},
+
+ opts : function(specs) {
+ parser.specs = specs;
+ return parser;
+ },
+
+ usage : function(usageString) {
+ parser.usageString = usageString;
+ return parser;
+ },
+
+ printFunc : function(print) {
+ parser.print = print;
+ return parser;
+ },
+
+ scriptName : function(script) {
+ parser.script = script;
+ return parser;
+ },
+
+ help : function(helpString) {
+ parser.helpString = helpString;
+ return parser;
+ },
- parseArgs : function(opts, parserOpts, argv) {
- parserOpts = parserOpts || {};
- var print = parserOpts.printFunc || function(str) {
+ parseArgs : function(argv, parserOpts) {
+ var printHelp = true;
+ if(argv && (!argv.length || typeof argv[0] != "string")) {
+ // using old API
+ parser.specs = argv;
+
+ parserOpts = parserOpts || {};
+ parser.script = parserOpts.script;
+ parser.print = parserOpts.pringFunc;
+ printHelp = parserOpts.printHelp;
+ if(printHelp == undefined)
+ printHelp = true;
+ argv = parserOpts.argv;
+ }
+ var print = parser.print || function(str) {
require("sys").puts(str);
process.exit(0);
};
- var printHelp = parserOpts.printHelp;
- if(printHelp == undefined)
- printHelp = true;
- parser.help = parserOpts.help || ""; // usage
- parser.script = parserOpts.script || process.argv[0] + " "
- + require('path').basename(process.argv[1]); // usage
- parser.opts = opts || {};
+ parser.helpString = parser.helpString || "";
+ parser.script = parser.script || process.argv[0] + " "
+ + require('path').basename(process.argv[1]);
+ parser.specs = parser.specs || {};
- var argv = parserOpts.argv || process.argv.slice(2);
+ var argv = argv || process.argv.slice(2);
var commandName;
if(JSON.stringify(parser.commands) != "{}") {
@@ -71,7 +109,7 @@ function ArgParser() {
if(!commandName) {
// no command but command expected e.g. 'git --version'
- parser.opts.command = {
+ parser.specs.command = {
position: 0,
help: 'one of: ' + _(parser.commands).keys().join(", ")
}
@@ -81,31 +119,31 @@ function ArgParser() {
var command = parser.commands[commandName];
if(!command)
print(parser.script + ": no such command '" + commandName + "'");
- parser.opts = _(command.opts).extend(parser.opts);
+ parser.specs = _(command.specs).extend(parser.specs);
parser.script += " " + command.name;
if(command.help)
- parser.help = command.help;
+ parser.helpString = command.help;
}
}
- if(parser.opts.length == undefined) {
- // opts is a hash not an array
- parser.opts = _(parser.opts).map(function(opt, name) {
+ if(parser.specs.length == undefined) {
+ // specs is a hash not an array
+ parser.specs = _(parser.specs).map(function(opt, name) {
opt.name = name;
return opt;
});
}
- parser.opts = parser.opts.map(function(opt) {
+ parser.specs = parser.specs.map(function(opt) {
return Opt(opt);
});
/* parse the args */
if(printHelp && (argv.indexOf("--help") != -1
|| argv.indexOf("-h") != -1))
- print(parser.usageString());
+ print(parser.getUsage());
var options = {};
- parser.opts.forEach(function(opt) {
+ parser.specs.forEach(function(opt) {
options[opt.name] = opt.default;
}, parser);
@@ -151,7 +189,7 @@ function ArgParser() {
}, parser);
// exit if required arg isn't present
- parser.opts.forEach(function(opt) {
+ parser.specs.forEach(function(opt) {
if(opt.required && !options[opt.name])
print(opt.name + " argument is required");
}, parser);
@@ -161,30 +199,39 @@ function ArgParser() {
return options;
},
- usageString : function() {
+ getUsage : function() {
+ if(parser.usageString)
+ return parser.usageString;
+
var str = "Usage: " + parser.script;
- // underscore
- var positionals = parser.opts.filter(function(opt) {
+
+ var positionals = parser.specs.filter(function(opt) {
return opt.position != undefined;
}).sort(function(opt1, opt2) {
return opt1.position > opt2.position;
});
+
+ var options = parser.specs.filter(function(opt) {
+ return opt.position == undefined;
+ });
+
// assume there are no gaps in the specified pos. args
positionals.forEach(function(pos) {
str += " <" + (pos.name || "arg" + pos.position) + ">";
});
- str += " [options]\n\n";
+ if(options.length)
+ str += " [options]\n\n";
positionals.forEach(function(pos) {
str += "<" + pos.name + ">\t\t" + (pos.help || "") + "\n";
});
- str += "\noptions:\n"
- // underscore
- parser.opts.forEach(function(opt) {
- if(opt.position == undefined)
- str += opt.string + "\t\t" + (opt.help || "") + "\n";
+ if(options.length)
+ str += "\noptions:\n"
+
+ options.forEach(function(opt) {
+ str += opt.string + "\t\t" + (opt.help || "") + "\n";
});
- return str + "\n" + parser.help;
+ return str + "\n" + (parser.helpString || "");
}
}
@@ -232,8 +279,6 @@ Arg = function(str) {
var val = valRegex.exec(str);
val = val && str;
-
-
var value = val || (lg && lgRegex.exec(str)[2]);
try { // try to infer type by JSON parsing the string
value = JSON.parse(value)
View
6 package.json
@@ -1,7 +1,7 @@
{
"name": "nomnom",
- "description": "Limited option parser",
- "version": "0.2",
+ "description": "Option parser with support for usage and commands",
+ "version": "0.3.0",
"author": "Heather Arthur <fayearthur@gmail.com>",
"repository": {
"type": "git",
@@ -13,6 +13,6 @@
"main": "./lib/nomnom",
"keywords": ["arguments", "option parser", "command line"],
"dependencies": {
- "underscore": "*"
+ "underscore": ">= 1.1.5"
}
}
View
36 test/chain.js
@@ -0,0 +1,36 @@
+var nomnom = require('../lib/nomnom'),
+ assert = require('assert');
+
+var options = nomnom()
+ .opts({
+ config: {
+ string: '-c PATH, --config=PATH',
+ default: 'config.json',
+ help: 'JSON file with tests to run'
+ },
+ debug: {
+ string: '-d, --debug',
+ help: 'Print debugging info'
+ }
+ })
+ .parseArgs(["-d", "--config=test.json"]);
+
+assert.ok(options.debug);
+assert.equal(options.config, "test.json");
+
+var options = nomnom.parseArgs(["-xvf", "--file=test.js"]);
+assert.ok(options.x);
+assert.equal(options.file, "test.js");
+
+var parser = nomnom()
+ .usage("test");
+
+assert.equal(parser.getUsage(), "test");
+
+var parser = nomnom()
+ .scriptName("test")
+ .help("help");
+
+assert.equal(parser.getUsage(), "Usage: test\nhelp");
+
+
View
2 test/hash.js
@@ -49,7 +49,7 @@ var opts = {
};
-var options = nomnom.parseArgs(opts, {argv: ["-c", "other.json", "--debug=false", "-v", "neuralnetwork",
+var options = nomnom().parseArgs(opts, {argv: ["-c", "other.json", "--debug=false", "-v", "neuralnetwork",
"-d", "http://db", "--options={}"]});
assert.equal(options.target, "neuralnetwork");
View
4 test/help.js
@@ -18,7 +18,7 @@ var opts = [
var parser = nomnom();
parser.parseArgs(opts, {script: 'test.js', printHelp: false});
-assert.equal(strip(parser.usageString()), strip("Usage:test.js[options]options:-c,--config=PATHJSONconfigwithtestinfo-lLOG"));
+assert.equal(strip(parser.getUsage()), strip("Usage:test.js[options]options:-c,--config=PATHJSONconfigwithtestinfo-lLOG"));
var opts = [
{ name: 'aname0',
position: 0},
@@ -36,4 +36,4 @@ var opts = [
parser = nomnom();
parser.parseArgs(opts, {script: 'test.js', printHelp: false});
-assert.equal(strip(parser.usageString()), strip("Usage:test.js<aname0><aname1><aname2>[options]<aname0><aname1><aname2>options:-d"));
+assert.equal(strip(parser.getUsage()), strip("Usage:test.js<aname0><aname1><aname2>[options]<aname0><aname1><aname2>options:-d"));

0 comments on commit 98697eb

Please sign in to comment.
Something went wrong with that request. Please try again.