2010-02-14 15:16:33 -05:00
|
|
|
(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) {
|
2010-02-16 18:00:40 -05:00
|
|
|
var _a, _b, arg, callback, is_option, results, rule, value;
|
2010-02-14 15:16:33 -05:00
|
|
|
results = [];
|
|
|
|
args = args.concat([]);
|
|
|
|
while (((arg = args.shift()))) {
|
|
|
|
is_option = false;
|
2010-02-16 18:00:40 -05:00
|
|
|
_a = this.rules;
|
|
|
|
for (_b = 0; _b < _a.length; _b++) {
|
|
|
|
rule = _a[_b];
|
2010-02-14 15:16:33 -05:00
|
|
|
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() {
|
2010-02-16 18:00:40 -05:00
|
|
|
var _a, _b, _c, _d, has_shorts, lines, longest, rule, text;
|
2010-02-14 15:16:33 -05:00
|
|
|
longest = 0;
|
|
|
|
has_shorts = false;
|
|
|
|
lines = [this.banner, '', this.options_title];
|
2010-02-16 18:00:40 -05:00
|
|
|
_a = this.rules;
|
|
|
|
for (_b = 0; _b < _a.length; _b++) {
|
|
|
|
rule = _a[_b];
|
2010-02-14 15:16:33 -05:00
|
|
|
if (rule.letter) {
|
|
|
|
has_shorts = true;
|
|
|
|
}
|
|
|
|
if (rule.flag.length > longest) {
|
|
|
|
longest = rule.flag.length;
|
|
|
|
}
|
|
|
|
}
|
2010-02-16 18:00:40 -05:00
|
|
|
_c = this.rules;
|
|
|
|
for (_d = 0; _d < _c.length; _d++) {
|
|
|
|
rule = _c[_d];
|
2010-02-14 15:16:33 -05:00
|
|
|
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) {
|
2010-02-16 18:00:40 -05:00
|
|
|
var _a, _b, _c, tuple;
|
|
|
|
_a = []; _b = rules;
|
|
|
|
for (_c = 0; _c < _b.length; _c++) {
|
|
|
|
tuple = _b[_c];
|
|
|
|
_a.push((function() {
|
2010-02-14 15:16:33 -05:00
|
|
|
if (tuple.length < 3) {
|
|
|
|
tuple.unshift(null);
|
|
|
|
}
|
|
|
|
return build_rule.apply(this, tuple);
|
|
|
|
}).call(this));
|
|
|
|
}
|
2010-02-16 18:00:40 -05:00
|
|
|
return _a;
|
2010-02-14 15:16:33 -05:00
|
|
|
};
|
|
|
|
// 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);
|
2010-02-14 20:50:45 -05:00
|
|
|
flag = flag.match(LONG_FLAG)[1];
|
2010-02-14 15:16:33 -05:00
|
|
|
return {
|
2010-02-14 20:50:45 -05:00
|
|
|
name: flag.substr(2),
|
2010-02-14 15:16:33 -05:00
|
|
|
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('');
|
|
|
|
};
|
|
|
|
})();
|