1 |
|
2 | (function() {
|
3 | var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments;
|
4 |
|
5 | exports.OptionParser = OptionParser = (function() {
|
6 |
|
7 | function OptionParser(rules, banner) {
|
8 | this.banner = banner;
|
9 | this.rules = buildRules(rules);
|
10 | }
|
11 |
|
12 | OptionParser.prototype.parse = function(args) {
|
13 | var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, seenNonOptionArg, skippingArgument, value, _i, _j, _len, _len1, _ref;
|
14 | options = {
|
15 | "arguments": []
|
16 | };
|
17 | skippingArgument = false;
|
18 | originalArgs = args;
|
19 | args = normalizeArguments(args);
|
20 | for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) {
|
21 | arg = args[i];
|
22 | if (skippingArgument) {
|
23 | skippingArgument = false;
|
24 | continue;
|
25 | }
|
26 | if (arg === '--') {
|
27 | pos = originalArgs.indexOf('--');
|
28 | options["arguments"] = options["arguments"].concat(originalArgs.slice(pos + 1));
|
29 | break;
|
30 | }
|
31 | isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG));
|
32 | seenNonOptionArg = options["arguments"].length > 0;
|
33 | if (!seenNonOptionArg) {
|
34 | matchedRule = false;
|
35 | _ref = this.rules;
|
36 | for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
37 | rule = _ref[_j];
|
38 | if (rule.shortFlag === arg || rule.longFlag === arg) {
|
39 | value = true;
|
40 | if (rule.hasArgument) {
|
41 | skippingArgument = true;
|
42 | value = args[i + 1];
|
43 | }
|
44 | options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value;
|
45 | matchedRule = true;
|
46 | break;
|
47 | }
|
48 | }
|
49 | if (isOption && !matchedRule) {
|
50 | throw new Error("unrecognized option: " + arg);
|
51 | }
|
52 | }
|
53 | if (seenNonOptionArg || !isOption) {
|
54 | options["arguments"].push(arg);
|
55 | }
|
56 | }
|
57 | return options;
|
58 | };
|
59 |
|
60 | OptionParser.prototype.help = function() {
|
61 | var letPart, lines, rule, spaces, _i, _len, _ref;
|
62 | lines = [];
|
63 | if (this.banner) {
|
64 | lines.unshift("" + this.banner + "\n");
|
65 | }
|
66 | _ref = this.rules;
|
67 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
68 | rule = _ref[_i];
|
69 | spaces = 15 - rule.longFlag.length;
|
70 | spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
|
71 | letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' ';
|
72 | lines.push(' ' + letPart + rule.longFlag + spaces + rule.description);
|
73 | }
|
74 | return "\n" + (lines.join('\n')) + "\n";
|
75 | };
|
76 |
|
77 | return OptionParser;
|
78 |
|
79 | })();
|
80 |
|
81 | LONG_FLAG = /^(--\w[\w\-]*)/;
|
82 |
|
83 | SHORT_FLAG = /^(-\w)$/;
|
84 |
|
85 | MULTI_FLAG = /^-(\w{2,})/;
|
86 |
|
87 | OPTIONAL = /\[(\w+(\*?))\]/;
|
88 |
|
89 | buildRules = function(rules) {
|
90 | var tuple, _i, _len, _results;
|
91 | _results = [];
|
92 | for (_i = 0, _len = rules.length; _i < _len; _i++) {
|
93 | tuple = rules[_i];
|
94 | if (tuple.length < 3) {
|
95 | tuple.unshift(null);
|
96 | }
|
97 | _results.push(buildRule.apply(null, tuple));
|
98 | }
|
99 | return _results;
|
100 | };
|
101 |
|
102 | buildRule = function(shortFlag, longFlag, description, options) {
|
103 | var match;
|
104 | if (options == null) {
|
105 | options = {};
|
106 | }
|
107 | match = longFlag.match(OPTIONAL);
|
108 | longFlag = longFlag.match(LONG_FLAG)[1];
|
109 | return {
|
110 | name: longFlag.substr(2),
|
111 | shortFlag: shortFlag,
|
112 | longFlag: longFlag,
|
113 | description: description,
|
114 | hasArgument: !!(match && match[1]),
|
115 | isList: !!(match && match[2])
|
116 | };
|
117 | };
|
118 |
|
119 | normalizeArguments = function(args) {
|
120 | var arg, l, match, result, _i, _j, _len, _len1, _ref;
|
121 | args = args.slice(0);
|
122 | result = [];
|
123 | for (_i = 0, _len = args.length; _i < _len; _i++) {
|
124 | arg = args[_i];
|
125 | if (match = arg.match(MULTI_FLAG)) {
|
126 | _ref = match[1].split('');
|
127 | for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
128 | l = _ref[_j];
|
129 | result.push('-' + l);
|
130 | }
|
131 | } else {
|
132 | result.push(arg);
|
133 | }
|
134 | }
|
135 | return result;
|
136 | };
|
137 |
|
138 | }).call(this);
|