415 lines
16 KiB
JavaScript
415 lines
16 KiB
JavaScript
'use strict';
|
|
|
|
var util = require('util');
|
|
var path = require('path');
|
|
var fs = require('fs');
|
|
|
|
function camelCase(str) {
|
|
const isCamelCase = str !== str.toLowerCase() && str !== str.toUpperCase();
|
|
if (!isCamelCase) {
|
|
str = str.toLowerCase();
|
|
}
|
|
if (str.indexOf('-') === -1 && str.indexOf('_') === -1) {
|
|
return str;
|
|
}
|
|
else {
|
|
let camelcase = '';
|
|
let nextChrUpper = false;
|
|
const leadingHyphens = str.match(/^-+/);
|
|
for (let i = leadingHyphens ? leadingHyphens[0].length : 0; i < str.length; i++) {
|
|
let chr = str.charAt(i);
|
|
if (nextChrUpper) {
|
|
nextChrUpper = false;
|
|
chr = chr.toUpperCase();
|
|
}
|
|
if (i !== 0 && (chr === '-' || chr === '_')) {
|
|
nextChrUpper = true;
|
|
}
|
|
else if (chr !== '-' && chr !== '_') {
|
|
camelcase += chr;
|
|
}
|
|
}
|
|
return camelcase;
|
|
}
|
|
}
|
|
function decamelize(str, joinString) {
|
|
const lowercase = str.toLowerCase();
|
|
joinString = joinString || '-';
|
|
let notCamelcase = '';
|
|
for (let i = 0; i < str.length; i++) {
|
|
const chrLower = lowercase.charAt(i);
|
|
const chrString = str.charAt(i);
|
|
if (chrLower !== chrString && i > 0) {
|
|
notCamelcase += `${joinString}${lowercase.charAt(i)}`;
|
|
}
|
|
else {
|
|
notCamelcase += chrString;
|
|
}
|
|
}
|
|
return notCamelcase;
|
|
}
|
|
function looksLikeNumber(x) {
|
|
if (x === null || x === undefined)
|
|
return false;
|
|
if (typeof x === 'number')
|
|
return true;
|
|
if (/^0x[0-9a-f]+$/i.test(x))
|
|
return true;
|
|
if (/^0[^.]/.test(x))
|
|
return false;
|
|
return /^[-]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
|
|
}
|
|
|
|
function tokenizeArgString(argString) {
|
|
if (Array.isArray(argString)) {
|
|
return argString.map(e => typeof e !== 'string' ? e + '' : e);
|
|
}
|
|
argString = argString.trim();
|
|
let i = 0;
|
|
let prevC = null;
|
|
let c = null;
|
|
let opening = null;
|
|
const args = [];
|
|
for (let ii = 0; ii < argString.length; ii++) {
|
|
prevC = c;
|
|
c = argString.charAt(ii);
|
|
if (c === ' ' && !opening) {
|
|
if (!(prevC === ' ')) {
|
|
i++;
|
|
}
|
|
continue;
|
|
}
|
|
if (c === opening) {
|
|
opening = null;
|
|
}
|
|
else if ((c === "'" || c === '"') && !opening) {
|
|
opening = c;
|
|
}
|
|
if (!args[i])
|
|
args[i] = '';
|
|
args[i] += c;
|
|
}
|
|
return args;
|
|
}
|
|
|
|
var DefaultValuesForTypeKey;
|
|
(function (DefaultValuesForTypeKey) {
|
|
DefaultValuesForTypeKey["BOOLEAN"] = "boolean";
|
|
DefaultValuesForTypeKey["STRING"] = "string";
|
|
DefaultValuesForTypeKey["NUMBER"] = "number";
|
|
DefaultValuesForTypeKey["ARRAY"] = "array";
|
|
})(DefaultValuesForTypeKey || (DefaultValuesForTypeKey = {}));
|
|
|
|
let mixin;
|
|
class YargsParser {
|
|
constructor(_mixin) {
|
|
mixin = _mixin;
|
|
}
|
|
parse(argsInput, options) {
|
|
const opts = Object.assign({
|
|
alias: undefined,
|
|
array: undefined,
|
|
boolean: undefined,
|
|
config: undefined,
|
|
configObjects: undefined,
|
|
configuration: undefined,
|
|
coerce: undefined,
|
|
count: undefined,
|
|
default: undefined,
|
|
envPrefix: undefined,
|
|
narg: undefined,
|
|
normalize: undefined,
|
|
string: undefined,
|
|
number: undefined,
|
|
__: undefined,
|
|
key: undefined
|
|
}, options);
|
|
const args = tokenizeArgString(argsInput);
|
|
const inputIsString = typeof argsInput === 'string';
|
|
const aliases = combineAliases(Object.assign(Object.create(null), opts.alias));
|
|
const configuration = Object.assign({
|
|
'boolean-negation': true,
|
|
'camel-case-expansion': true,
|
|
'combine-arrays': false,
|
|
'dot-notation': true,
|
|
'duplicate-arguments-array': true,
|
|
'flatten-duplicate-arrays': true,
|
|
'greedy-arrays': true,
|
|
'halt-at-non-option': false,
|
|
'nargs-eats-options': false,
|
|
'negation-prefix': 'no-',
|
|
'parse-numbers': true,
|
|
'parse-positional-numbers': true,
|
|
'populate--': false,
|
|
'set-placeholder-key': false,
|
|
'short-option-groups': true,
|
|
'strip-aliased': false,
|
|
'strip-dashed': false,
|
|
'unknown-options-as-args': false
|
|
}, opts.configuration);
|
|
const defaults = Object.assign(Object.create(null), opts.default);
|
|
const configObjects = opts.configObjects || [];
|
|
const envPrefix = opts.envPrefix;
|
|
const notFlagsOption = configuration['populate--'];
|
|
const notFlagsArgv = notFlagsOption ? '--' : '_';
|
|
const newAliases = Object.create(null);
|
|
const defaulted = Object.create(null);
|
|
const __ = opts.__ || mixin.format;
|
|
const flags = {
|
|
aliases: Object.create(null),
|
|
arrays: Object.create(null),
|
|
bools: Object.create(null),
|
|
strings: Object.create(null),
|
|
numbers: Object.create(null),
|
|
counts: Object.create(null),
|
|
normalize: Object.create(null),
|
|
configs: Object.create(null),
|
|
nargs: Object.create(null),
|
|
coercions: Object.create(null),
|
|
keys: []
|
|
};
|
|
const negative = /^-([0-9]+(\.[0-9]+)?|\.[0-9]+)$/;
|
|
const negatedBoolean = new RegExp('^--' + configuration['negation-prefix'] + '(.+)');
|
|
[].concat(opts.array || []).filter(Boolean).forEach(function (opt) {
|
|
const key = typeof opt === 'object' ? opt.key : opt;
|
|
const assignment = Object.keys(opt).map(function (key) {
|
|
const arrayFlagKeys = {
|
|
boolean: 'bools',
|
|
string: 'strings',
|
|
number: 'numbers'
|
|
};
|
|
return arrayFlagKeys[key];
|
|
}).filter(Boolean).pop();
|
|
if (assignment) {
|
|
flags[assignment][key] = true;
|
|
}
|
|
flags.arrays[key] = true;
|
|
flags.keys.push(key);
|
|
});
|
|
[].concat(opts.boolean || []).filter(Boolean).forEach(function (key) {
|
|
flags.bools[key] = true;
|
|
flags.keys.push(key);
|
|
});
|
|
[].concat(opts.string || []).filter(Boolean).forEach(function (key) {
|
|
flags.strings[key] = true;
|
|
flags.keys.push(key);
|
|
});
|
|
[].concat(opts.number || []).filter(Boolean).forEach(function (key) {
|
|
flags.numbers[key] = true;
|
|
flags.keys.push(key);
|
|
});
|
|
[].concat(opts.count || []).filter(Boolean).forEach(function (key) {
|
|
flags.counts[key] = true;
|
|
flags.keys.push(key);
|
|
});
|
|
[].concat(opts.normalize || []).filter(Boolean).forEach(function (key) {
|
|
flags.normalize[key] = true;
|
|
flags.keys.push(key);
|
|
});
|
|
if (typeof opts.narg === 'object') {
|
|
Object.entries(opts.narg).forEach(([key, value]) => {
|
|
if (typeof value === 'number') {
|
|
flags.nargs[key] = value;
|
|
flags.keys.push(key);
|
|
}
|
|
});
|
|
}
|
|
if (typeof opts.coerce === 'object') {
|
|
Object.entries(opts.coerce).forEach(([key, value]) => {
|
|
if (typeof value === 'function') {
|
|
flags.coercions[key] = value;
|
|
flags.keys.push(key);
|
|
}
|
|
});
|
|
}
|
|
if (typeof opts.config !== 'undefined') {
|
|
if (Array.isArray(opts.config) || typeof opts.config === 'string') {
|
|
[].concat(opts.config).filter(Boolean).forEach(function (key) {
|
|
flags.configs[key] = true;
|
|
});
|
|
}
|
|
else if (typeof opts.config === 'object') {
|
|
Object.entries(opts.config).forEach(([key, value]) => {
|
|
if (typeof value === 'boolean' || typeof value === 'function') {
|
|
flags.configs[key] = value;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
extendAliases(opts.key, aliases, opts.default, flags.arrays);
|
|
Object.keys(defaults).forEach(function (key) {
|
|
(flags.aliases[key] || []).forEach(function (alias) {
|
|
defaults[alias] = defaults[key];
|
|
});
|
|
});
|
|
let error = null;
|
|
checkConfiguration();
|
|
let notFlags = [];
|
|
const argv = Object.assign(Object.create(null), { _: [] });
|
|
const argvReturn = {};
|
|
for (let i = 0; i < args.length; i++) {
|
|
const arg = args[i];
|
|
const truncatedArg = arg.replace(/^-{3,}/, '---');
|
|
let broken;
|
|
let key;
|
|
let letters;
|
|
let m;
|
|
let next;
|
|
let value;
|
|
if (arg !== '--' && /^-/.test(arg) && isUnknownOptionAsArg(arg)) {
|
|
pushPositional(arg);
|
|
}
|
|
else if (truncatedArg.match(/^---+(=|$)/)) {
|
|
pushPositional(arg);
|
|
continue;
|
|
}
|
|
else if (arg.match(/^--.+=/) || (!configuration['short-option-groups'] && arg.match(/^-.+=/))) {
|
|
m = arg.match(/^--?([^=]+)=([\s\S]*)$/);
|
|
if (m !== null && Array.isArray(m) && m.length >= 3) {
|
|
if (checkAllAliases(m[1], flags.arrays)) {
|
|
i = eatArray(i, m[1], args, m[2]);
|
|
}
|
|
else if (checkAllAliases(m[1], flags.nargs) !== false) {
|
|
i = eatNargs(i, m[1], args, m[2]);
|
|
}
|
|
else {
|
|
setArg(m[1], m[2], true);
|
|
}
|
|
}
|
|
}
|
|
else if (arg.match(negatedBoolean) && configuration['boolean-negation']) {
|
|
m = arg.match(negatedBoolean);
|
|
if (m !== null && Array.isArray(m) && m.length >= 2) {
|
|
key = m[1];
|
|
setArg(key, checkAllAliases(key, flags.arrays) ? [false] : false);
|
|
}
|
|
}
|
|
else if (arg.match(/^--.+/) || (!configuration['short-option-groups'] && arg.match(/^-[^-]+/))) {
|
|
m = arg.match(/^--?(.+)/);
|
|
if (m !== null && Array.isArray(m) && m.length >= 2) {
|
|
key = m[1];
|
|
if (checkAllAliases(key, flags.arrays)) {
|
|
i = eatArray(i, key, args);
|
|
}
|
|
else if (checkAllAliases(key, flags.nargs) !== false) {
|
|
i = eatNargs(i, key, args);
|
|
}
|
|
else {
|
|
next = args[i + 1];
|
|
if (next !== undefined && (!next.match(/^-/) ||
|
|
next.match(negative)) &&
|
|
!checkAllAliases(key, flags.bools) &&
|
|
!checkAllAliases(key, flags.counts)) {
|
|
setArg(key, next);
|
|
i++;
|
|
}
|
|
else if (/^(true|false)$/.test(next)) {
|
|
setArg(key, next);
|
|
i++;
|
|
}
|
|
else {
|
|
setArg(key, defaultValue(key));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (arg.match(/^-.\..+=/)) {
|
|
m = arg.match(/^-([^=]+)=([\s\S]*)$/);
|
|
if (m !== null && Array.isArray(m) && m.length >= 3) {
|
|
setArg(m[1], m[2]);
|
|
}
|
|
}
|
|
else if (arg.match(/^-.\..+/) && !arg.match(negative)) {
|
|
next = args[i + 1];
|
|
m = arg.match(/^-(.\..+)/);
|
|
if (m !== null && Array.isArray(m) && m.length >= 2) {
|
|
key = m[1];
|
|
if (next !== undefined && !next.match(/^-/) &&
|
|
!checkAllAliases(key, flags.bools) &&
|
|
!checkAllAliases(key, flags.counts)) {
|
|
setArg(key, next);
|
|
i++;
|
|
}
|
|
else {
|
|
setArg(key, defaultValue(key));
|
|
}
|
|
}
|
|
}
|
|
else if (arg.match(/^-[^-]+/) && !arg.match(negative)) {
|
|
letters = arg.slice(1, -1).split('');
|
|
broken = false;
|
|
for (let j = 0; j < letters.length; j++) {
|
|
next = arg.slice(j + 2);
|
|
if (letters[j + 1] && letters[j + 1] === '=') {
|
|
value = arg.slice(j + 3);
|
|
key = letters[j];
|
|
if (checkAllAliases(key, flags.arrays)) {
|
|
i = eatArray(i, key, args, value);
|
|
}
|
|
else if (checkAllAliases(key, flags.nargs) !== false) {
|
|
i = eatNargs(i, key, args, value);
|
|
}
|
|
else {
|
|
setArg(key, value);
|
|
}
|
|
broken = true;
|
|
break;
|
|
}
|
|
if (next === '-') {
|
|
setArg(letters[j], next);
|
|
continue;
|
|
}
|
|
if (/[A-Za-z]/.test(letters[j]) &&
|
|
/^-?\d+(\.\d*)?(e-?\d+)?$/.test(next) &&
|
|
checkAllAliases(next, flags.bools) === false) {
|
|
setArg(letters[j], next);
|
|
broken = true;
|
|
break;
|
|
}
|
|
if (letters[j + 1] && letters[j + 1].match(/\W/)) {
|
|
setArg(letters[j], next);
|
|
broken = true;
|
|
break;
|
|
}
|
|
else {
|
|
setArg(letters[j], defaultValue(letters[j]));
|
|
}
|
|
}
|
|
key = arg.slice(-1)[0];
|
|
if (!broken && key !== '-') {
|
|
if (checkAllAliases(key, flags.arrays)) {
|
|
i = eatArray(i, key, args);
|
|
}
|
|
else if (checkAllAliases(key, flags.nargs) !== false) {
|
|
i = eatNargs(i, key, args);
|
|
}
|
|
else {
|
|
next = args[i + 1];
|
|
if (next !== undefined && (!/^(-|--)[^-]/.test(next) ||
|
|
next.match(negative)) &&
|
|
!checkAllAliases(key, flags.bools) &&
|
|
!checkAllAliases(key, flags.counts)) {
|
|
setArg(key, next);
|
|
i++;
|
|
}
|
|
else if (/^(true|false)$/.test(next)) {
|
|
setArg(key, next);
|
|
i++;
|
|
}
|
|
else {
|
|
setArg(key, defaultValue(key));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (arg.match(/^-[0-9]$/) &&
|
|
arg.match(negative) &&
|
|
checkAllAliases(arg.slice(1), flags.bools)) {
|
|
key = arg.slice(1);
|
|
setArg(key, defaultValue(key));
|
|
}
|
|
else if (arg === '--') {
|
|
notFlags = args.slice(i + 1);
|
|
break;
|
|
}
|
|
el |