arnaucube
arnaucube/socketioMEANseedPublic Self-hosted repository
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};