function parse()

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;
}