init
This commit is contained in:
		
							
								
								
									
										147
									
								
								node_modules/commander/lib/argument.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								node_modules/commander/lib/argument.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,147 @@
 | 
			
		||||
const { InvalidArgumentError } = require('./error.js');
 | 
			
		||||
 | 
			
		||||
// @ts-check
 | 
			
		||||
 | 
			
		||||
class Argument {
 | 
			
		||||
  /**
 | 
			
		||||
   * Initialize a new command argument with the given name and description.
 | 
			
		||||
   * The default is that the argument is required, and you can explicitly
 | 
			
		||||
   * indicate this with <> around the name. Put [] around the name for an optional argument.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {string} name
 | 
			
		||||
   * @param {string} [description]
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  constructor(name, description) {
 | 
			
		||||
    this.description = description || '';
 | 
			
		||||
    this.variadic = false;
 | 
			
		||||
    this.parseArg = undefined;
 | 
			
		||||
    this.defaultValue = undefined;
 | 
			
		||||
    this.defaultValueDescription = undefined;
 | 
			
		||||
    this.argChoices = undefined;
 | 
			
		||||
 | 
			
		||||
    switch (name[0]) {
 | 
			
		||||
      case '<': // e.g. <required>
 | 
			
		||||
        this.required = true;
 | 
			
		||||
        this._name = name.slice(1, -1);
 | 
			
		||||
        break;
 | 
			
		||||
      case '[': // e.g. [optional]
 | 
			
		||||
        this.required = false;
 | 
			
		||||
        this._name = name.slice(1, -1);
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        this.required = true;
 | 
			
		||||
        this._name = name;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._name.length > 3 && this._name.slice(-3) === '...') {
 | 
			
		||||
      this.variadic = true;
 | 
			
		||||
      this._name = this._name.slice(0, -3);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Return argument name.
 | 
			
		||||
   *
 | 
			
		||||
   * @return {string}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  name() {
 | 
			
		||||
    return this._name;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @api private
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  _concatValue(value, previous) {
 | 
			
		||||
    if (previous === this.defaultValue || !Array.isArray(previous)) {
 | 
			
		||||
      return [value];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return previous.concat(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Set the default value, and optionally supply the description to be displayed in the help.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {any} value
 | 
			
		||||
   * @param {string} [description]
 | 
			
		||||
   * @return {Argument}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  default(value, description) {
 | 
			
		||||
    this.defaultValue = value;
 | 
			
		||||
    this.defaultValueDescription = description;
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Set the custom handler for processing CLI command arguments into argument values.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Function} [fn]
 | 
			
		||||
   * @return {Argument}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  argParser(fn) {
 | 
			
		||||
    this.parseArg = fn;
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Only allow argument value to be one of choices.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {string[]} values
 | 
			
		||||
   * @return {Argument}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  choices(values) {
 | 
			
		||||
    this.argChoices = values.slice();
 | 
			
		||||
    this.parseArg = (arg, previous) => {
 | 
			
		||||
      if (!this.argChoices.includes(arg)) {
 | 
			
		||||
        throw new InvalidArgumentError(`Allowed choices are ${this.argChoices.join(', ')}.`);
 | 
			
		||||
      }
 | 
			
		||||
      if (this.variadic) {
 | 
			
		||||
        return this._concatValue(arg, previous);
 | 
			
		||||
      }
 | 
			
		||||
      return arg;
 | 
			
		||||
    };
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Make argument required.
 | 
			
		||||
   */
 | 
			
