Current File : //lib/node_modules/bower/lib/node_modules/bower-config/lib/vendor/optimist.js |
var path = require('path');
var minimist = require('minimist');
var wordwrap = require('wordwrap');
/* Hack an instance of Argv with process.argv into Argv
so people can do
require('optimist')(['--beeble=1','-z','zizzle']).argv
to parse a list of args and
require('optimist').argv
to get a parsed version of process.argv.
*/
var inst = Argv(process.argv.slice(2));
Object.keys(inst).forEach(function(key) {
Argv[key] =
typeof inst[key] == 'function' ? inst[key].bind(inst) : inst[key];
});
var exports = (module.exports = Argv);
function Argv(processArgs, cwd) {
var self = {};
if (!cwd) cwd = process.cwd();
self.$0 = process.argv
.slice(0, 2)
.map(function(x) {
var b = rebase(cwd, x);
return x.match(/^\//) && b.length < x.length ? b : x;
})
.join(' ');
if (process.env._ != undefined && process.argv[1] == process.env._) {
self.$0 = process.env._.replace(
path.dirname(process.execPath) + '/',
''
);
}
var options = {
boolean: [],
string: [],
alias: {},
default: []
};
self.boolean = function(bools) {
options.boolean.push.apply(options.boolean, [].concat(bools));
return self;
};
self.string = function(strings) {
options.string.push.apply(options.string, [].concat(strings));
return self;
};
self.default = function(key, value) {
if (typeof key === 'object') {
Object.keys(key).forEach(function(k) {
self.default(k, key[k]);
});
} else {
options.default[key] = value;
}
return self;
};
self.alias = function(x, y) {
if (typeof x === 'object') {
Object.keys(x).forEach(function(key) {
self.alias(key, x[key]);
});
} else {
options.alias[x] = (options.alias[x] || []).concat(y);
}
return self;
};
var demanded = {};
self.demand = function(keys) {
if (typeof keys == 'number') {
if (!demanded._) demanded._ = 0;
demanded._ += keys;
} else if (Array.isArray(keys)) {
keys.forEach(function(key) {
self.demand(key);
});
} else {
demanded[keys] = true;
}
return self;
};
var usage;
self.usage = function(msg, opts) {
if (!opts && typeof msg === 'object') {
opts = msg;
msg = null;
}
usage = msg;
if (opts) self.options(opts);
return self;
};
function fail(msg) {
self.showHelp();
if (msg) console.error(msg);
process.exit(1);
}
var checks = [];
self.check = function(f) {
checks.push(f);
return self;
};
var descriptions = {};
self.describe = function(key, desc) {
if (typeof key === 'object') {
Object.keys(key).forEach(function(k) {
self.describe(k, key[k]);
});
} else {
descriptions[key] = desc;
}
return self;
};
self.parse = function(args) {
return parseArgs(args);
};
self.option = self.options = function(key, opt) {
if (typeof key === 'object') {
Object.keys(key).forEach(function(k) {
self.options(k, key[k]);
});
} else {
if (opt.alias) self.alias(key, opt.alias);
if (opt.demand) self.demand(key);
if (typeof opt.default !== 'undefined') {
self.default(key, opt.default);
}
if (opt.boolean || opt.type === 'boolean') {
self.boolean(key);
}
if (opt.string || opt.type === 'string') {
self.string(key);
}
var desc = opt.describe || opt.description || opt.desc;
if (desc) {
self.describe(key, desc);
}
}
return self;
};
var wrap = null;
self.wrap = function(cols) {
wrap = cols;
return self;
};
self.showHelp = function(fn) {
if (!fn) fn = console.error;
fn(self.help());
};
self.help = function() {
var keys = Object.keys(
Object.keys(descriptions)
.concat(Object.keys(demanded))
.concat(Object.keys(options.default))
.reduce(function(acc, key) {
if (key !== '_') acc[key] = true;
return acc;
}, {})
);
var help = keys.length ? ['Options:'] : [];
if (usage) {
help.unshift(usage.replace(/\$0/g, self.$0), '');
}
var switches = keys.reduce(function(acc, key) {
acc[key] = [key]
.concat(options.alias[key] || [])
.map(function(sw) {
return (sw.length > 1 ? '--' : '-') + sw;
})
.join(', ');
return acc;
}, {});
var switchlen = longest(
Object.keys(switches).map(function(s) {
return switches[s] || '';
})
);
var desclen = longest(
Object.keys(descriptions).map(function(d) {
return descriptions[d] || '';
})
);
keys.forEach(function(key) {
var kswitch = switches[key];
var desc = descriptions[key] || '';
if (wrap) {
desc = wordwrap(switchlen + 4, wrap)(desc).slice(switchlen + 4);
}
var spadding = new Array(
Math.max(switchlen - kswitch.length + 3, 0)
).join(' ');
var dpadding = new Array(
Math.max(desclen - desc.length + 1, 0)
).join(' ');
var type = null;
if (options.boolean[key]) type = '[boolean]';
if (options.string[key]) type = '[string]';
if (!wrap && dpadding.length > 0) {
desc += dpadding;
}
var prelude = ' ' + kswitch + spadding;
var extra = [
type,
demanded[key] ? '[required]' : null,
options.default[key] !== undefined
? '[default: ' + JSON.stringify(options.default[key]) + ']'
: null
]
.filter(Boolean)
.join(' ');
var body = [desc, extra].filter(Boolean).join(' ');
if (wrap) {
var dlines = desc.split('\n');
var dlen =
dlines.slice(-1)[0].length +
(dlines.length === 1 ? prelude.length : 0);
body =
desc +
(dlen + extra.length > wrap - 2
? '\n' +
new Array(wrap - extra.length + 1).join(' ') +
extra
: new Array(wrap - extra.length - dlen + 1).join(' ') +
extra);
}
help.push(prelude + body);
});
help.push('');
return help.join('\n');
};
Object.defineProperty(self, 'argv', {
get: function() {
return parseArgs(processArgs);
},
enumerable: true
});
function parseArgs(args) {
var argv = minimist(args, options);
argv.$0 = self.$0;
if (demanded._ && argv._.length < demanded._) {
fail(
'Not enough non-option arguments: got ' +
argv._.length +
', need at least ' +
demanded._
);
}
var missing = [];
Object.keys(demanded).forEach(function(key) {
if (!argv[key]) missing.push(key);
});
if (missing.length) {
fail('Missing required arguments: ' + missing.join(', '));
}
checks.forEach(function(f) {
try {
if (f(argv) === false) {
fail('Argument check failed: ' + f.toString());
}
} catch (err) {
fail(err);
}
});
return argv;
}
function longest(xs) {
return Math.max.apply(
null,
xs.map(function(x) {
return x.length;
})
);
}
return self;
}
// rebase an absolute path to a relative one with respect to a base directory
// exported for tests
exports.rebase = rebase;
function rebase(base, dir) {
var ds = path
.normalize(dir)
.split('/')
.slice(1);
var bs = path
.normalize(base)
.split('/')
.slice(1);
for (var i = 0; ds[i] && ds[i] == bs[i]; i++);
ds.splice(0, i);
bs.splice(0, i);
var p = path
.normalize(
bs
.map(function() {
return '..';
})
.concat(ds)
.join('/')
)
.replace(/\/$/, '')
.replace(/^$/, '.');
return p.match(/^[.\/]/) ? p : './' + p;
}