export function parseOptions()

in src/util/commandline/option-parser.ts [90:166]


export function parseOptions(...params: any[]): void {
  let flagOptions: OptionsDescription;
  let positionalOptions: PositionalOptionsDescription;
  let target: any;
  let args: string[];

  if (params.length === 4) {
    debug(`Parser called with 4 args: ${util.inspect(params)}`);
    [flagOptions, positionalOptions, target, args] = params;
  } else {
    debug(`Parser called with 3 args: ${util.inspect(params)}`);
    [flagOptions, target, args] = params;
    positionalOptions = [];
  }

  debug(`Parsing command line ${args.join(" ")}`);
  const minimistOptions = descriptionToMinimistOpts(flagOptions);
  const parsed = minimist(args, minimistOptions);

  debug(`Raw parsed command line = ${util.inspect(parsed)}`);

  // handle flag args
  Object.keys(flagOptions).forEach((targetPropertyName) => {
    const option = flagOptions[targetPropertyName];
    const optKey = optionKey(option);

    // Skip required args if help or version have been invoked
    if (!parsed["help"] && !parsed["version"] && option.required && !parsed[optKey]) {
      // TODO: Replace this with auto-prompting
      throw new Error(`Missing required option ${optionDisplayName(option)}`);
    }
    target[targetPropertyName] = parsed[optKey];
  });

  // Handle positional args
  const positionalArgs = parsed["_"] || [];

  positionalOptions.sort((a, b) => {
    if (a.position === null) {
      return +1;
    }
    if (b.position === null) {
      return -1;
    }
    return b.position - a.position;
  });

  // Check for leftover positional parameters, fail if found
  const hasRestOption = positionalOptions.some((o) => o.position === null);
  if (!hasRestOption && positionalArgs.length > positionalOptions.length) {
    const unknownArgs = positionalArgs.slice(positionalOptions.length);
    throw new Error(`Unknown arguments: ${unknownArgs.join(" ")}`);
  }

  positionalOptions.forEach((opt, index) => {
    debug(`Checking for ${opt.required ? "required" : "optional"} option ${opt.name} at position ${opt.position}`);

    if (positionalArgs.length - 1 < opt.position) {
      if (!parsed["help"] && opt.required) {
        throw new Error(`Missing required positional argument ${opt.name}`);
      } else if (opt.defaultValue) {
        target[opt.propertyName] = opt.defaultValue;
        return;
      } else {
        return;
      }
    }

    if (opt.position !== null) {
      target[opt.propertyName] = positionalArgs[opt.position];
      positionalArgs[opt.position] = null;
    } else {
      // This is the rest argument, pick up whatever's left
      target[opt.propertyName] = positionalArgs.filter((opt) => opt !== null);
    }
  });
}