removing the vendored optparse in favor of a pure-coffeescript optparse library
This commit is contained in:
parent
9de729e825
commit
e77f4f61aa
|
@ -3,7 +3,7 @@
|
||||||
posix = require('posix');
|
posix = require('posix');
|
||||||
path = require('path');
|
path = require('path');
|
||||||
coffee = require('coffee-script');
|
coffee = require('coffee-script');
|
||||||
optparse = require('./../../vendor/optparse-js/src/optparse');
|
optparse = require('optparse');
|
||||||
BANNER = "coffee compiles CoffeeScript source files into JavaScript.\n\nUsage:\n coffee path/to/script.coffee";
|
BANNER = "coffee compiles CoffeeScript source files into JavaScript.\n\nUsage:\n coffee path/to/script.coffee";
|
||||||
SWITCHES = [['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-r', '--run', 'compile and run a CoffeeScript'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JSLint'], ['-e', '--eval', 'compile a string from the command line'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-tr', '--tree', 'print the parse tree that Jison produces'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
|
SWITCHES = [['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-r', '--run', 'compile and run a CoffeeScript'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JSLint'], ['-e', '--eval', 'compile a string from the command line'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-tr', '--tree', 'print the parse tree that Jison produces'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
|
||||||
WATCH_INTERVAL = 0.5;
|
WATCH_INTERVAL = 0.5;
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
};
|
};
|
||||||
// The "--help" usage message.
|
// The "--help" usage message.
|
||||||
usage = function usage() {
|
usage = function usage() {
|
||||||
puts('\n' + option_parser.toString() + '\n');
|
puts('\n' + option_parser.help() + '\n');
|
||||||
return process.exit(0);
|
return process.exit(0);
|
||||||
};
|
};
|
||||||
// The "--version" message.
|
// The "--version" message.
|
||||||
|
@ -125,14 +125,13 @@
|
||||||
opts = (options = {});
|
opts = (options = {});
|
||||||
oparser = (option_parser = new optparse.OptionParser(SWITCHES));
|
oparser = (option_parser = new optparse.OptionParser(SWITCHES));
|
||||||
oparser.banner = BANNER;
|
oparser.banner = BANNER;
|
||||||
oparser.add = oparser['on'];
|
|
||||||
oparser.add('interactive', function() {
|
oparser.add('interactive', function() {
|
||||||
return opts.interactive = true;
|
return opts.interactive = true;
|
||||||
});
|
});
|
||||||
oparser.add('run', function() {
|
oparser.add('run', function() {
|
||||||
return opts.run = true;
|
return opts.run = true;
|
||||||
});
|
});
|
||||||
oparser.add('output', function(n, dir) {
|
oparser.add('output', function(dir) {
|
||||||
return opts.output = dir;
|
return opts.output = dir;
|
||||||
});
|
});
|
||||||
oparser.add('watch', function() {
|
oparser.add('watch', function() {
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
(function(){
|
||||||
|
var LONG_FLAG, OPTIONAL, SHORT_FLAG, build_rule, build_rules, op, spaces;
|
||||||
|
// Create an OptionParser with a list of valid options.
|
||||||
|
op = (exports.OptionParser = function OptionParser(rules) {
|
||||||
|
this.banner = 'Usage: [Options]';
|
||||||
|
this.options_title = 'Available options:';
|
||||||
|
this.rules = build_rules(rules);
|
||||||
|
this.actions = {};
|
||||||
|
return this;
|
||||||
|
});
|
||||||
|
// Add a callback to fire when a particular option is encountered.
|
||||||
|
op.prototype.add = function add(value, callback) {
|
||||||
|
return this.actions[value] = callback;
|
||||||
|
};
|
||||||
|
// Parse the argument array, calling defined callbacks, returning the remaining non-option arguments.
|
||||||
|
op.prototype.parse = function parse(args) {
|
||||||
|
var __a, __b, arg, callback, is_option, results, rule, value;
|
||||||
|
results = [];
|
||||||
|
args = args.concat([]);
|
||||||
|
while (((arg = args.shift()))) {
|
||||||
|
is_option = false;
|
||||||
|
__a = this.rules;
|
||||||
|
for (__b = 0; __b < __a.length; __b++) {
|
||||||
|
rule = __a[__b];
|
||||||
|
if (rule.letter === arg || rule.flag === arg) {
|
||||||
|
callback = this.actions[rule.name];
|
||||||
|
value = rule.argument && args.shift();
|
||||||
|
if (callback) {
|
||||||
|
callback(value);
|
||||||
|
}
|
||||||
|
is_option = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(is_option)) {
|
||||||
|
results.push(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
// Return the help text for this OptionParser, for --help and such.
|
||||||
|
op.prototype.help = function help() {
|
||||||
|
var __a, __b, __c, __d, has_shorts, lines, longest, rule, text;
|
||||||
|
longest = 0;
|
||||||
|
has_shorts = false;
|
||||||
|
lines = [this.banner, '', this.options_title];
|
||||||
|
__a = this.rules;
|
||||||
|
for (__b = 0; __b < __a.length; __b++) {
|
||||||
|
rule = __a[__b];
|
||||||
|
if (rule.letter) {
|
||||||
|
has_shorts = true;
|
||||||
|
}
|
||||||
|
if (rule.flag.length > longest) {
|
||||||
|
longest = rule.flag.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__c = this.rules;
|
||||||
|
for (__d = 0; __d < __c.length; __d++) {
|
||||||
|
rule = __c[__d];
|
||||||
|
has_shorts ? (text = rule.letter ? spaces(2) + rule.letter + ', ' : spaces(6)) : null;
|
||||||
|
text += spaces(longest, rule.flag) + spaces(3);
|
||||||
|
text += rule.description;
|
||||||
|
lines.push(text);
|
||||||
|
}
|
||||||
|
return lines.join('\n');
|
||||||
|
};
|
||||||
|
// Private:
|
||||||
|
// Regex matchers for option flags.
|
||||||
|
LONG_FLAG = /^(--\w+)/;
|
||||||
|
SHORT_FLAG = /^(-\w+)/;
|
||||||
|
OPTIONAL = /\[(.+)\]/;
|
||||||
|
// Build rules from a list of valid switch tuples in the form:
|
||||||
|
// [letter-flag, long-flag, help], or [long-flag, help].
|
||||||
|
build_rules = function build_rules(rules) {
|
||||||
|
var __a, __b, __c, tuple;
|
||||||
|
__a = []; __b = rules;
|
||||||
|
for (__c = 0; __c < __b.length; __c++) {
|
||||||
|
tuple = __b[__c];
|
||||||
|
__a.push((function() {
|
||||||
|
if (tuple.length < 3) {
|
||||||
|
tuple.unshift(null);
|
||||||
|
}
|
||||||
|
return build_rule.apply(this, tuple);
|
||||||
|
}).call(this));
|
||||||
|
}
|
||||||
|
return __a;
|
||||||
|
};
|
||||||
|
// Build a rule from a short-letter-flag, long-form-flag, and help text.
|
||||||
|
build_rule = function build_rule(letter, flag, description) {
|
||||||
|
var match;
|
||||||
|
match = flag.match(OPTIONAL);
|
||||||
|
return {
|
||||||
|
name: flag.match(LONG_FLAG)[1].substr(2),
|
||||||
|
letter: letter,
|
||||||
|
flag: flag,
|
||||||
|
description: description,
|
||||||
|
argument: !!(match && match[1])
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// Space-pad a string with the specified number of characters.
|
||||||
|
spaces = function spaces(num, text) {
|
||||||
|
var builder;
|
||||||
|
builder = [];
|
||||||
|
if (text) {
|
||||||
|
if (text.length >= num) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
num -= text.length;
|
||||||
|
builder.push(text);
|
||||||
|
}
|
||||||
|
while (num -= 1) {
|
||||||
|
builder.push(' ');
|
||||||
|
}
|
||||||
|
return builder.join('');
|
||||||
|
};
|
||||||
|
})();
|
|
@ -706,7 +706,7 @@
|
||||||
};
|
};
|
||||||
// JavaScript templating a-la ERB, pilfered from John Resig's
|
// JavaScript templating a-la ERB, pilfered from John Resig's
|
||||||
// "Secrets of the JavaScript Ninja", page 83.
|
// "Secrets of the JavaScript Ninja", page 83.
|
||||||
// Single-quotea fix from Rick Strahl's version.
|
// Single-quote fix from Rick Strahl's version.
|
||||||
_.template = function template(str, data) {
|
_.template = function template(str, data) {
|
||||||
var c, fn;
|
var c, fn;
|
||||||
c = _.templateSettings;
|
c = _.templateSettings;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
posix: require 'posix'
|
posix: require 'posix'
|
||||||
path: require 'path'
|
path: require 'path'
|
||||||
coffee: require 'coffee-script'
|
coffee: require 'coffee-script'
|
||||||
optparse: require('./../../vendor/optparse-js/src/optparse')
|
optparse: require('optparse')
|
||||||
|
|
||||||
BANNER: '''
|
BANNER: '''
|
||||||
coffee compiles CoffeeScript source files into JavaScript.
|
coffee compiles CoffeeScript source files into JavaScript.
|
||||||
|
@ -41,7 +41,7 @@ exports.run: ->
|
||||||
|
|
||||||
# The "--help" usage message.
|
# The "--help" usage message.
|
||||||
usage: ->
|
usage: ->
|
||||||
puts '\n' + option_parser.toString() + '\n'
|
puts '\n' + option_parser.help() + '\n'
|
||||||
process.exit 0
|
process.exit 0
|
||||||
|
|
||||||
# The "--version" message.
|
# The "--version" message.
|
||||||
|
@ -107,11 +107,10 @@ parse_options: ->
|
||||||
opts: options: {}
|
opts: options: {}
|
||||||
oparser: option_parser: new optparse.OptionParser SWITCHES
|
oparser: option_parser: new optparse.OptionParser SWITCHES
|
||||||
oparser.banner: BANNER
|
oparser.banner: BANNER
|
||||||
oparser.add: oparser['on']
|
|
||||||
|
|
||||||
oparser.add 'interactive', -> opts.interactive: true
|
oparser.add 'interactive', -> opts.interactive: true
|
||||||
oparser.add 'run', -> opts.run: true
|
oparser.add 'run', -> opts.run: true
|
||||||
oparser.add 'output', (n, dir) -> opts.output: dir
|
oparser.add 'output', (dir) -> opts.output: dir
|
||||||
oparser.add 'watch', -> opts.watch: true
|
oparser.add 'watch', -> opts.watch: true
|
||||||
oparser.add 'print', -> opts.print: true
|
oparser.add 'print', -> opts.print: true
|
||||||
oparser.add 'lint', -> opts.lint: true
|
oparser.add 'lint', -> opts.lint: true
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Create an OptionParser with a list of valid options.
|
||||||
|
op: exports.OptionParser: (rules) ->
|
||||||
|
@banner: 'Usage: [Options]'
|
||||||
|
@options_title: 'Available options:'
|
||||||
|
@rules: build_rules(rules)
|
||||||
|
@actions: {}
|
||||||
|
this
|
||||||
|
|
||||||
|
# Add a callback to fire when a particular option is encountered.
|
||||||
|
op::add: (value, callback) ->
|
||||||
|
@actions[value]: callback
|
||||||
|
|
||||||
|
# Parse the argument array, calling defined callbacks, returning the remaining non-option arguments.
|
||||||
|
op::parse: (args) ->
|
||||||
|
results: []
|
||||||
|
args: args.concat []
|
||||||
|
while (arg: args.shift())
|
||||||
|
is_option: false
|
||||||
|
for rule in @rules
|
||||||
|
if rule.letter is arg or rule.flag is arg
|
||||||
|
callback: @actions[rule.name]
|
||||||
|
value: rule.argument and args.shift()
|
||||||
|
callback(value) if callback
|
||||||
|
is_option: true
|
||||||
|
break
|
||||||
|
results.push arg unless is_option
|
||||||
|
results
|
||||||
|
|
||||||
|
# Return the help text for this OptionParser, for --help and such.
|
||||||
|
op::help: ->
|
||||||
|
longest: 0
|
||||||
|
has_shorts: false
|
||||||
|
lines: [@banner, '', @options_title]
|
||||||
|
for rule in @rules
|
||||||
|
has_shorts: true if rule.letter
|
||||||
|
longest: rule.flag.length if rule.flag.length > longest
|
||||||
|
for rule in @rules
|
||||||
|
if has_shorts
|
||||||
|
text: if rule.letter then spaces(2) + rule.letter + ', ' else spaces(6)
|
||||||
|
text += spaces(longest, rule.flag) + spaces(3)
|
||||||
|
text += rule.description
|
||||||
|
lines.push text
|
||||||
|
lines.join('\n')
|
||||||
|
|
||||||
|
# Private:
|
||||||
|
|
||||||
|
# Regex matchers for option flags.
|
||||||
|
LONG_FLAG: /^(--\w+)/
|
||||||
|
SHORT_FLAG: /^(-\w+)/
|
||||||
|
OPTIONAL: /\[(.+)\]/
|
||||||
|
|
||||||
|
# Build rules from a list of valid switch tuples in the form:
|
||||||
|
# [letter-flag, long-flag, help], or [long-flag, help].
|
||||||
|
build_rules: (rules) ->
|
||||||
|
for tuple in rules
|
||||||
|
tuple.unshift(null) if tuple.length < 3
|
||||||
|
build_rule(tuple...)
|
||||||
|
|
||||||
|
# Build a rule from a short-letter-flag, long-form-flag, and help text.
|
||||||
|
build_rule: (letter, flag, description) ->
|
||||||
|
match: flag.match(OPTIONAL)
|
||||||
|
{
|
||||||
|
name: flag.match(LONG_FLAG)[1].substr(2)
|
||||||
|
letter: letter
|
||||||
|
flag: flag
|
||||||
|
description: description
|
||||||
|
argument: !!(match and match[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
# Space-pad a string with the specified number of characters.
|
||||||
|
spaces: (num, text) ->
|
||||||
|
builder: []
|
||||||
|
if text
|
||||||
|
return text if text.length >= num
|
||||||
|
num -= text.length
|
||||||
|
builder.push text
|
||||||
|
while num -= 1 then builder.push ' '
|
||||||
|
builder.join ''
|
|
@ -533,7 +533,7 @@
|
||||||
|
|
||||||
# JavaScript templating a-la ERB, pilfered from John Resig's
|
# JavaScript templating a-la ERB, pilfered from John Resig's
|
||||||
# "Secrets of the JavaScript Ninja", page 83.
|
# "Secrets of the JavaScript Ninja", page 83.
|
||||||
# Single-quotea fix from Rick Strahl's version.
|
# Single-quote fix from Rick Strahl's version.
|
||||||
_.template: (str, data) ->
|
_.template: (str, data) ->
|
||||||
c: _.templateSettings
|
c: _.templateSettings
|
||||||
fn: new Function 'obj',
|
fn: new Function 'obj',
|
||||||
|
|
|
@ -1,161 +0,0 @@
|
||||||
optparse-js
|
|
||||||
===========
|
|
||||||
|
|
||||||
Optparse-js is a command line option parser for Javascript. It's slightly based on Ruby's implementation optparse but with some differences (different languages has different needs) such as custom parsers.
|
|
||||||
|
|
||||||
All examples in this readme is using [Node.js](http://nodejs.org/). How ever, the library works with all kinds of Javascript implementations.
|
|
||||||
|
|
||||||
|
|
||||||
QUICK START
|
|
||||||
-----------
|
|
||||||
|
|
||||||
The library defines one class, the OptionParser class. The class constructor takes one single argument, a list with a set of rules. Here is a quick example:
|
|
||||||
|
|
||||||
// Import the sys library
|
|
||||||
var sys = require('sys');
|
|
||||||
|
|
||||||
// Import the optparse library.
|
|
||||||
var optparse = require('optparse');
|
|
||||||
|
|
||||||
// Define an option called ´´help´´. We give it a quick alias named ´´-h´´
|
|
||||||
// and a quick help text.
|
|
||||||
var switches = [
|
|
||||||
['-h', '--help', 'Shows help sections']
|
|
||||||
];
|
|
||||||
|
|
||||||
// Create a new OptionParser.
|
|
||||||
var parser = new optparse.OptionParser(switches);
|
|
||||||
|
|
||||||
// Hook the help option. The callback will be executed when the OptionParser
|
|
||||||
// hits the switch ´´-h´´ or ´´--help´´. Each representatio
|
|
||||||
parser.on('help', function() {
|
|
||||||
sys.puts('Help');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DEFINING RULES
|
|
||||||
--------------
|
|
||||||
The OptionParser constructor takes an Array with rules. Each rule is represented by an array (tuple) of two or three values. A typical rule definition may look like this:
|
|
||||||
|
|
||||||
['-h', '--help', 'Print this help']
|
|
||||||
|
|
||||||
|
|
||||||
The first value is optional, and represents an alias for the long-named switch (the second value, in this case ´´--help´´).
|
|
||||||
|
|
||||||
The second argument is the actual rule. The rule must start with a double dash followed by a switch name (in this case ´help´). The OptionParser also supports special option arguments. Define an option argument in the rule by adding a named argument after the leading double dash and switch name (E.G '--port-number PORT_NUMBER'). The argument is then parsed to the option handler. To define an optional option argument, just add a braces around argument in the rule (E.G '--port-number [PORT_NUMBER]). The OptionParser also supports filter. More on that in in the section called ´Option Filters´.
|
|
||||||
|
|
||||||
The third argument is an optional rule description.
|
|
||||||
|
|
||||||
|
|
||||||
OPTION FILTERS
|
|
||||||
--------------
|
|
||||||
Filters is a neat feature that let you filter option arguments. The OptionParser itself as already a set of built-in common filter's. These are:
|
|
||||||
|
|
||||||
- NUMBER, supports both decimal and hexadecimal numbers.
|
|
||||||
- DATE, filters arguments that matches YYYY-MM-DD.
|
|
||||||
- EMAIL, filters arguments that matches my@email.com.
|
|
||||||
|
|
||||||
It's simple to use any of the filter above in your rule-set. Here is a quick example how to filter number:
|
|
||||||
|
|
||||||
var rules = [
|
|
||||||
['--first-option NUMBER', 'Takes a number as argument'],
|
|
||||||
['--second-option [NUMBER]', 'Takes an optional number as argument']
|
|
||||||
]
|
|
||||||
|
|
||||||
You can add your own set of filter by calling the *parser_instance.filter* method:
|
|
||||||
|
|
||||||
parser.filter('single_char', function(value) {
|
|
||||||
if(value.length != 1) throw "Filter mismatch.";
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
OPTION PARSER
|
|
||||||
-------------
|
|
||||||
The OptionParser class has the following properties and methods:
|
|
||||||
|
|
||||||
### string banner
|
|
||||||
An optional usage banner. This text is included when calling ´´toString´´. Default value is: "Usage: [Options]".
|
|
||||||
|
|
||||||
|
|
||||||
### string options_title
|
|
||||||
An optional title for the options list. This text is included when calling ´´toString´´. Default value is: "Available options:".
|
|
||||||
|
|
||||||
|
|
||||||
### function on(switch_or_arg_index, callback)
|
|
||||||
Add's a callback for a switch or an argument (defined by index). Switch hooks MUST be typed witout the leading ´´--´´. This example show how to hook a switch:
|
|
||||||
|
|
||||||
parser.on('help', function(optional_argument) {
|
|
||||||
// Show help section
|
|
||||||
});
|
|
||||||
|
|
||||||
And this example show how to hook an argument (an option without the leading - or --):
|
|
||||||
|
|
||||||
parser.on(0, function(opt) {
|
|
||||||
puts('The first non-switch option is:' + opt);
|
|
||||||
});
|
|
||||||
|
|
||||||
It's also possible to define a default handler. The default handler is called when no rule's are meet. Here is an example how to add a ´default handler´:
|
|
||||||
|
|
||||||
parser.on(function(opt) {
|
|
||||||
puts('No handler was defined for option:' + opt);
|
|
||||||
});
|
|
||||||
|
|
||||||
Use the wildcard handler to build a custom ´´on´´ handler.
|
|
||||||
|
|
||||||
parser.on('*', function(opt, value) {
|
|
||||||
puts('option=' + opt + ', value=' + value);
|
|
||||||
});
|
|
||||||
|
|
||||||
### function filter(name, callback)
|
|
||||||
Adds a new filter extension to the OptionParser instance. The first argument is the name of the filter (trigger). The second argument is the actual filter See the ´OPTION FILTERS´ section for more info.
|
|
||||||
|
|
||||||
It's possible to override the default filters by passing the value "_DEFAULT" to the ´´name´´ argument. The name of the filter is automatically transformed into
|
|
||||||
upper case.
|
|
||||||
|
|
||||||
|
|
||||||
### function halt([callback])
|
|
||||||
Interrupt's further parsing. This function should be called from an ´on´ -callbacks, to cancel the parsing. This can be useful when the program should ignore all other arguments (when displaying help or version information).
|
|
||||||
|
|
||||||
The function also takes an optional callback argument. If the callback argument is specified, a ´halt´ callback will be added (instead of executing the ´halt´ command).
|
|
||||||
|
|
||||||
Here is an example how to add an ´on_halt´ callback:
|
|
||||||
|
|
||||||
parser.halt(function() {
|
|
||||||
puts('An option callback interupted the parser');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
### function parse(arguments)
|
|
||||||
Start's parsing of arguments. This should be the last thing you do.
|
|
||||||
|
|
||||||
|
|
||||||
### function options()
|
|
||||||
Returns an Array with all defined option rules
|
|
||||||
|
|
||||||
|
|
||||||
### function toString()
|
|
||||||
Returns a string representation of this OptionParser instance (a formatted help section).
|
|
||||||
|
|
||||||
|
|
||||||
MORE EXAMPLES
|
|
||||||
-------------
|
|
||||||
See examples/nodejs-test.js and examples/browser-test-html for more info how to
|
|
||||||
use the script.
|
|
||||||
|
|
||||||
|
|
||||||
SUGGESTIONS
|
|
||||||
-----------
|
|
||||||
All comments in how to improve this library is very welcome. Feel free post suggestions to the [Issue tracker](http://github.com/jfd/optparse-js/issues), or even better, fork the repository to implement your own features.
|
|
||||||
|
|
||||||
|
|
||||||
LICENSE
|
|
||||||
-------
|
|
||||||
Released under a MIT-style license.
|
|
||||||
|
|
||||||
|
|
||||||
COPYRIGHT
|
|
||||||
---------
|
|
||||||
Copyright (c) 2009 Johan Dahlberg
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
- Support for Argument lists (for switches)
|
|
|
@ -1,75 +0,0 @@
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
|
||||||
"http://www.w3.org/TR/html4/strict.dtd">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
|
||||||
<title>optparse.js example</title>
|
|
||||||
<script type="text/javascript" charset="utf-8" src="../src/optparse.js"></script>
|
|
||||||
<script>
|
|
||||||
// Arguments to be passed to the parser
|
|
||||||
var ARGS = ['-p', 'This is a message', '-i', 'test.html', '--debug'];
|
|
||||||
|
|
||||||
// Define some options
|
|
||||||
var SWITCHES = [
|
|
||||||
['-i', '--include-file FILE', "Includes a file"],
|
|
||||||
['-p', '--print [MESSAGE]', "Prints a message on screen"],
|
|
||||||
['-d', '--debug', "Enables debug mode"],
|
|
||||||
];
|
|
||||||
|
|
||||||
function puts(msg) {
|
|
||||||
var body = document.getElementById('body');
|
|
||||||
var pre = document.createElement('pre');
|
|
||||||
pre.innerHTML = msg;
|
|
||||||
body.appendChild(pre);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onLoad() {
|
|
||||||
puts("optparse.js");
|
|
||||||
|
|
||||||
// Create a new OptionParser with defined switches
|
|
||||||
var parser = new optparse.OptionParser(SWITCHES);
|
|
||||||
|
|
||||||
// Internal variable to store options.
|
|
||||||
var options = {
|
|
||||||
debug: false,
|
|
||||||
files: []
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle the first argument (switches excluded)
|
|
||||||
parser.on(0, function(value) {
|
|
||||||
puts("First non-switch argument is: " + value);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle the --include-file switch
|
|
||||||
parser.on('include-file', function(value) {
|
|
||||||
options.files.push(value);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle the --print switch
|
|
||||||
parser.on('print', function(value) {
|
|
||||||
puts('PRINT: ' + value);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle the --debug switch
|
|
||||||
parser.on('debug', function() {
|
|
||||||
options.debug = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Parse command line arguments
|
|
||||||
parser.parse(ARGS);
|
|
||||||
|
|
||||||
// Output all files that was included.
|
|
||||||
puts("No of files to include: " + options.files.length);
|
|
||||||
for(var i = 0; i < options.files.length; i++) {
|
|
||||||
puts("File [" + (i + 1) + "]:" + options.files[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is debug-mode enabled?
|
|
||||||
puts("Debug mode is set to: " + options.debug);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body id="body" onload="onLoad()">
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,88 +0,0 @@
|
||||||
// Import the optparse script
|
|
||||||
var optparse = require('../src/optparse');
|
|
||||||
|
|
||||||
process.mixin(require("utils"));
|
|
||||||
|
|
||||||
// Define some options
|
|
||||||
var SWITCHES = [
|
|
||||||
['-i', '--include-file FILE', "Includes a file"],
|
|
||||||
['-p', '--print [MESSAGE]', "Prints an optional message on screen"],
|
|
||||||
['-d', '--debug', "Enables debug mode"],
|
|
||||||
['-H', '--help', "Shows this help section"],
|
|
||||||
['--date DATE', "A date. A date is expected E.G. 2009-01-14"],
|
|
||||||
['--number NUMBER', "A Number. Supported formats are 123, 123.123, 0xA123"],
|
|
||||||
['--other NAME', "No handler defined for this option. Will be handled by the wildcard handler."],
|
|
||||||
];
|
|
||||||
|
|
||||||
// Create a new OptionParser with defined switches
|
|
||||||
var parser = new optparse.OptionParser(SWITCHES), print_summary = true,
|
|
||||||
first_arg;
|
|
||||||
parser.banner = 'Usage: nodejs-test.js [options]';
|
|
||||||
|
|
||||||
// Internal variable to store options.
|
|
||||||
var options = {
|
|
||||||
debug: false,
|
|
||||||
files: [],
|
|
||||||
number: undefined,
|
|
||||||
date: undefined
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle the first argument (switches excluded)
|
|
||||||
parser.on(0, function(value) {
|
|
||||||
first_arg = value;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle the --include-file switch
|
|
||||||
parser.on('include-file', function(value) {
|
|
||||||
options.files.push(value);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle the --print switch
|
|
||||||
parser.on('print', function(value) {
|
|
||||||
puts('PRINT: ' + (value || 'No message entered'));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle the --date switch
|
|
||||||
parser.on('date', function(value) {
|
|
||||||
options.date = value;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle the --number switch
|
|
||||||
parser.on('number', function(value) {
|
|
||||||
options.number = value;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle the --debug switch
|
|
||||||
parser.on('debug', function() {
|
|
||||||
options.debug = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle the --help switch
|
|
||||||
parser.on('help', function() {
|
|
||||||
puts(parser.toString());
|
|
||||||
print_summary = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set a default handler
|
|
||||||
parser.on('*', function(opt, value) {
|
|
||||||
puts('wild handler for ' + opt + ', value=' + value);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Parse command line arguments
|
|
||||||
parser.parse(process.ARGV);
|
|
||||||
|
|
||||||
if(print_summary) {
|
|
||||||
puts("First non-switch argument is: " + first_arg);
|
|
||||||
|
|
||||||
// Output all files that was included.
|
|
||||||
puts("No of files to include: " + options.files.length);
|
|
||||||
for(var i = 0; i < options.files.length; i++) {
|
|
||||||
puts("File [" + (i + 1) + "]:" + options.files[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is debug-mode enabled?
|
|
||||||
puts("Debug mode is set to: " + options.debug);
|
|
||||||
|
|
||||||
puts("Number value is: " + options.number);
|
|
||||||
puts("Date value is: " + options.date);
|
|
||||||
}
|
|
|
@ -1,309 +0,0 @@
|
||||||
// Optparse.js 1.0 - Option Parser for Javascript
|
|
||||||
//
|
|
||||||
// Copyright (c) 2009 Johan Dahlberg
|
|
||||||
//
|
|
||||||
// See README.md for license.
|
|
||||||
//
|
|
||||||
var optparse = {};
|
|
||||||
try{ optparse = exports } catch(e) {}; // Try to export the lib for node.js
|
|
||||||
(function(self) {
|
|
||||||
var VERSION = '1.0';
|
|
||||||
var LONG_SWITCH_RE = /^--\w/;
|
|
||||||
var SHORT_SWITCH_RE = /^-\w/;
|
|
||||||
var NUMBER_RE = /^(0x[A-Fa-f0-9]+)|([0-9]+\.[0-9]+)|(\d+)$/;
|
|
||||||
var DATE_RE = /^\d{4}-(0[0-9]|1[0,1,2])-([0,1,2][0-9]|3[0,1])$/;
|
|
||||||
var EMAIL_RE = /^([0-9a-zA-Z]+([_.-]?[0-9a-zA-Z]+)*@[0-9a-zA-Z]+[0-9,a-z,A-Z,.,-]*(.){1}[a-zA-Z]{2,4})+$/;
|
|
||||||
var EXT_RULE_RE = /(\-\-[\w_-]+)\s+([\w\[\]_-]+)|(\-\-[\w_-]+)/;
|
|
||||||
var ARG_OPTIONAL_RE = /\[(.+)\]/;
|
|
||||||
|
|
||||||
// The default switch argument filter to use, when argument name doesnt match
|
|
||||||
// any other names.
|
|
||||||
var DEFAULT_FILTER = '_DEFAULT';
|
|
||||||
var PREDEFINED_FILTERS = {};
|
|
||||||
|
|
||||||
// The default switch argument filter. Parses the argument as text.
|
|
||||||
function filter_text(value) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch argument filter that expects an integer, HEX or a decimal value. An
|
|
||||||
// exception is throwed if the criteria is not matched.
|
|
||||||
// Valid input formats are: 0xFFFFFFF, 12345 and 1234.1234
|
|
||||||
function filter_number(value) {
|
|
||||||
var m = NUMBER_RE(value);
|
|
||||||
if(m == null) throw OptError('Expected a number representative');
|
|
||||||
if(m[1]) {
|
|
||||||
// The number is in HEX format. Convert into a number, then return it
|
|
||||||
return parseInt(m[1], 16);
|
|
||||||
} else {
|
|
||||||
// The number is in regular- or decimal form. Just run in through
|
|
||||||
// the float caster.
|
|
||||||
return parseFloat(m[2] || m[3]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Switch argument filter that expects a Date expression. The date string MUST be
|
|
||||||
// formated as: "yyyy-mm-dd" An exception is throwed if the criteria is not
|
|
||||||
// matched. An DATE object is returned on success.
|
|
||||||
function filter_date(value) {
|
|
||||||
var m = DATE_RE(value);
|
|
||||||
if(m == null) throw OptError('Expected a date representation in the "yyyy-mm-dd" format.');
|
|
||||||
return new Date(parseInt(m[0]), parseInt(m[1]), parseInt(m[2]));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Switch argument filter that expects an email address. An exception is throwed
|
|
||||||
// if the criteria doesn`t match.
|
|
||||||
function filter_email(value) {
|
|
||||||
var m = EMAIL_RE(value);
|
|
||||||
if(m == null) throw OptError('Excpeted an email address.');
|
|
||||||
return m[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register all predefined filters. This dict is used by each OptionParser
|
|
||||||
// instance, when parsing arguments. Custom filters can be added to the parser
|
|
||||||
// instance by calling the "add_filter" -method.
|
|
||||||
PREDEFINED_FILTERS[DEFAULT_FILTER] = filter_text;
|
|
||||||
PREDEFINED_FILTERS['TEXT'] = filter_text;
|
|
||||||
PREDEFINED_FILTERS['NUMBER'] = filter_number;
|
|
||||||
PREDEFINED_FILTERS['DATE'] = filter_date;
|
|
||||||
PREDEFINED_FILTERS['EMAIL'] = filter_email;
|
|
||||||
|
|
||||||
// Buildes rules from a switches collection. The switches collection is defined
|
|
||||||
// when constructing a new OptionParser object.
|
|
||||||
function build_rules(filters, arr) {
|
|
||||||
var rules = [];
|
|
||||||
for(var i=0; i<arr.length; i++) {
|
|
||||||
var r = arr[i], rule
|
|
||||||
if(!contains_expr(r)) throw OptError('Rule MUST contain an option.');
|
|
||||||
switch(r.length) {
|
|
||||||
case 1:
|
|
||||||
rule = build_rule(filters, r[0]);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
var expr = LONG_SWITCH_RE(r[0]) ? 0 : 1;
|
|
||||||
var alias = expr == 0 ? -1 : 0;
|
|
||||||
var desc = alias == -1 ? 1 : -1;
|
|
||||||
rule = build_rule(filters, r[alias], r[expr], r[desc]);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
rule = build_rule(filters, r[0], r[1], r[2]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
case 0:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
rules.push(rule)
|
|
||||||
}
|
|
||||||
return rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Builds a rule with specified expression, short style switch and help. This
|
|
||||||
// function expects a dict with filters to work correctly.
|
|
||||||
//
|
|
||||||
// Return format:
|
|
||||||
// name The name of the switch.
|
|
||||||
// short The short style switch
|
|
||||||
// long The long style switch
|
|
||||||
// decl The declaration expression (the input expression)
|
|
||||||
// desc The optional help section for the switch
|
|
||||||
// optional_arg Indicates that switch argument is optional
|
|
||||||
// filter The filter to use when parsing the arg. An
|
|
||||||
// <<undefined>> value means that the switch does
|
|
||||||
// not take anargument.
|
|
||||||
function build_rule(filters, short, expr, desc) {
|
|
||||||
var optional, filter;
|
|
||||||
var m = expr.match(EXT_RULE_RE);
|
|
||||||
if(m == null) throw OptError('The switch is not well-formed.');
|
|
||||||
var long = m[1] || m[3];
|
|
||||||
if(m[2] != undefined) {
|
|
||||||
// A switch argument is expected. Check if the argument is optional,
|
|
||||||
// then find a filter that suites.
|
|
||||||
var optional_match = ARG_OPTIONAL_RE(m[2]);
|
|
||||||
var filter_name = optional_match === null ? m[2] : optional_match[1];
|
|
||||||
optional = optional_match !== null;
|
|
||||||
filter = filters[filter_name];
|
|
||||||
if(filter === undefined) filter = filters[DEFAULT_FILTER];
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
name: long.substr(2),
|
|
||||||
short: short,
|
|
||||||
long: long,
|
|
||||||
decl: expr,
|
|
||||||
desc: desc,
|
|
||||||
optional_arg: optional,
|
|
||||||
filter: filter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop's trough all elements of an array and check if there is valid
|
|
||||||
// options expression within. An valid option is a token that starts
|
|
||||||
// double dashes. E.G. --my_option
|
|
||||||
function contains_expr(arr) {
|
|
||||||
if(!arr || !arr.length) return false;
|
|
||||||
var l = arr.length;
|
|
||||||
while(l-- > 0) if(LONG_SWITCH_RE(arr[l])) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extends destination object with members of source object
|
|
||||||
function extend(dest, src) {
|
|
||||||
var result = dest;
|
|
||||||
for(var n in src) {
|
|
||||||
result[n] = src[n];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Appends spaces to match specified number of chars
|
|
||||||
function spaces(arg1, arg2) {
|
|
||||||
var l, builder = [];
|
|
||||||
if(arg1.constructor === Number) {
|
|
||||||
l = arg1;
|
|
||||||
} else {
|
|
||||||
if(arg1.length == arg2) return arg1;
|
|
||||||
l = arg2 - arg1.length;
|
|
||||||
builder.push(arg1);
|
|
||||||
}
|
|
||||||
while(l-- > 0) builder.push(' ');
|
|
||||||
return builder.join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new Parser object that can be used to parse command line arguments.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
function Parser(rules) {
|
|
||||||
return new OptionParser(rules);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates an error object with specified error message.
|
|
||||||
function OptError(msg) {
|
|
||||||
return new function() {
|
|
||||||
this.msg = msg;
|
|
||||||
this.toString = function() {
|
|
||||||
return this.msg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function OptionParser(rules) {
|
|
||||||
this.banner = 'Usage: [Options]';
|
|
||||||
this.options_title = 'Available options:'
|
|
||||||
this._rules = rules;
|
|
||||||
this._halt = false;
|
|
||||||
this.filters = extend({}, PREDEFINED_FILTERS);
|
|
||||||
this.on_args = {};
|
|
||||||
this.on_switches = {};
|
|
||||||
this.on_halt = function() {};
|
|
||||||
this.default_handler = function() {};
|
|
||||||
}
|
|
||||||
|
|
||||||
OptionParser.prototype = {
|
|
||||||
|
|
||||||
// Adds args and switchs handler.
|
|
||||||
on: function(value, fn) {
|
|
||||||
if(value.constructor === Function ) {
|
|
||||||
this.default_handler = value;
|
|
||||||
} else if(value.constructor === Number) {
|
|
||||||
this.on_args[value] = fn;
|
|
||||||
} else {
|
|
||||||
this.on_switches[value] = fn;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Adds a custom filter to the parser. It's possible to override the
|
|
||||||
// default filter by passing the value "_DEFAULT" to the ´´name´´
|
|
||||||
// argument. The name of the filter is automatically transformed into
|
|
||||||
// upper case.
|
|
||||||
filter: function(name, fn) {
|
|
||||||
this.filters[name.toUpperCase()] = fn;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Parses specified args. Returns remaining arguments.
|
|
||||||
parse: function(args) {
|
|
||||||
var result = [], callback;
|
|
||||||
var rules = build_rules(this.filters, this._rules);
|
|
||||||
var tokens = args.concat([]);
|
|
||||||
while((token = tokens.shift()) && this._halt == false) {
|
|
||||||
if(LONG_SWITCH_RE(token) || SHORT_SWITCH_RE(token)) {
|
|
||||||
var arg = undefined;
|
|
||||||
// The token is a long or a short switch. Get the corresponding
|
|
||||||
// rule, filter and handle it. Pass the switch to the default
|
|
||||||
// handler if no rule matched.
|
|
||||||
for(var i = 0; i < rules.length; i++) {
|
|
||||||
var rule = rules[i];
|
|
||||||
if(rule.long == token || rule.short == token) {
|
|
||||||
if(rule.filter !== undefined) {
|
|
||||||
arg = tokens.shift();
|
|
||||||
if(!LONG_SWITCH_RE(arg) && !SHORT_SWITCH_RE(arg)) {
|
|
||||||
try {
|
|
||||||
arg = rule.filter(arg);
|
|
||||||
} catch(e) {
|
|
||||||
throw OptError(token + ': ' + e.toString());
|
|
||||||
}
|
|
||||||
} else if(rule.optional_arg) {
|
|
||||||
tokens.unshift(arg);
|
|
||||||
} else {
|
|
||||||
throw OptError('Expected switch argument.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback = this.on_switches[rule.name];
|
|
||||||
if (!callback) callback = this.on_switches['*'];
|
|
||||||
if(callback) callback.apply(this, [rule.name, arg]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(i == rules.length) this.default_handler.apply(this, [token]);
|
|
||||||
} else {
|
|
||||||
// Did not match long or short switch. Parse the token as a
|
|
||||||
// normal argument.
|
|
||||||
callback = this.on_args[result.length];
|
|
||||||
result.push(token);
|
|
||||||
if(callback) callback.apply(this, [token]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this._halt ? this.on_halt.apply(this, []) : result;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Returns an Array with all defined option rules
|
|
||||||
options: function() {
|
|
||||||
return build_rules(this.filters, this._rules);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Add an on_halt callback if argument ´´fn´´ is specified. on_switch handlers can
|
|
||||||
// call instance.halt to abort the argument parsing. This can be useful when
|
|
||||||
// displaying help or version information.
|
|
||||||
halt: function(fn) {
|
|
||||||
this._halt = fn === undefined
|
|
||||||
if(fn) this.on_halt = fn;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Returns a string representation of this OptionParser instance.
|
|
||||||
toString: function() {
|
|
||||||
var builder = [this.banner, '', this.options_title],
|
|
||||||
shorts = false, longest = 0, rule;
|
|
||||||
var rules = build_rules(this.filters, this._rules);
|
|
||||||
for(var i = 0; i < rules.length; i++) {
|
|
||||||
rule = rules[i];
|
|
||||||
// Quick-analyze the options.
|
|
||||||
if(rule.short) shorts = true;
|
|
||||||
if(rule.decl.length > longest) longest = rule.decl.length;
|
|
||||||
}
|
|
||||||
for(var i = 0; i < rules.length; i++) {
|
|
||||||
var text;
|
|
||||||
rule = rules[i];
|
|
||||||
if(shorts) {
|
|
||||||
if(rule.short) text = spaces(2) + rule.short + ', ';
|
|
||||||
else text = spaces(6);
|
|
||||||
}
|
|
||||||
text += spaces(rule.decl, longest) + spaces(3);
|
|
||||||
text += rule.desc;
|
|
||||||
builder.push(text);
|
|
||||||
}
|
|
||||||
return builder.join('\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.VERSION = VERSION;
|
|
||||||
self.OptionParser = OptionParser;
|
|
||||||
|
|
||||||
})(optparse);
|
|
Loading…
Reference in New Issue