in src/argsParser.js [124:244]
function parse(options, args=process.argv.slice(2)) {
const missingValue = Symbol();
const preparedOptions = prepareOptions(options);
const parsedOptions = {};
const positionalArguments = [];
for (const optionName in options) {
const option = options[optionName];
if (option.default !== undefined) {
parsedOptions[optionName] = option.default;
} else if (option.list) {
parsedOptions[optionName] = [];
}
}
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (isOption(arg)) {
let optionName = arg;
let value = null;
let option = null;
if (optionName.includes('=')) {
const index = arg.indexOf('=');
optionName = arg.slice(0, index);
value = arg.slice(index+1);
}
if (preparedOptions.hasOwnProperty(optionName)) {
option = preparedOptions[optionName];
} else {
// Unknown options are just "passed along".
// The logic is as follows:
// - If an option is encountered without a value, it's treated
// as a flag
// - If the option has a value, it's initialized with that value
// - If the option has been seen before, it's converted to a list
// If the previous value was true (i.e. a flag), that value is
// discarded.
const realOptionName = optionName.replace(/^--?(no-)?/, '');
const isList = parsedOptions.hasOwnProperty(realOptionName) &&
parsedOptions[realOptionName] !== true;
option = {
key: realOptionName,
full: realOptionName,
flag: !parsedOptions.hasOwnProperty(realOptionName) &&
value === null &&
isOption(args[i+1]),
list: isList,
process(value) {
// Try to parse values as JSON to be compatible with nomnom
try {
return JSON.parse(value);
} catch(_e) {}
return value;
},
};
if (isList) {
const currentValue = parsedOptions[realOptionName];
if (!Array.isArray(currentValue)) {
parsedOptions[realOptionName] = currentValue === true ?
[] :
[currentValue];
}
}
}
if (option.callback) {
throwError(0, option.callback());
} else if (option.flag) {
if (optionName.startsWith('--no-')) {
value = false;
} else if (value !== null) {
value = value === '1';
} else {
value = true;
}
parsedOptions[option.key] = value;
} else {
if (value === null && i < args.length - 1 && !isOption(args[i+1])) {
// consume next value
value = args[i+1];
i += 1;
}
if (value !== null) {
if (option.process) {
value = option.process(value);
}
if (option.list) {
parsedOptions[option.key].push(value);
} else {
parsedOptions[option.key] = value;
}
} else {
parsedOptions[option.key] = missingValue;
}
}
} else {
positionalArguments.push(/^\d+$/.test(arg) ? Number(arg) : arg);
}
}
for (const optionName in parsedOptions) {
if (parsedOptions[optionName] === missingValue) {
throwError(
1,
`Missing value: --${options[optionName].full} requires a value`,
getHelpText(options)
);
}
}
const result = {
positionalArguments,
options: parsedOptions,
};
validateOptions(parsedOptions, options);
return result;
}