You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
3.3 KiB
155 lines
3.3 KiB
3 years ago
|
'use strict';
|
||
|
|
||
|
const EQQ = /\s|=/;
|
||
|
const FLAG = /^-{1,2}/;
|
||
|
const PREFIX = /^--no-/i;
|
||
|
|
||
|
function isBool(any) {
|
||
|
return typeof any === 'boolean';
|
||
|
}
|
||
|
|
||
|
function toArr(any) {
|
||
|
return Array.isArray(any) ? any : any == null ? [] : [any];
|
||
|
}
|
||
|
|
||
|
function toString(any) {
|
||
|
return any == null || any === true ? '' : String(any);
|
||
|
}
|
||
|
|
||
|
function toBool(any) {
|
||
|
return any === 'false' ? false : Boolean(any);
|
||
|
}
|
||
|
|
||
|
function toNum(any) {
|
||
|
return (!isBool(any) && Number(any)) || any;
|
||
|
}
|
||
|
|
||
|
function getAlibi(names, arr) {
|
||
|
if (arr.length === 0) return arr;
|
||
|
let k, i = 0, len = arr.length, vals = [];
|
||
|
for (; i < len; i++) {
|
||
|
k = arr[i];
|
||
|
vals.push(k);
|
||
|
if (names[k] !== void 0) {
|
||
|
vals = vals.concat(names[k]);
|
||
|
}
|
||
|
}
|
||
|
return vals;
|
||
|
}
|
||
|
|
||
|
function typecast(key, val, strings, booleans) {
|
||
|
if (strings.indexOf(key) !== -1) return toString(val);
|
||
|
if (booleans.indexOf(key) !== -1) return toBool(val);
|
||
|
return toNum(val);
|
||
|
}
|
||
|
|
||
|
module.exports = function(args, opts) {
|
||
|
args = args || [];
|
||
|
opts = opts || {};
|
||
|
|
||
|
opts.string = toArr(opts.string);
|
||
|
opts.boolean = toArr(opts.boolean);
|
||
|
|
||
|
const aliases = {};
|
||
|
let k, i, j, x, y, len, type;
|
||
|
|
||
|
if (opts.alias !== void 0) {
|
||
|
for (k in opts.alias) {
|
||
|
aliases[k] = toArr(opts.alias[k]);
|
||
|
len = aliases[k].length; // save length
|
||
|
for (i = 0; i < len; i++) {
|
||
|
x = aliases[k][i]; // alias's key name
|
||
|
aliases[x] = [k]; // set initial array
|
||
|
for (j = 0; j < len; j++) {
|
||
|
if (x !== aliases[k][j]) {
|
||
|
aliases[x].push(aliases[k][j]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (opts.default !== void 0) {
|
||
|
for (k in opts.default) {
|
||
|
type = typeof opts.default[k];
|
||
|
opts[type] = (opts[type] || []).concat(k);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// apply to all aliases
|
||
|
opts.string = getAlibi(aliases, opts.string);
|
||
|
opts.boolean = getAlibi(aliases, opts.boolean);
|
||
|
|
||
|
let idx = 0;
|
||
|
const out = { _: [] };
|
||
|
|
||
|
while (args[idx] !== void 0) {
|
||
|
let incr = 1;
|
||
|
const val = args[idx];
|
||
|
|
||
|
if (val === '--') {
|
||
|
out._ = out._.concat(args.slice(idx + 1));
|
||
|
break;
|
||
|
} else if (!FLAG.test(val)) {
|
||
|
out._.push(val);
|
||
|
} else if (PREFIX.test(val)) {
|
||
|
out[val.replace(PREFIX, '')] = false;
|
||
|
} else {
|
||
|
let tmp;
|
||
|
const segs = val.split(EQQ);
|
||
|
const isGroup = segs[0].charCodeAt(1) !== 45; // '-'
|
||
|
|
||
|
const flag = segs[0].substr(isGroup ? 1 : 2);
|
||
|
len = flag.length;
|
||
|
const key = isGroup ? flag[len - 1] : flag;
|
||
|
|
||
|
if (opts.unknown !== void 0 && aliases[key] === void 0) {
|
||
|
return opts.unknown(segs[0]);
|
||
|
}
|
||
|
|
||
|
if (segs.length > 1) {
|
||
|
tmp = segs[1];
|
||
|
} else {
|
||
|
tmp = args[idx + 1] || true;
|
||
|
FLAG.test(tmp) ? (tmp = true) : (incr = 2);
|
||
|
}
|
||
|
|
||
|
if (isGroup && len > 1) {
|
||
|
for (i = len - 1; i--; ) {
|
||
|
k = flag[i]; // all but last key
|
||
|
out[k] = typecast(k, true, opts.string, opts.boolean);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const value = typecast(key, tmp, opts.string, opts.boolean);
|
||
|
out[key] = out[key] !== void 0 ? toArr(out[key]).concat(value) : value;
|
||
|
|
||
|
// handle discarded args when dealing with booleans
|
||
|
if (isBool(value) && !isBool(tmp) && tmp !== 'true' && tmp !== 'false') {
|
||
|
out._.push(tmp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
idx += incr;
|
||
|
}
|
||
|
|
||
|
if (opts.default !== void 0) {
|
||
|
for (k in opts.default) {
|
||
|
if (out[k] === void 0) {
|
||
|
out[k] = opts.default[k];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (k in out) {
|
||
|
if (aliases[k] === void 0) continue;
|
||
|
y = out[k];
|
||
|
len = aliases[k].length;
|
||
|
for (i = 0; i < len; i++) {
|
||
|
out[aliases[k][i]] = y; // assign value
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return out;
|
||
|
};
|