1 |
|
2 | (function() {
|
3 | var Getopt, __matches;
|
4 |
|
5 | Getopt = (function() {
|
6 | Getopt.HAS_ARGUMENT = true;
|
7 |
|
8 | Getopt.NO_ARGUMENT = false;
|
9 |
|
10 | Getopt.MULTI_SUPPORTED = true;
|
11 |
|
12 | Getopt.SINGLE_ONLY = false;
|
13 |
|
14 | Getopt.VERSION = '0.3.1';
|
15 |
|
16 | function Getopt(optionsPattern) {
|
17 | var comment, def, definition, fixed_long_name, has_argument, long_name, multi_supported, name, names, option, optional, short_name, _i, _len, _ref;
|
18 | this.optionsPattern = optionsPattern;
|
19 | this.short_options = {};
|
20 | this.long_options = {};
|
21 | this.long_names = [];
|
22 | this.events = {};
|
23 | this.argv = [];
|
24 | this.options = {};
|
25 | this.errorFunc = function(e) {
|
26 | console.info(e.message);
|
27 | return process.exit(1);
|
28 | };
|
29 | if (process.argv[1]) {
|
30 | this.help = "Usage: node " + (process.argv[1].match(/(?:.*[\/\\])?(.*)$/)[1]) + "\n\n[[OPTIONS]]\n";
|
31 | } else {
|
32 | this.help = "[[OPTIONS]]";
|
33 | }
|
34 | names = {};
|
35 | _ref = this.optionsPattern;
|
36 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
37 | option = _ref[_i];
|
38 | short_name = option[0], definition = option[1], comment = option[2], def = option[3];
|
39 | if (comment == null) {
|
40 | comment = '';
|
41 | }
|
42 | if (definition == null) {
|
43 | definition = '';
|
44 | }
|
45 | if (short_name == null) {
|
46 | short_name = '';
|
47 | }
|
48 | __matches = definition.match(/^([\w\-]*)/);
|
49 | long_name = __matches[1];
|
50 | has_argument = definition.indexOf('=') !== -1;
|
51 | multi_supported = definition.indexOf('+') !== -1;
|
52 | optional = /\[=.*?\]/.test(definition);
|
53 | long_name = long_name.trim();
|
54 | short_name = short_name.trim();
|
55 | if (optional && short_name) {
|
56 | throw new Error('optional argument can only work with long option');
|
57 | }
|
58 | long_name || (long_name = short_name);
|
59 | fixed_long_name = 'opt_' + long_name;
|
60 | name = long_name;
|
61 | if (long_name === '') {
|
62 | throw new Error("empty option found. the last option name is " + (this.long_names.slice(-1)));
|
63 | }
|
64 | if (names[fixed_long_name] == null) {
|
65 | this.long_names.push(long_name);
|
66 | this.long_options[long_name] = {
|
67 | name: name,
|
68 | short_name: short_name,
|
69 | long_name: long_name,
|
70 | has_argument: has_argument,
|
71 | multi_supported: multi_supported,
|
72 | comment: comment,
|
73 | optional: optional,
|
74 | definition: definition,
|
75 | def: def
|
76 | };
|
77 | names[fixed_long_name] = true;
|
78 | } else {
|
79 | throw new Error("option " + long_name + " is redefined.");
|
80 | }
|
81 | if (short_name !== '') {
|
82 | if (short_name.length !== 1) {
|
83 | throw new Error('short option must be single characters');
|
84 | }
|
85 | this.short_options[short_name] = this.long_options[long_name];
|
86 | }
|
87 | }
|
88 | this;
|
89 | }
|
90 |
|
91 | Getopt.prototype.getOptionByName = function(name) {
|
92 | var _ref;
|
93 | return (_ref = this.long_options[name]) != null ? _ref : this.short_options[name];
|
94 | };
|
95 |
|
96 | Getopt.prototype.getOptionName = function(name) {
|
97 | var _ref;
|
98 | return (_ref = this.getOptionByName(name)) != null ? _ref.name : void 0;
|
99 | };
|
100 |
|
101 | Getopt.prototype.on = function(name, cb) {
|
102 | var iname;
|
103 | if (name) {
|
104 | iname = this.getOptionName(name);
|
105 | if (!iname) {
|
106 | throw new Error("unknown option " + name);
|
107 | }
|
108 | } else {
|
109 | iname = name;
|
110 | }
|
111 | this.events[iname] = cb;
|
112 | return this;
|
113 | };
|
114 |
|
115 | Getopt.prototype.emit = function(name, value) {
|
116 | var event;
|
117 | event = this.events[this.getOptionName(name)];
|
118 | if (event) {
|
119 | return event.call(this, value);
|
120 | } else {
|
121 | throw new Error("Getopt event on '" + name + "' is not found");
|
122 | }
|
123 | };
|
124 |
|
125 | Getopt.prototype.save_option_ = function(options, option, argv) {
|
126 | var name, value, _ref;
|
127 | if (option.has_argument) {
|
128 | if (argv.length === 0) {
|
129 | throw new Error("option " + option.long_name + " need argument");
|
130 | }
|
131 | value = argv.shift();
|
132 | } else {
|
133 | value = true;
|
134 | }
|
135 | name = option.name;
|
136 | if (option.multi_supported) {
|
137 | if (options[name] == null) {
|
138 | options[name] = [];
|
139 | }
|
140 | options[name].push(value);
|
141 | } else {
|
142 | options[name] = value;
|
143 | }
|
144 | if ((_ref = this.events[name]) != null) {
|
145 | _ref.call(this, value);
|
146 | }
|
147 | return this;
|
148 | };
|
149 |
|
150 | Getopt.prototype.parse = function(argv) {
|
151 | var arg, e, i, long_name, name, option, rt_argv, rt_options, short_name, short_names, sname, value, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
|
152 | try {
|
153 | argv = argv.slice(0);
|
154 | rt_options = {};
|
155 | rt_argv = [];
|
156 | _ref = this.long_names;
|
157 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
158 | long_name = _ref[_i];
|
159 | option = this.long_options[long_name];
|
160 | if ((option.def != null) || (rt_options[option.long_name] != null)) {
|
161 | rt_options[option.long_name] = option.def;
|
162 | }
|
163 | }
|
164 | while ((arg = argv.shift()) != null) {
|
165 | if (__matches = arg.match(/^-(\w[\w\-]*)/)) {
|
166 | short_names = __matches[1];
|
167 | for (i = _j = 0, _len1 = short_names.length; _j < _len1; i = ++_j) {
|
168 | short_name = short_names[i];
|
169 | option = this.short_options[short_name];
|
170 | if (!option) {
|
171 | throw new Error("invalid option " + short_name);
|
172 | }
|
173 | if (option.has_argument) {
|
174 | if (i < arg.length - 2) {
|
175 | argv.unshift(arg.slice(i + 2));
|
176 | }
|
177 | this.save_option_(rt_options, option, argv);
|
178 | break;
|
179 | } else {
|
180 | this.save_option_(rt_options, option, argv);
|
181 | }
|
182 | }
|
183 | } else if (__matches = arg.match(/^--(\w[\w\-]*)((?:=[^]*)?)$/)) {
|
184 | long_name = __matches[1];
|
185 | value = __matches[2];
|
186 | option = this.long_options[long_name];
|
187 | if (!option) {
|
188 | throw new Error("invalid option " + long_name);
|
189 | }
|
190 | if (value !== '') {
|
191 | value = value.slice(1);
|
192 | argv.unshift(value);
|
193 | } else if (option.optional) {
|
194 | argv.unshift('');
|
195 | }
|
196 | this.save_option_(rt_options, option, argv);
|
197 | } else if (arg === '--') {
|
198 | rt_argv = rt_argv.concat(argv);
|
199 | for (_k = 0, _len2 = argv.length; _k < _len2; _k++) {
|
200 | arg = argv[_k];
|
201 | if ((_ref1 = this.events['']) != null) {
|
202 | _ref1.call(this, arg);
|
203 | }
|
204 | }
|
205 | break;
|
206 | } else {
|
207 | rt_argv.push(arg);
|
208 | if ((_ref2 = this.events['']) != null) {
|
209 | _ref2.call(this, arg);
|
210 | }
|
211 | }
|
212 | }
|
213 | _ref3 = Object.keys(rt_options);
|
214 | for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
|
215 | name = _ref3[_l];
|
216 | sname = this.long_options[name].short_name;
|
217 | if (sname !== '') {
|
218 | rt_options[sname] = rt_options[name];
|
219 | }
|
220 | }
|
221 | } catch (_error) {
|
222 | e = _error;
|
223 | this.errorFunc(e);
|
224 | }
|
225 | this.argv = rt_argv;
|
226 | this.options = rt_options;
|
227 | return this;
|
228 | };
|
229 |
|
230 | Getopt.prototype.parse_system = function() {
|
231 | return this.parseSystem();
|
232 | };
|
233 |
|
234 | Getopt.prototype.parseSystem = function() {
|
235 | return this.parse(process.argv.slice(2));
|
236 | };
|
237 |
|
238 | Getopt.prototype.setHelp = function(help) {
|
239 | this.help = help;
|
240 | return this;
|
241 | };
|
242 |
|
243 | Getopt.prototype.sort = function() {
|
244 | return this.long_names.sort(function(a, b) {
|
245 | return a > b && 1 || a < b && -1 || 0;
|
246 | });
|
247 | };
|
248 |
|
249 | Getopt.prototype.getHelp = function() {
|
250 | var comment, def, definition, i, line, lines, long_name, n, option, options, short_name, table, td, tr, ws, _i, _j, _k, _len, _len1, _len2, _ref;
|
251 | ws = [];
|
252 | options = [];
|
253 | table = [];
|
254 | _ref = this.long_names;
|
255 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
256 | long_name = _ref[_i];
|
257 | tr = [];
|
258 | option = this.long_options[long_name];
|
259 | short_name = option.short_name, long_name = option.long_name, comment = option.comment, definition = option.definition, def = option.def;
|
260 | tr.push(short_name ? short_name === long_name ? " -" + short_name : " -" + short_name + ", --" + definition : " --" + definition);
|
261 | tr.push(" " + comment);
|
262 | if (def) {
|
263 | tr.push(" (default: " + def + ")");
|
264 | }
|
265 | table.push(tr);
|
266 | }
|
267 | for (_j = 0, _len1 = table.length; _j < _len1; _j++) {
|
268 | tr = table[_j];
|
269 | for (i = _k = 0, _len2 = tr.length; _k < _len2; i = ++_k) {
|
270 | td = tr[i];
|
271 | if (ws[i] == null) {
|
272 | ws[i] = 0;
|
273 | }
|
274 | ws[i] = Math.max(ws[i], td.length);
|
275 | }
|
276 | }
|
277 | lines = (function() {
|
278 | var _l, _len3, _len4, _m, _results;
|
279 | _results = [];
|
280 | for (_l = 0, _len3 = table.length; _l < _len3; _l++) {
|
281 | tr = table[_l];
|
282 | line = '';
|
283 | for (i = _m = 0, _len4 = tr.length; _m < _len4; i = ++_m) {
|
284 | td = tr[i];
|
285 | if (i) {
|
286 | n = ws[i - 1] - tr[i - 1].length;
|
287 | while (n--) {
|
288 | line += ' ';
|
289 | }
|
290 | }
|
291 | line += td;
|
292 | }
|
293 | _results.push(line.trimRight());
|
294 | }
|
295 | return _results;
|
296 | })();
|
297 | return this.help.replace('[[OPTIONS]]', lines.join("\n"));
|
298 | };
|
299 |
|
300 | Getopt.prototype.showHelp = function() {
|
301 | console.info(this.getHelp());
|
302 | return this;
|
303 | };
|
304 |
|
305 | Getopt.prototype.bindHelp = function(help) {
|
306 | if (help) {
|
307 | this.setHelp(help);
|
308 | }
|
309 | this.on('help', function() {
|
310 | this.showHelp();
|
311 | return process.exit(0);
|
312 | });
|
313 | return this;
|
314 | };
|
315 |
|
316 | Getopt.prototype.getVersion = function() {
|
317 | return Getopt.VERSION;
|
318 | };
|
319 |
|
320 | Getopt.prototype.error = function(errorFunc) {
|
321 | this.errorFunc = errorFunc;
|
322 | return this;
|
323 | };
|
324 |
|
325 | Getopt.getVersion = function() {
|
326 | return this.VERSION;
|
327 | };
|
328 |
|
329 | Getopt.create = function(options) {
|
330 | return new Getopt(options);
|
331 | };
|
332 |
|
333 | return Getopt;
|
334 |
|
335 | })();
|
336 |
|
337 | module.exports = Getopt;
|
338 |
|
339 | }).call(this);
|