socketioMEANseed/www/node_modules/optimist/index.js
www/node_modules/optimist/index.jsRaw
1var path = require('path');
2var minimist = require('minimist');
3var wordwrap = require('wordwrap');
4
5/* Hack an instance of Argv with process.argv into Argv
6 so people can do
7 require('optimist')(['--beeble=1','-z','zizzle']).argv
8 to parse a list of args and
9 require('optimist').argv
10 to get a parsed version of process.argv.
11*/
12
13var inst = Argv(process.argv.slice(2));
14Object.keys(inst).forEach(function (key) {
15 Argv[key] = typeof inst[key] == 'function'
16 ? inst[key].bind(inst)
17 : inst[key];
18});
19
20var exports = module.exports = Argv;
21function Argv (processArgs, cwd) {
22 var self = {};
23 if (!cwd) cwd = process.cwd();
24
25 self.$0 = process.argv
26 .slice(0,2)
27 .map(function (x) {
28 var b = rebase(cwd, x);
29 return x.match(/^\//) && b.length < x.length
30 ? b : x
31 })
32 .join(' ')
33 ;
34
35 if (process.env._ != undefined && process.argv[1] == process.env._) {
36 self.$0 = process.env._.replace(
37 path.dirname(process.execPath) + '/', ''
38 );
39 }
40
41 var options = {
42 boolean: [],
43 string: [],
44 alias: {},
45 default: []
46 };
47
48 self.boolean = function (bools) {
49 options.boolean.push.apply(options.boolean, [].concat(bools));
50 return self;
51 };
52
53 self.string = function (strings) {
54 options.string.push.apply(options.string, [].concat(strings));
55 return self;
56 };
57
58 self.default = function (key, value) {
59 if (typeof key === 'object') {
60 Object.keys(key).forEach(function (k) {
61 self.default(k, key[k]);
62 });
63 }
64 else {
65 options.default[key] = value;
66 }
67 return self;
68 };
69
70 self.alias = function (x, y) {
71 if (typeof x === 'object') {
72 Object.keys(x).forEach(function (key) {
73 self.alias(key, x[key]);
74 });
75 }
76 else {
77 options.alias[x] = (options.alias[x] || []).concat(y);
78 }
79 return self;
80 };
81
82 var demanded = {};
83 self.demand = function (keys) {
84 if (typeof keys == 'number') {
85 if (!demanded._) demanded._ = 0;
86 demanded._ += keys;
87 }
88 else if (Array.isArray(keys)) {
89 keys.forEach(function (key) {
90 self.demand(key);
91 });
92 }
93 else {
94 demanded[keys] = true;
95 }
96
97 return self;
98 };
99
100 var usage;
101 self.usage = function (msg, opts) {
102 if (!opts && typeof msg === 'object') {
103 opts = msg;
104 msg = null;
105 }
106
107 usage = msg;
108
109 if (opts) self.options(opts);
110
111 return self;
112 };
113
114 function fail (msg) {
115 self.showHelp();
116 if (msg) console.error(msg);
117 process.exit(1);
118 }
119
120 var checks = [];
121 self.check = function (f) {
122 checks.push(f);
123 return self;
124 };
125
126 var descriptions = {};
127 self.describe = function (key, desc) {
128 if (typeof key === 'object') {
129 Object.keys(key).forEach(function (k) {
130 self.describe(k, key[k]);
131 });
132 }
133 else {
134 descriptions[key] = desc;
135 }
136 return self;
137 };
138
139 self.parse = function (args) {
140 return parseArgs(args);
141 };
142
143 self.option = self.options = function (key, opt) {
144 if (typeof key === 'object') {
145 Object.keys(key).forEach(function (k) {
146 self.options(k, key[k]);
147 });
148 }
149 else {
150 if (opt.alias) self.alias(key, opt.alias);
151 if (opt.demand) self.demand(key);
152 if (typeof opt.default !== 'undefined') {
153 self.default(key, opt.default);
154 }
155
156 if (opt.boolean || opt.type === 'boolean') {
157 self.boolean(key);
158 }
159 if (opt.string || opt.type === 'string') {
160 self.string(key);
161 }
162
163 var desc = opt.describe || opt.description || opt.desc;
164 if (desc) {
165 self.describe(key, desc);
166 }
167 }
168
169 return self;
170 };
171
172 var wrap = null;
173 self.wrap = function (cols) {
174 wrap = cols;
175 return self;
176 };
177
178 self.showHelp = function (fn) {
179 if (!fn) fn = console.error;
180 fn(self.help());
181 };
182
183 self.help = function () {
184 var keys = Object.keys(
185 Object.keys(descriptions)
186 .concat(Object.keys(demanded))
187 .concat(Object.keys(options.default))
188 .reduce(function (acc, key) {
189 if (key !== '_') acc[key] = true;
190 return acc;
191 }, {})
192 );
193
194 var help = keys.length ? [ 'Options:' ] : [];
195
196 if (usage) {
197 help.unshift(usage.replace(/\$0/g, self.$0), '');
198 }
199
200 var switches = keys.reduce(function (acc, key) {
201 acc[key] = [ key ].concat(options.alias[key] || [])
202 .map(function (sw) {
203 return (sw.length > 1 ? '--' : '-') + sw
204 })
205 .join(', ')
206 ;
207 return acc;
208 }, {});
209
210 var switchlen = longest(Object.keys(switches).map(function (s) {
211 return switches[s] || '';
212 }));
213
214 var desclen = longest(Object.keys(descriptions).map(function (d) {
215 return descriptions[d] || '';
216 }));
217
218 keys.forEach(function (key) {
219 var kswitch = switches[key];
220 var desc = descriptions[key] || '';
221
222 if (wrap) {
223 desc = wordwrap(switchlen + 4, wrap)(desc)
224 .slice(switchlen + 4)
225 ;
226 }
227
228 var spadding = new Array(
229 Math.max(switchlen - kswitch.length + 3, 0)
230 ).join(' ');
231
232 var dpadding = new Array(
233 Math.max(desclen - desc.length + 1, 0)
234 ).join(' ');
235
236 var type = null;
237
238 if (options.boolean[key]) type = '[boolean]';
239 if (options.string[key]) type = '[string]';
240
241 if (!wrap && dpadding.length > 0) {
242 desc += dpadding;
243 }
244
245 var prelude = ' ' + kswitch + spadding;
246 var extra = [
247 type,
248 demanded[key]
249 ? '[required]'
250 : null
251 ,
252 options.default[key] !== undefined
253 ? '[default: ' + JSON.stringify(options.default[key]) + ']'
254 : null
255 ,
256 ].filter(Boolean).join(' ');
257
258 var body = [ desc, extra ].filter(Boolean).join(' ');
259
260 if (wrap) {
261 var dlines = desc.split('\n');
262 var dlen = dlines.slice(-1)[0].length
263 + (dlines.length === 1 ? prelude.length : 0)
264
265 body = desc + (dlen + extra.length > wrap - 2
266 ? '\n'
267 + new Array(wrap - extra.length + 1).join(' ')
268 + extra
269 : new Array(wrap - extra.length - dlen + 1).join(' ')
270 + extra
271 );
272 }
273
274 help.push(prelude + body);
275 });
276
277 help.push('');
278 return help.join('\n');
279 };
280
281 Object.defineProperty(self, 'argv', {
282 get : function () { return parseArgs(processArgs) },
283 enumerable : true,
284 });
285
286 function parseArgs (args) {
287 var argv = minimist(args, options);
288 argv.$0 = self.$0;
289
290 if (demanded._ && argv._.length < demanded._) {
291 fail('Not enough non-option arguments: got '
292 + argv._.length + ', need at least ' + demanded._
293 );
294 }
295
296 var missing = [];
297 Object.keys(demanded).forEach(function (key) {
298 if (!argv[key]) missing.push(key);
299 });
300
301 if (missing.length) {
302 fail('Missing required arguments: ' + missing.join(', '));
303 }
304
305 checks.forEach(function (f) {
306 try {
307 if (f(argv) === false) {
308 fail('Argument check failed: ' + f.toString());
309 }
310 }
311 catch (err) {
312 fail(err)
313 }
314 });
315
316 return argv;
317 }
318
319 function longest (xs) {
320 return Math.max.apply(
321 null,
322 xs.map(function (x) { return x.length })
323 );
324 }
325
326 return self;
327};
328
329// rebase an absolute path to a relative one with respect to a base directory
330// exported for tests
331exports.rebase = rebase;
332function rebase (base, dir) {
333 var ds = path.normalize(dir).split('/').slice(1);
334 var bs = path.normalize(base).split('/').slice(1);
335
336 for (var i = 0; ds[i] && ds[i] == bs[i]; i++);
337 ds.splice(0, i); bs.splice(0, i);
338
339 var p = path.normalize(
340 bs.map(function () { return '..' }).concat(ds).join('/')
341 ).replace(/\/$/,'').replace(/^$/, '.');
342 return p.match(/^[.\/]/) ? p : './' + p;
343};