From e77f4f61aa01269e42428c73375bf083d1d8d6bc Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Sun, 14 Feb 2010 15:16:33 -0500 Subject: [PATCH] removing the vendored optparse in favor of a pure-coffeescript optparse library --- lib/coffee_script/command_line.js | 7 +- lib/coffee_script/optparse.js | 116 +++++++ lib/coffee_script/underscore.js | 2 +- src/command_line.coffee | 7 +- src/optparse.coffee | 78 +++++ src/underscore.coffee | 2 +- vendor/optparse-js/README.md | 161 --------- vendor/optparse-js/TODO | 1 - vendor/optparse-js/examples/browser-test.html | 75 ----- vendor/optparse-js/examples/nodejs-test.js | 88 ----- vendor/optparse-js/src/optparse.js | 309 ------------------ 11 files changed, 202 insertions(+), 644 deletions(-) create mode 100755 lib/coffee_script/optparse.js create mode 100644 src/optparse.coffee delete mode 100644 vendor/optparse-js/README.md delete mode 100644 vendor/optparse-js/TODO delete mode 100644 vendor/optparse-js/examples/browser-test.html delete mode 100644 vendor/optparse-js/examples/nodejs-test.js delete mode 100755 vendor/optparse-js/src/optparse.js diff --git a/lib/coffee_script/command_line.js b/lib/coffee_script/command_line.js index 70fabf0c..b093b55a 100644 --- a/lib/coffee_script/command_line.js +++ b/lib/coffee_script/command_line.js @@ -3,7 +3,7 @@ posix = require('posix'); path = require('path'); 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"; 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; @@ -27,7 +27,7 @@ }; // The "--help" usage message. usage = function usage() { - puts('\n' + option_parser.toString() + '\n'); + puts('\n' + option_parser.help() + '\n'); return process.exit(0); }; // The "--version" message. @@ -125,14 +125,13 @@ opts = (options = {}); oparser = (option_parser = new optparse.OptionParser(SWITCHES)); oparser.banner = BANNER; - oparser.add = oparser['on']; oparser.add('interactive', function() { return opts.interactive = true; }); oparser.add('run', function() { return opts.run = true; }); - oparser.add('output', function(n, dir) { + oparser.add('output', function(dir) { return opts.output = dir; }); oparser.add('watch', function() { diff --git a/lib/coffee_script/optparse.js b/lib/coffee_script/optparse.js new file mode 100755 index 00000000..d30ec5e2 --- /dev/null +++ b/lib/coffee_script/optparse.js @@ -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(''); + }; +})(); \ No newline at end of file diff --git a/lib/coffee_script/underscore.js b/lib/coffee_script/underscore.js index fd1e292e..5527c963 100644 --- a/lib/coffee_script/underscore.js +++ b/lib/coffee_script/underscore.js @@ -706,7 +706,7 @@ }; // JavaScript templating a-la ERB, pilfered from John Resig's // "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) { var c, fn; c = _.templateSettings; diff --git a/src/command_line.coffee b/src/command_line.coffee index b0624bf6..237841be 100644 --- a/src/command_line.coffee +++ b/src/command_line.coffee @@ -1,7 +1,7 @@ posix: require 'posix' path: require 'path' coffee: require 'coffee-script' -optparse: require('./../../vendor/optparse-js/src/optparse') +optparse: require('optparse') BANNER: ''' coffee compiles CoffeeScript source files into JavaScript. @@ -41,7 +41,7 @@ exports.run: -> # The "--help" usage message. usage: -> - puts '\n' + option_parser.toString() + '\n' + puts '\n' + option_parser.help() + '\n' process.exit 0 # The "--version" message. @@ -107,11 +107,10 @@ parse_options: -> opts: options: {} oparser: option_parser: new optparse.OptionParser SWITCHES oparser.banner: BANNER - oparser.add: oparser['on'] oparser.add 'interactive', -> opts.interactive: 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 'print', -> opts.print: true oparser.add 'lint', -> opts.lint: true diff --git a/src/optparse.coffee b/src/optparse.coffee new file mode 100644 index 00000000..14b847a6 --- /dev/null +++ b/src/optparse.coffee @@ -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 '' diff --git a/src/underscore.coffee b/src/underscore.coffee index 8026ea7d..ac008e5f 100644 --- a/src/underscore.coffee +++ b/src/underscore.coffee @@ -533,7 +533,7 @@ # JavaScript templating a-la ERB, pilfered from John Resig's # "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) -> c: _.templateSettings fn: new Function 'obj', diff --git a/vendor/optparse-js/README.md b/vendor/optparse-js/README.md deleted file mode 100644 index d08ccf16..00000000 --- a/vendor/optparse-js/README.md +++ /dev/null @@ -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 - diff --git a/vendor/optparse-js/TODO b/vendor/optparse-js/TODO deleted file mode 100644 index a1b60506..00000000 --- a/vendor/optparse-js/TODO +++ /dev/null @@ -1 +0,0 @@ -- Support for Argument lists (for switches) \ No newline at end of file diff --git a/vendor/optparse-js/examples/browser-test.html b/vendor/optparse-js/examples/browser-test.html deleted file mode 100644 index 2d8f6d38..00000000 --- a/vendor/optparse-js/examples/browser-test.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - optparse.js example - - - - - - - \ No newline at end of file diff --git a/vendor/optparse-js/examples/nodejs-test.js b/vendor/optparse-js/examples/nodejs-test.js deleted file mode 100644 index d0c5b658..00000000 --- a/vendor/optparse-js/examples/nodejs-test.js +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/vendor/optparse-js/src/optparse.js b/vendor/optparse-js/src/optparse.js deleted file mode 100755 index 7ed9d0c7..00000000 --- a/vendor/optparse-js/src/optparse.js +++ /dev/null @@ -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> 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); \ No newline at end of file