Spaces:
Sleeping
Sleeping
File size: 3,893 Bytes
4cadbaf |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
const flagSymbol = Symbol('arg flag');
function arg(opts, {argv = process.argv.slice(2), permissive = false, stopAtPositional = false} = {}) {
if (!opts) {
throw new Error('Argument specification object is required');
}
const result = {_: []};
const aliases = {};
const handlers = {};
for (const key of Object.keys(opts)) {
if (!key) {
throw new TypeError('Argument key cannot be an empty string');
}
if (key[0] !== '-') {
throw new TypeError(`Argument key must start with '-' but found: '${key}'`);
}
if (key.length === 1) {
throw new TypeError(`Argument key must have a name; singular '-' keys are not allowed: ${key}`);
}
if (typeof opts[key] === 'string') {
aliases[key] = opts[key];
continue;
}
let type = opts[key];
let isFlag = false;
if (Array.isArray(type) && type.length === 1 && typeof type[0] === 'function') {
const [fn] = type;
type = (value, name, prev = []) => {
prev.push(fn(value, name, prev[prev.length - 1]));
return prev;
};
isFlag = fn === Boolean || fn[flagSymbol] === true;
} else if (typeof type === 'function') {
isFlag = type === Boolean || type[flagSymbol] === true;
} else {
throw new TypeError(`Type missing or not a function or valid array type: ${key}`);
}
if (key[1] !== '-' && key.length > 2) {
throw new TypeError(`Short argument keys (with a single hyphen) must have only one character: ${key}`);
}
handlers[key] = [type, isFlag];
}
for (let i = 0, len = argv.length; i < len; i++) {
const wholeArg = argv[i];
if (stopAtPositional && result._.length > 0) {
result._ = result._.concat(argv.slice(i));
break;
}
if (wholeArg === '--') {
result._ = result._.concat(argv.slice(i + 1));
break;
}
if (wholeArg.length > 1 && wholeArg[0] === '-') {
/* eslint-disable operator-linebreak */
const separatedArguments = (wholeArg[1] === '-' || wholeArg.length === 2)
? [wholeArg]
: wholeArg.slice(1).split('').map(a => `-${a}`);
/* eslint-enable operator-linebreak */
for (let j = 0; j < separatedArguments.length; j++) {
const arg = separatedArguments[j];
const [originalArgName, argStr] = arg[1] === '-' ? arg.split(/=(.*)/, 2) : [arg, undefined];
let argName = originalArgName;
while (argName in aliases) {
argName = aliases[argName];
}
if (!(argName in handlers)) {
if (permissive) {
result._.push(arg);
continue;
} else {
const err = new Error(`Unknown or unexpected option: ${originalArgName}`);
err.code = 'ARG_UNKNOWN_OPTION';
throw err;
}
}
const [type, isFlag] = handlers[argName];
if (!isFlag && ((j + 1) < separatedArguments.length)) {
throw new TypeError(`Option requires argument (but was followed by another short argument): ${originalArgName}`);
}
if (isFlag) {
result[argName] = type(true, argName, result[argName]);
} else if (argStr === undefined) {
if (
argv.length < i + 2 ||
(
argv[i + 1].length > 1 &&
(argv[i + 1][0] === '-') &&
!(
argv[i + 1].match(/^-?\d*(\.(?=\d))?\d*$/) &&
(
type === Number ||
// eslint-disable-next-line no-undef
(typeof BigInt !== 'undefined' && type === BigInt)
)
)
)
) {
const extended = originalArgName === argName ? '' : ` (alias for ${argName})`;
throw new Error(`Option requires argument: ${originalArgName}${extended}`);
}
result[argName] = type(argv[i + 1], argName, result[argName]);
++i;
} else {
result[argName] = type(argStr, argName, result[argName]);
}
}
} else {
result._.push(wholeArg);
}
}
return result;
}
arg.flag = fn => {
fn[flagSymbol] = true;
return fn;
};
// Utility types
arg.COUNT = arg.flag((v, name, existingCount) => (existingCount || 0) + 1);
module.exports = arg;
|