		||||
  argRequired() {
 | 
			
		||||
    this.required = true;
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Make argument optional.
 | 
			
		||||
   */
 | 
			
		||||
  argOptional() {
 | 
			
		||||
    this.required = false;
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Takes an argument and returns its human readable equivalent for help usage.
 | 
			
		||||
 *
 | 
			
		||||
 * @param {Argument} arg
 | 
			
		||||
 * @return {string}
 | 
			
		||||
 * @api private
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
function humanReadableArgName(arg) {
 | 
			
		||||
  const nameOutput = arg.name() + (arg.variadic === true ? '...' : '');
 | 
			
		||||
 | 
			
		||||
  return arg.required
 | 
			
		||||
    ? '<' + nameOutput + '>'
 | 
			
		||||
    : '[' + nameOutput + ']';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.Argument = Argument;
 | 
			
		||||
exports.humanReadableArgName = humanReadableArgName;
 | 
			
		||||
							
								
								
									
										2179
									
								
								node_modules/commander/lib/command.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2179
									
								
								node_modules/commander/lib/command.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										45
									
								
								node_modules/commander/lib/error.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								node_modules/commander/lib/error.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
// @ts-check
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * CommanderError class
 | 
			
		||||
 * @class
 | 
			
		||||
 */
 | 
			
		||||
class CommanderError extends Error {
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs the CommanderError class
 | 
			
		||||
   * @param {number} exitCode suggested exit code which could be used with process.exit
 | 
			
		||||
   * @param {string} code an id string representing the error
 | 
			
		||||
   * @param {string} message human-readable description of the error
 | 
			
		||||
   * @constructor
 | 
			
		||||
   */
 | 
			
		||||
  constructor(exitCode, code, message) {
 | 
			
		||||
    super(message);
 | 
			
		||||
    // properly capture stack trace in Node.js
 | 
			
		||||
    Error.captureStackTrace(this, this.constructor);
 | 
			
		||||
    this.name = this.constructor.name;
 | 
			
		||||
    this.code = code;
 | 
			
		||||
    this.exitCode = exitCode;
 | 
			
		||||
    this.nestedError = undefined;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * InvalidArgumentError class
 | 
			
		||||
 * @class
 | 
			
		||||
 */
 | 
			
		||||
class InvalidArgumentError extends CommanderError {
 | 
			
		||||
  /**
 | 
			
		||||
   * Constructs the InvalidArgumentError class
 | 
			
		||||
   * @param {string} [message] explanation of why argument is invalid
 | 
			
		||||
   * @constructor
 | 
			
		||||
   */
 | 
			
		||||
  constructor(message) {
 | 
			
		||||
    super(1, 'commander.invalidArgument', message);
 | 
			
		||||
    // properly capture stack trace in Node.js
 | 
			
		||||
    Error.captureStackTrace(this, this.constructor);
 | 
			
		||||
    this.name = this.constructor.name;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.CommanderError = CommanderError;
 | 
			
		||||
exports.InvalidArgumentError = InvalidArgumentError;
 | 
			
		||||
							
								
								
									
										461
									
								
								node_modules/commander/lib/help.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										461
									
								
								node_modules/commander/lib/help.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,461 @@
 | 
			
		||||
const { humanReadableArgName } = require('./argument.js');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TypeScript import types for JSDoc, used by Visual Studio Code IntelliSense and `npm run typescript-checkJS`
 | 
			
		||||
 * https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#import-types
 | 
			
		||||
 * @typedef { import("./argument.js").Argument } Argument
 | 
			
		||||
 * @typedef { import("./command.js").Command } Command
 | 
			
		||||
 * @typedef { import("./option.js").Option } Option
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// @ts-check
 | 
			
		||||
 | 
			
		||||
// Although this is a class, methods are static in style to allow override using subclass or just functions.
 | 
			
		||||
class Help {
 | 
			
		||||
  constructor() {
 | 
			
		||||
    this.helpWidth = undefined;
 | 
			
		||||
    this.sortSubcommands = false;
 | 
			
		||||
    this.sortOptions = false;
 | 
			
		||||
    this.showGlobalOptions = false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get an array of the visible subcommands. Includes a placeholder for the implicit help command, if there is one.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @returns {Command[]}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  visibleCommands(cmd) {
 | 
			
		||||
    const visibleCommands = cmd.commands.filter(cmd => !cmd._hidden);
 | 
			
		||||
    if (cmd._hasImplicitHelpCommand()) {
 | 
			
		||||
      // Create a command matching the implicit help command.
 | 
			
		||||
      const [, helpName, helpArgs] = cmd._helpCommandnameAndArgs.match(/([^ ]+) *(.*)/);
 | 
			
		||||
      const helpCommand = cmd.createCommand(helpName)
 | 
			
		||||
        .helpOption(false);
 | 
			
		||||
      helpCommand.description(cmd._helpCommandDescription);
 | 
			
		||||
      if (helpArgs) helpCommand.arguments(helpArgs);
 | 
			
		||||
      visibleCommands.push(helpCommand);
 | 
			
		||||
    }
 | 
			
		||||
    if (this.sortSubcommands) {
 | 
			
		||||
      visibleCommands.sort((a, b) => {
 | 
			
		||||
        // @ts-ignore: overloaded return type
 | 
			
		||||
        return a.name().localeCompare(b.name());
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    return visibleCommands;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Compare options for sort.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Option} a
 | 
			
		||||
   * @param {Option} b
 | 
			
		||||
   * @returns number
 | 
			
		||||
   */
 | 
			
		||||
  compareOptions(a, b) {
 | 
			
		||||
    const getSortKey = (option) => {
 | 
			
		||||
      // WYSIWYG for order displayed in help. Short used for comparison if present. No special handling for negated.
 | 
			
		||||
      return option.short ? option.short.replace(/^-/, '') : option.long.replace(/^--/, '');
 | 
			
		||||
    };
 | 
			
		||||
    return getSortKey(a).localeCompare(getSortKey(b));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get an array of the visible options. Includes a placeholder for the implicit help option, if there is one.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @returns {Option[]}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  visibleOptions(cmd) {
 | 
			
		||||
    const visibleOptions = cmd.options.filter((option) => !option.hidden);
 | 
			
		||||
    // Implicit help
 | 
			
		||||
    const showShortHelpFlag = cmd._hasHelpOption && cmd._helpShortFlag && !cmd._findOption(cmd._helpShortFlag);
 | 
			
		||||
    const showLongHelpFlag = cmd._hasHelpOption && !cmd._findOption(cmd._helpLongFlag);
 | 
			
		||||
    if (showShortHelpFlag || showLongHelpFlag) {
 | 
			
		||||
      let helpOption;
 | 
			
		||||
      if (!showShortHelpFlag) {
 | 
			
		||||
        helpOption = cmd.createOption(cmd._helpLongFlag, cmd._helpDescription);
 | 
			
		||||
      } else if (!showLongHelpFlag) {
 | 
			
		||||
        helpOption = cmd.createOption(cmd._helpShortFlag, cmd._helpDescription);
 | 
			
		||||
      } else {
 | 
			
		||||
        helpOption = cmd.createOption(cmd._helpFlags, cmd._helpDescription);
 | 
			
		||||
      }
 | 
			
		||||
      visibleOptions.push(helpOption);
 | 
			
		||||
    }
 | 
			
		||||
    if (this.sortOptions) {
 | 
			
		||||
      visibleOptions.sort(this.compareOptions);
 | 
			
		||||
    }
 | 
			
		||||
    return visibleOptions;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get an array of the visible global options. (Not including help.)
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @returns {Option[]}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  visibleGlobalOptions(cmd) {
 | 
			
		||||
    if (!this.showGlobalOptions) return [];
 | 
			
		||||
 | 
			
		||||
    const globalOptions = [];
 | 
			
		||||
    for (let parentCmd = cmd.parent; parentCmd; parentCmd = parentCmd.parent) {
 | 
			
		||||
      const visibleOptions = parentCmd.options.filter((option) => !option.hidden);
 | 
			
		||||
      globalOptions.push(...visibleOptions);
 | 
			
		||||
    }
 | 
			
		||||
    if (this.sortOptions) {
 | 
			
		||||
      globalOptions.sort(this.compareOptions);
 | 
			
		||||
    }
 | 
			
		||||
    return globalOptions;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get an array of the arguments if any have a description.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @returns {Argument[]}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  visibleArguments(cmd) {
 | 
			
		||||
    // Side effect! Apply the legacy descriptions before the arguments are displayed.
 | 
			
		||||
    if (cmd._argsDescription) {
 | 
			
		||||
      cmd._args.forEach(argument => {
 | 
			
		||||
        argument.description = argument.description || cmd._argsDescription[argument.name()] || '';
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // If there are any arguments with a description then return all the arguments.
 | 
			
		||||
    if (cmd._args.find(argument => argument.description)) {
 | 
			
		||||
      return cmd._args;
 | 
			
		||||
    }
 | 
			
		||||
    return [];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the command term to show in the list of subcommands.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @returns {string}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  subcommandTerm(cmd) {
 | 
			
		||||
    // Legacy. Ignores custom usage string, and nested commands.
 | 
			
		||||
    const args = cmd._args.map(arg => humanReadableArgName(arg)).join(' ');
 | 
			
		||||
    return cmd._name +
 | 
			
		||||
      (cmd._aliases[0] ? '|' + cmd._aliases[0] : '') +
 | 
			
		||||
      (cmd.options.length ? ' [options]' : '') + // simplistic check for non-help option
 | 
			
		||||
      (args ? ' ' + args : '');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the option term to show in the list of options.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Option} option
 | 
			
		||||
   * @returns {string}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  optionTerm(option) {
 | 
			
		||||
    return option.flags;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the argument term to show in the list of arguments.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Argument} argument
 | 
			
		||||
   * @returns {string}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  argumentTerm(argument) {
 | 
			
		||||
    return argument.name();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the longest command term length.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @param {Help} helper
 | 
			
		||||
   * @returns {number}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  longestSubcommandTermLength(cmd, helper) {
 | 
			
		||||
    return helper.visibleCommands(cmd).reduce((max, command) => {
 | 
			
		||||
      return Math.max(max, helper.subcommandTerm(command).length);
 | 
			
		||||
    }, 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the longest option term length.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @param {Help} helper
 | 
			
		||||
   * @returns {number}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  longestOptionTermLength(cmd, helper) {
 | 
			
		||||
    return helper.visibleOptions(cmd).reduce((max, option) => {
 | 
			
		||||
      return Math.max(max, helper.optionTerm(option).length);
 | 
			
		||||
    }, 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the longest global option term length.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @param {Help} helper
 | 
			
		||||
   * @returns {number}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  longestGlobalOptionTermLength(cmd, helper) {
 | 
			
		||||
    return helper.visibleGlobalOptions(cmd).reduce((max, option) => {
 | 
			
		||||
      return Math.max(max, helper.optionTerm(option).length);
 | 
			
		||||
    }, 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the longest argument term length.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @param {Help} helper
 | 
			
		||||
   * @returns {number}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  longestArgumentTermLength(cmd, helper) {
 | 
			
		||||
    return helper.visibleArguments(cmd).reduce((max, argument) => {
 | 
			
		||||
      return Math.max(max, helper.argumentTerm(argument).length);
 | 
			
		||||
    }, 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the command usage to be displayed at the top of the built-in help.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @returns {string}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  commandUsage(cmd) {
 | 
			
		||||
    // Usage
 | 
			
		||||
    let cmdName = cmd._name;
 | 
			
		||||
    if (cmd._aliases[0]) {
 | 
			
		||||
      cmdName = cmdName + '|' + cmd._aliases[0];
 | 
			
		||||
    }
 | 
			
		||||
    let parentCmdNames = '';
 | 
			
		||||
    for (let parentCmd = cmd.parent; parentCmd; parentCmd = parentCmd.parent) {
 | 
			
		||||
      parentCmdNames = parentCmd.name() + ' ' + parentCmdNames;
 | 
			
		||||
    }
 | 
			
		||||
    return parentCmdNames + cmdName + ' ' + cmd.usage();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the description for the command.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @returns {string}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  commandDescription(cmd) {
 | 
			
		||||
    // @ts-ignore: overloaded return type
 | 
			
		||||
    return cmd.description();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the subcommand summary to show in the list of subcommands.
 | 
			
		||||
   * (Fallback to description for backwards compatibility.)
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @returns {string}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  subcommandDescription(cmd) {
 | 
			
		||||
    // @ts-ignore: overloaded return type
 | 
			
		||||
    return cmd.summary() || cmd.description();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the option description to show in the list of options.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Option} option
 | 
			
		||||
   * @return {string}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  optionDescription(option) {
 | 
			
		||||
    const extraInfo = [];
 | 
			
		||||
 | 
			
		||||
    if (option.argChoices) {
 | 
			
		||||
      extraInfo.push(
 | 
			
		||||
        // use stringify to match the display of the default value
 | 
			
		||||
        `choices: ${option.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`);
 | 
			
		||||
    }
 | 
			
		||||
    if (option.defaultValue !== undefined) {
 | 
			
		||||
      // default for boolean and negated more for programmer than end user,
 | 
			
		||||
      // but show true/false for boolean option as may be for hand-rolled env or config processing.
 | 
			
		||||
      const showDefault = option.required || option.optional ||
 | 
			
		||||
        (option.isBoolean() && typeof option.defaultValue === 'boolean');
 | 
			
		||||
      if (showDefault) {
 | 
			
		||||
        extraInfo.push(`default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    // preset for boolean and negated are more for programmer than end user
 | 
			
		||||
    if (option.presetArg !== undefined && option.optional) {
 | 
			
		||||
      extraInfo.push(`preset: ${JSON.stringify(option.presetArg)}`);
 | 
			
		||||
    }
 | 
			
		||||
    if (option.envVar !== undefined) {
 | 
			
		||||
      extraInfo.push(`env: ${option.envVar}`);
 | 
			
		||||
    }
 | 
			
		||||
    if (extraInfo.length > 0) {
 | 
			
		||||
      return `${option.description} (${extraInfo.join(', ')})`;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return option.description;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the argument description to show in the list of arguments.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Argument} argument
 | 
			
		||||
   * @return {string}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  argumentDescription(argument) {
 | 
			
		||||
    const extraInfo = [];
 | 
			
		||||
    if (argument.argChoices) {
 | 
			
		||||
      extraInfo.push(
 | 
			
		||||
        // use stringify to match the display of the default value
 | 
			
		||||
        `choices: ${argument.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`);
 | 
			
		||||
    }
 | 
			
		||||
    if (argument.defaultValue !== undefined) {
 | 
			
		||||
      extraInfo.push(`default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`);
 | 
			
		||||
    }
 | 
			
		||||
    if (extraInfo.length > 0) {
 | 
			
		||||
      const extraDescripton = `(${extraInfo.join(', ')})`;
 | 
			
		||||
      if (argument.description) {
 | 
			
		||||
        return `${argument.description} ${extraDescripton}`;
 | 
			
		||||
      }
 | 
			
		||||
      return extraDescripton;
 | 
			
		||||
    }
 | 
			
		||||
    return argument.description;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Generate the built-in help text.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @param {Help} helper
 | 
			
		||||
   * @returns {string}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  formatHelp(cmd, helper) {
 | 
			
		||||
    const termWidth = helper.padWidth(cmd, helper);
 | 
			
		||||
    const helpWidth = helper.helpWidth || 80;
 | 
			
		||||
    const itemIndentWidth = 2;
 | 
			
		||||
    const itemSeparatorWidth = 2; // between term and description
 | 
			
		||||
    function formatItem(term, description) {
 | 
			
		||||
      if (description) {
 | 
			
		||||
        const fullText = `${term.padEnd(termWidth + itemSeparatorWidth)}${description}`;
 | 
			
		||||
        return helper.wrap(fullText, helpWidth - itemIndentWidth, termWidth + itemSeparatorWidth);
 | 
			
		||||
      }
 | 
			
		||||
      return term;
 | 
			
		||||
    }
 | 
			
		||||
    function formatList(textArray) {
 | 
			
		||||
      return textArray.join('\n').replace(/^/gm, ' '.repeat(itemIndentWidth));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Usage
 | 
			
		||||
    let output = [`Usage: ${helper.commandUsage(cmd)}`, ''];
 | 
			
		||||
 | 
			
		||||
    // Description
 | 
			
		||||
    const commandDescription = helper.commandDescription(cmd);
 | 
			
		||||
    if (commandDescription.length > 0) {
 | 
			
		||||
      output = output.concat([commandDescription, '']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Arguments
 | 
			
		||||
    const argumentList = helper.visibleArguments(cmd).map((argument) => {
 | 
			
		||||
      return formatItem(helper.argumentTerm(argument), helper.argumentDescription(argument));
 | 
			
		||||
    });
 | 
			
		||||
    if (argumentList.length > 0) {
 | 
			
		||||
      output = output.concat(['Arguments:', formatList(argumentList), '']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Options
 | 
			
		||||
    const optionList = helper.visibleOptions(cmd).map((option) => {
 | 
			
		||||
      return formatItem(helper.optionTerm(option), helper.optionDescription(option));
 | 
			
		||||
    });
 | 
			
		||||
    if (optionList.length > 0) {
 | 
			
		||||
      output = output.concat(['Options:', formatList(optionList), '']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this.showGlobalOptions) {
 | 
			
		||||
      const globalOptionList = helper.visibleGlobalOptions(cmd).map((option) => {
 | 
			
		||||
        return formatItem(helper.optionTerm(option), helper.optionDescription(option));
 | 
			
		||||
      });
 | 
			
		||||
      if (globalOptionList.length > 0) {
 | 
			
		||||
        output = output.concat(['Global Options:', formatList(globalOptionList), '']);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Commands
 | 
			
		||||
    const commandList = helper.visibleCommands(cmd).map((cmd) => {
 | 
			
		||||
      return formatItem(helper.subcommandTerm(cmd), helper.subcommandDescription(cmd));
 | 
			
		||||
    });
 | 
			
		||||
    if (commandList.length > 0) {
 | 
			
		||||
      output = output.concat(['Commands:', formatList(commandList), '']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return output.join('\n');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Calculate the pad width from the maximum term length.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Command} cmd
 | 
			
		||||
   * @param {Help} helper
 | 
			
		||||
   * @returns {number}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  padWidth(cmd, helper) {
 | 
			
		||||
    return Math.max(
 | 
			
		||||
      helper.longestOptionTermLength(cmd, helper),
 | 
			
		||||
      helper.longestGlobalOptionTermLength(cmd, helper),
 | 
			
		||||
      helper.longestSubcommandTermLength(cmd, helper),
 | 
			
		||||
      helper.longestArgumentTermLength(cmd, helper)
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Wrap the given string to width characters per line, with lines after the first indented.
 | 
			
		||||
   * Do not wrap if insufficient room for wrapping (minColumnWidth), or string is manually formatted.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {string} str
 | 
			
		||||
   * @param {number} width
 | 
			
		||||
   * @param {number} indent
 | 
			
		||||
   * @param {number} [minColumnWidth=40]
 | 
			
		||||
   * @return {string}
 | 
			
		||||
   *
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  wrap(str, width, indent, minColumnWidth = 40) {
 | 
			
		||||
    // Detect manually wrapped and indented strings by searching for line breaks
 | 
			
		||||
    // followed by multiple spaces/tabs.
 | 
			
		||||
    if (str.match(/[\n]\s+/)) return str;
 | 
			
		||||
    // Do not wrap if not enough room for a wrapped column of text (as could end up with a word per line).
 | 
			
		||||
    const columnWidth = width - indent;
 | 
			
		||||
    if (columnWidth < minColumnWidth) return str;
 | 
			
		||||
 | 
			
		||||
    const leadingStr = str.slice(0, indent);
 | 
			
		||||
    const columnText = str.slice(indent);
 | 
			
		||||
 | 
			
		||||
    const indentString = ' '.repeat(indent);
 | 
			
		||||
    const regex = new RegExp('.{1,' + (columnWidth - 1) + '}([\\s\u200B]|$)|[^\\s\u200B]+?([\\s\u200B]|$)', 'g');
 | 
			
		||||
    const lines = columnText.match(regex) || [];
 | 
			
		||||
    return leadingStr + lines.map((line, i) => {
 | 
			
		||||
      if (line.slice(-1) === '\n') {
 | 
			
		||||
        line = line.slice(0, line.length - 1);
 | 
			
		||||
      }
 | 
			
		||||
      return ((i > 0) ? indentString : '') + line.trimRight();
 | 
			
		||||
    }).join('\n');
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.Help = Help;
 | 
			
		||||
							
								
								
									
										326
									
								
								node_modules/commander/lib/option.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										326
									
								
								node_modules/commander/lib/option.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,326 @@
 | 
			
		||||
const { InvalidArgumentError } = require('./error.js');
 | 
			
		||||
 | 
			
		||||
// @ts-check
 | 
			
		||||
 | 
			
		||||
class Option {
 | 
			
		||||
  /**
 | 
			
		||||
   * Initialize a new `Option` with the given `flags` and `description`.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {string} flags
 | 
			
		||||
   * @param {string} [description]
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  constructor(flags, description) {
 | 
			
		||||
    this.flags = flags;
 | 
			
		||||
    this.description = description || '';
 | 
			
		||||
 | 
			
		||||
    this.required = flags.includes('<'); // A value must be supplied when the option is specified.
 | 
			
		||||
    this.optional = flags.includes('['); // A value is optional when the option is specified.
 | 
			
		||||
    // variadic test ignores <value,...> et al which might be used to describe custom splitting of single argument
 | 
			
		||||
    this.variadic = /\w\.\.\.[>\]]$/.test(flags); // The option can take multiple values.
 | 
			
		||||
    this.mandatory = false; // The option must have a value after parsing, which usually means it must be specified on command line.
 | 
			
		||||
    const optionFlags = splitOptionFlags(flags);
 | 
			
		||||
    this.short = optionFlags.shortFlag;
 | 
			
		||||
    this.long = optionFlags.longFlag;
 | 
			
		||||
    this.negate = false;
 | 
			
		||||
    if (this.long) {
 | 
			
		||||
      this.negate = this.long.startsWith('--no-');
 | 
			
		||||
    }
 | 
			
		||||
    this.defaultValue = undefined;
 | 
			
		||||
    this.defaultValueDescription = undefined;
 | 
			
		||||
    this.presetArg = undefined;
 | 
			
		||||
    this.envVar = undefined;
 | 
			
		||||
    this.parseArg = undefined;
 | 
			
		||||
    this.hidden = false;
 | 
			
		||||
    this.argChoices = undefined;
 | 
			
		||||
    this.conflictsWith = [];
 | 
			
		||||
    this.implied = undefined;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Set the default value, and optionally supply the description to be displayed in the help.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {any} value
 | 
			
		||||
   * @param {string} [description]
 | 
			
		||||
   * @return {Option}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  default(value, description) {
 | 
			
		||||
    this.defaultValue = value;
 | 
			
		||||
    this.defaultValueDescription = description;
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Preset to use when option used without option-argument, especially optional but also boolean and negated.
 | 
			
		||||
   * The custom processing (parseArg) is called.
 | 
			
		||||
   *
 | 
			
		||||
   * @example
 | 
			
		||||
   * new Option('--color').default('GREYSCALE').preset('RGB');
 | 
			
		||||
   * new Option('--donate [amount]').preset('20').argParser(parseFloat);
 | 
			
		||||
   *
 | 
			
		||||
   * @param {any} arg
 | 
			
		||||
   * @return {Option}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  preset(arg) {
 | 
			
		||||
    this.presetArg = arg;
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Add option name(s) that conflict with this option.
 | 
			
		||||
   * An error will be displayed if conflicting options are found during parsing.
 | 
			
		||||
   *
 | 
			
		||||
   * @example
 | 
			
		||||
   * new Option('--rgb').conflicts('cmyk');
 | 
			
		||||
   * new Option('--js').conflicts(['ts', 'jsx']);
 | 
			
		||||
   *
 | 
			
		||||
   * @param {string | string[]} names
 | 
			
		||||
   * @return {Option}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  conflicts(names) {
 | 
			
		||||
    this.conflictsWith = this.conflictsWith.concat(names);
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Specify implied option values for when this option is set and the implied options are not.
 | 
			
		||||
   *
 | 
			
		||||
   * The custom processing (parseArg) is not called on the implied values.
 | 
			
		||||
   *
 | 
			
		||||
   * @example
 | 
			
		||||
   * program
 | 
			
		||||
   *   .addOption(new Option('--log', 'write logging information to file'))
 | 
			
		||||
   *   .addOption(new Option('--trace', 'log extra details').implies({ log: 'trace.txt' }));
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Object} impliedOptionValues
 | 
			
		||||
   * @return {Option}
 | 
			
		||||
   */
 | 
			
		||||
  implies(impliedOptionValues) {
 | 
			
		||||
    this.implied = Object.assign(this.implied || {}, impliedOptionValues);
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Set environment variable to check for option value.
 | 
			
		||||
   *
 | 
			
		||||
   * An environment variable is only used if when processed the current option value is
 | 
			
		||||
   * undefined, or the source of the current value is 'default' or 'config' or 'env'.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {string} name
 | 
			
		||||
   * @return {Option}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  env(name) {
 | 
			
		||||
    this.envVar = name;
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Set the custom handler for processing CLI option arguments into option values.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {Function} [fn]
 | 
			
		||||
   * @return {Option}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  argParser(fn) {
 | 
			
		||||
    this.parseArg = fn;
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Whether the option is mandatory and must have a value after parsing.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {boolean} [mandatory=true]
 | 
			
		||||
   * @return {Option}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  makeOptionMandatory(mandatory = true) {
 | 
			
		||||
    this.mandatory = !!mandatory;
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Hide option in help.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {boolean} [hide=true]
 | 
			
		||||
   * @return {Option}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  hideHelp(hide = true) {
 | 
			
		||||
    this.hidden = !!hide;
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @api private
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  _concatValue(value, previous) {
 | 
			
		||||
    if (previous === this.defaultValue || !Array.isArray(previous)) {
 | 
			
		||||
      return [value];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return previous.concat(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Only allow option value to be one of choices.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {string[]} values
 | 
			
		||||
   * @return {Option}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  choices(values) {
 | 
			
		||||
    this.argChoices = values.slice();
 | 
			
		||||
    this.parseArg = (arg, previous) => {
 | 
			
		||||
      if (!this.argChoices.includes(arg)) {
 | 
			
		||||
        throw new InvalidArgumentError(`Allowed choices are ${this.argChoices.join(', ')}.`);
 | 
			
		||||
      }
 | 
			
		||||
      if (this.variadic) {
 | 
			
		||||
        return this._concatValue(arg, previous);
 | 
			
		||||
      }
 | 
			
		||||
      return arg;
 | 
			
		||||
    };
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Return option name.
 | 
			
		||||
   *
 | 
			
		||||
   * @return {string}
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  name() {
 | 
			
		||||
    if (this.long) {
 | 
			
		||||
      return this.long.replace(/^--/, '');
 | 
			
		||||
    }
 | 
			
		||||
    return this.short.replace(/^-/, '');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Return option name, in a camelcase format that can be used
 | 
			
		||||
   * as a object attribute key.
 | 
			
		||||
   *
 | 
			
		||||
   * @return {string}
 | 
			
		||||
   * @api private
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  attributeName() {
 | 
			
		||||
    return camelcase(this.name().replace(/^no-/, ''));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Check if `arg` matches the short or long flag.
 | 
			
		||||
   *
 | 
			
		||||
   * @param {string} arg
 | 
			
		||||
   * @return {boolean}
 | 
			
		||||
   * @api private
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  is(arg) {
 | 
			
		||||
    return this.short === arg || this.long === arg;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Return whether a boolean option.
 | 
			
		||||
   *
 | 
			
		||||
   * Options are one of boolean, negated, required argument, or optional argument.
 | 
			
		||||
   *
 | 
			
		||||
   * @return {boolean}
 | 
			
		||||
   * @api private
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  isBoolean() {
 | 
			
		||||
    return !this.required && !this.optional && !this.negate;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This class is to make it easier to work with dual options, without changing the existing
 | 
			
		||||
 * implementation. We support separate dual options for separate positive and negative options,
 | 
			
		||||
 * like `--build` and `--no-build`, which share a single option value. This works nicely for some
 | 
			
		||||
 * use cases, but is tricky for others where we want separate behaviours despite
 | 
			
		||||
 * the single shared option value.
 | 
			
		||||
 */
 | 
			
		||||
class DualOptions {
 | 
			
		||||
  /**
 | 
			
		||||
   * @param {Option[]} options
 | 
			
		||||
   */
 | 
			
		||||
  constructor(options) {
 | 
			
		||||
    this.positiveOptions = new Map();
 | 
			
		||||
    this.negativeOptions = new Map();
 | 
			
		||||
    this.dualOptions = new Set();
 | 
			
		||||
    options.forEach(option => {
 | 
			
		||||
      if (option.negate) {
 | 
			
		||||
        this.negativeOptions.set(option.attributeName(), option);
 | 
			
		||||
      } else {
 | 
			
		||||
        this.positiveOptions.set(option.attributeName(), option);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    this.negativeOptions.forEach((value, key) => {
 | 
			
		||||
      if (this.positiveOptions.has(key)) {
 | 
			
		||||
        this.dualOptions.add(key);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Did the value come from the option, and not from possible matching dual option?
 | 
			
		||||
   *
 | 
			
		||||
   * @param {any} value
 | 
			
		||||
   * @param {Option} option
 | 
			
		||||
   * @returns {boolean}
 | 
			
		||||
   */
 | 
			
		||||
  valueFromOption(value, option) {
 | 
			
		||||
    const optionKey = option.attributeName();
 | 
			
		||||
    if (!this.dualOptions.has(optionKey)) return true;
 | 
			
		||||
 | 
			
		||||
    // Use the value to deduce if (probably) came from the option.
 | 
			
		||||
    const preset = this.negativeOptions.get(optionKey).presetArg;
 | 
			
		||||
    const negativeValue = (preset !== undefined) ? preset : false;
 | 
			
		||||
    return option.negate === (negativeValue === value);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Convert string from kebab-case to camelCase.
 | 
			
		||||
 *
 | 
			
		||||
 * @param {string} str
 | 
			
		||||
 * @return {string}
 | 
			
		||||
 * @api private
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
function camelcase(str) {
 | 
			
		||||
  return str.split('-').reduce((str, word) => {
 | 
			
		||||
    return str + word[0].toUpperCase() + word.slice(1);
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Split the short and long flag out of something like '-m,--mixed <value>'
 | 
			
		||||
 *
 | 
			
		||||
 * @api private
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
function splitOptionFlags(flags) {
 | 
			
		||||
  let shortFlag;
 | 
			
		||||
  let longFlag;
 | 
			
		||||
  // Use original very loose parsing to maintain backwards compatibility for now,
 | 
			
		||||
  // which allowed for example unintended `-sw, --short-word` [sic].
 | 
			
		||||
  const flagParts = flags.split(/[ |,]+/);
 | 
			
		||||
  if (flagParts.length > 1 && !/^[[<]/.test(flagParts[1])) shortFlag = flagParts.shift();
 | 
			
		||||
  longFlag = flagParts.shift();
 | 
			
		||||
  // Add support for lone short flag without significantly changing parsing!
 | 
			
		||||
  if (!shortFlag && /^-[^-]$/.test(longFlag)) {
 | 
			
		||||
    shortFlag = longFlag;
 | 
			
		||||
    longFlag = undefined;
 | 
			
		||||
  }
 | 
			
		||||
  return { shortFlag, longFlag };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.Option = Option;
 | 
			
		||||
exports.splitOptionFlags = splitOptionFlags;
 | 
			
		||||
exports.DualOptions = DualOptions;
 | 
			
		||||
							
								
								
									
										100
									
								
								node_modules/commander/lib/suggestSimilar.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								node_modules/commander/lib/suggestSimilar.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
const maxDistance = 3;
 | 
			
		||||
 | 
			
		||||
function editDistance(a, b) {
 | 
			
		||||
  // https://en.wikipedia.org/wiki/Damerau–Levenshtein_distance
 | 
			
		||||
  // Calculating optimal string alignment distance, no substring is edited more than once.
 | 
			
		||||
  // (Simple implementation.)
 | 
			
		||||
 | 
			
		||||
  // Quick early exit, return worst case.
 | 
			
		||||
  if (Math.abs(a.length - b.length) > maxDistance) return Math.max(a.length, b.length);
 | 
			
		||||
 | 
			
		||||
  // distance between prefix substrings of a and b
 | 
			
		||||
  const d = [];
 | 
			
		||||
 | 
			
		||||
  // pure deletions turn a into empty string
 | 
			
		||||
  for (let i = 0; i <= a.length; i++) {
 | 
			
		||||
    d[i] = [i];
 | 
			
		||||
  }
 | 
			
		||||
  // pure insertions turn empty string into b
 | 
			
		||||
  for (let j = 0; j <= b.length; j++) {
 | 
			
		||||
    d[0][j] = j;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // fill matrix
 | 
			
		||||
  for (let j = 1; j <= b.length; j++) {
 | 
			
		||||
    for (let i = 1; i <= a.length; i++) {
 | 
			
		||||
      let cost = 1;
 | 
			
		||||
      if (a[i - 1] === b[j - 1]) {
 | 
			
		||||
        cost = 0;
 | 
			
		||||
      } else {
 | 
			
		||||
        cost = 1;
 | 
			
		||||
      }
 | 
			
		||||
      d[i][j] = Math.min(
 | 
			
		||||
        d[i - 1][j] + 1, // deletion
 | 
			
		||||
        d[i][j - 1] + 1, // insertion
 | 
			
		||||
        d[i - 1][j - 1] + cost // substitution
 | 
			
		||||
      );
 | 
			
		||||
      // transposition
 | 
			
		||||
      if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
 | 
			
		||||
        d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + 1);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return d[a.length][b.length];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Find close matches, restricted to same number of edits.
 | 
			
		||||
 *
 | 
			
		||||
 * @param {string} word
 | 
			
		||||
 * @param {string[]} candidates
 | 
			
		||||
 * @returns {string}
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
function suggestSimilar(word, candidates) {
 | 
			
		||||
  if (!candidates || candidates.length === 0) return '';
 | 
			
		||||
  // remove possible duplicates
 | 
			
		||||
  candidates = Array.from(new Set(candidates));
 | 
			
		||||
 | 
			
		||||
  const searchingOptions = word.startsWith('--');
 | 
			
		||||
  if (searchingOptions) {
 | 
			
		||||
    word = word.slice(2);
 | 
			
		||||
    candidates = candidates.map(candidate => candidate.slice(2));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let similar = [];
 | 
			
		||||
  let bestDistance = maxDistance;
 | 
			
		||||
  const minSimilarity = 0.4;
 | 
			
		||||
  candidates.forEach((candidate) => {
 | 
			
		||||
    if (candidate.length <= 1) return; // no one character guesses
 | 
			
		||||
 | 
			
		||||
    const distance = editDistance(word, candidate);
 | 
			
		||||
    const length = Math.max(word.length, candidate.length);
 | 
			
		||||
    const similarity = (length - distance) / length;
 | 
			
		||||
    if (similarity > minSimilarity) {
 | 
			
		||||
      if (distance < bestDistance) {
 | 
			
		||||
        // better edit distance, throw away previous worse matches
 | 
			
		||||
        bestDistance = distance;
 | 
			
		||||
        similar = [candidate];
 | 
			
		||||
      } else if (distance === bestDistance) {
 | 
			
		||||
        similar.push(candidate);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  similar.sort((a, b) => a.localeCompare(b));
 | 
			
		||||
  if (searchingOptions) {
 | 
			
		||||
    similar = similar.map(candidate => `--${candidate}`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (similar.length > 1) {
 | 
			
		||||
    return `\n(Did you mean one of ${similar.join(', ')}?)`;
 | 
			
		||||
  }
 | 
			
		||||
  if (similar.length === 1) {
 | 
			
		||||
    return `\n(Did you mean ${similar[0]}?)`;
 | 
			
		||||
  }
 | 
			
		||||
  return '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.suggestSimilar = suggestSimilar;
 | 
			
		||||
		Reference in New Issue
	
	Block a user