[
  {
    "path": ".editorconfig",
    "content": "# EditorConfig is awesome: http://EditorConfig.org\n\n# top-most EditorConfig file\nroot = true\n\n[*]\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 2\ntab_width = 2\n# trim_trailing_whitespace = true\n"
  },
  {
    "path": ".gitattributes",
    "content": "# disable line-ending changes (otherwise Windows developers with default settings from git install see Prettier wanting to fix every file)\n* -text\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [shadowspawn, abetomo, tj]\ntidelift: npm/commander\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\nThe text in these markdown comments is instructions that will not appear in the displayed pull request,\nand can be deleted.\n\nPlease submit pull requests against the develop branch.\n\nFollow the existing code style. Check the tests succeed, including format and lint.\n  npm run test\n  npm run check\n\nDon't update the CHANGELOG or package version number. That gets done by maintainers when preparing the release.\n\nCommander currently has zero production dependencies. That isn't a hard requirement, but is a simple story. Requests which \nadd a dependency are much less likely to be accepted, and we are likely to ask for alternative approaches to avoid the dependency.\n-->\n\n## Problem\n\n<!--\nWhat problem are you solving?\nWhat Issues does this relate to?\nShow the broken output if appropriate.\n-->\n\n## Solution\n\n<!--\nHow did you solve the problem? \nShow the fixed output if appropriate.\n\nThere are a lot of forms of documentation which could need updating for a change in functionality. It\nis ok if you want to show us the code to discuss before doing the extra work, and\nyou should say so in your comments so we focus on the concept first before talking about all the other pieces:\n\n- TypeScript typings\n- JSDoc documentation in code\n- tests\n- README\n- examples/\n-->\n\n## ChangeLog\n\n<!--\nOptional. Suggest a line for adding to the CHANGELOG to summarise your change.\n-->\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"npm\"\n    target-branch: \"develop\"\n    directory: \"/\"\n    schedule:\n      interval: \"monthly\"\n  - package-ecosystem: \"github-actions\"\n    target-branch: \"develop\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "content": "name: \"CodeQL\"\n\non:\n  push:\n    branches: [ master, develop ]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [ master, develop ]\n  schedule:\n    - cron: '27 5 * * 6'\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [ 'javascript' ]\n\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v6\n\n    # Initializes the CodeQL tools for scanning.\n    - name: Initialize CodeQL\n      uses: github/codeql-action/init@v4\n      with:\n        languages: ${{ matrix.language }}\n        # If you wish to specify custom queries, you can do so here or in a config file.\n        # By default, queries listed here will override any specified in a config file.\n        # Prefix the list here with \"+\" to use these queries and those in the config file.\n        # queries: ./path/to/local/query, your-org/your-repo/queries@main\n\n    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).\n    # If this step fails, then you should remove it and run the build manually (see below)\n    - name: Autobuild\n      uses: github/codeql-action/autobuild@v4\n\n    # ℹ️ Command-line programs to run using the OS shell.\n    # 📚 https://git.io/JvXDl\n\n    # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines\n    #    and modify them (or add more) to build your code if your project\n    #    uses a compiled language\n\n    #- run: |\n    #   make bootstrap\n    #   make release\n\n    - name: Perform CodeQL Analysis\n      uses: github/codeql-action/analyze@v4\n"
  },
  {
    "path": ".github/workflows/tests.yml",
    "content": "name: build\n\non: [push, pull_request]\n\npermissions:\n  contents: read\n\njobs:\n  test:\n    name: Test on node ${{ matrix.node-version }} and ${{ matrix.os }}\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        node-version: [20.x, 22.x, 24.x]\n        os: [ubuntu-latest, windows-latest, macos-latest]\n\n    steps:\n    - uses: actions/checkout@v6\n    - name: Use Node.js ${{ matrix.node-version }}\n      uses: actions/setup-node@v6\n      with:\n        cache: 'npm'\n        node-version: ${{ matrix.node-version }}\n    # Use separate run commands so command status handled correctly on Windows\n    - name: npm install\n      run: npm ci\n    - name: npm test\n      run: npm test\n    - name: npm run check\n      run: npm run check\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules\n*.sock\n.idea\n.vscode/\ncoverage/\n"
  },
  {
    "path": ".prettierignore",
    "content": "# exclude everything, and opt-in to types we want to format\n**.*\n# add the filetypes we want to format\n!**.js\n!**.mjs\n!**.cjs\n!**.ts\n!**.mts\n!**.cts\n!**.json\n"
  },
  {
    "path": ".prettierrc.js",
    "content": "const config = {\n  singleQuote: true,\n  overrides: [\n    {\n      files: ['tsconfig*.json'],\n      options: { parser: 'jsonc' },\n    },\n  ],\n};\n\nmodule.exports = config;\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\nand this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).\n\n<!-- markdownlint-disable MD024 -->\n<!-- markdownlint-disable MD004 -->\n\n## [14.0.3] (2026-01-31)\n\n### Added\n\n- Release Policy document ([#2462])\n  \n### Changes\n\n- old major versions now supported for 12 months instead of just previous major version, to give predictable end-of-life date ([#2462])\n- clarify typing for deprecated callback parameter to `.outputHelp()` ([#2427])\n- simple readability improvements to README ([#2465])\n  \n## [14.0.2] (2025-10-25)\n\n### Changed\n\n- improve negative number auto-detection test ([#2428])\n- update (dev) dependencies\n\n## [14.0.1] (2025-09-12)\n\n### Fixed\n\n- broken markdown link in README ([#2369])\n\n### Changed\n\n- improve code readability by using optional chaining ([#2394])\n- use more idiomatic code with object spread instead of `Object.assign()` ([#2395])\n- improve code readability using `string.endsWith()` instead of `string.slice()` ([#2396])\n- refactor `.parseOptions()` to process args array in-place ([#2409])\n- change private variadic support routines from `._concatValue()` to `._collectValue()` (change code from `array.concat()` to `array.push()`) ([#2410])\n- update (dev) dependencies\n\n## [14.0.0] (2025-05-18)\n\n### Added\n\n- support for groups of options and commands in the help using low-level `.helpGroup()` on `Option` and `Command`, and higher-level `.optionsGroup()` and `.commandsGroup()` which can be used in chaining way to specify group title for following options/commands ([#2328])\n- support for unescaped negative numbers as option-arguments and command-arguments ([#2339])\n- TypeScript: add `parseArg` property to `Argument` class ([#2359])\n\n### Fixed\n\n- remove bogus leading space in help when option has default value but not a description ([#2348])\n- `.configureOutput()` now makes copy of settings instead of modifying in-place, fixing side-effects ([#2350])\n\n### Changed\n\n- *Breaking:* Commander 14 requires Node.js v20 or higher\n- internal refactor of `Help` class adding `.formatItemList()` and `.groupItems()` methods ([#2328])\n\n## [13.1.0] (2025-01-21)\n\n### Added\n\n- support a pair of long option flags to allow a memorable shortened flag, like `.option('--ws, --workspace')` ([#2312])\n\n## [13.0.0] (2024-12-30)\n\n### Added\n\n- support multiple calls to `.parse()` with default settings ([#2299])\n- add `.saveStateBeforeParse()` and `.restoreStateBeforeParse()` for use by subclasses ([#2299])\n- style routines like `styleTitle()` to add color to help using `.configureHelp()` or Help subclass ([#2251])\n- color related support in `.configureOutput()` for `getOutHasColors()`, `getErrHasColors()`, and `stripColor()` ([#2251])\n- Help property for `minWidthToWrap` ([#2251])\n- Help methods for `displayWidth()`, `boxWrap()`, `preformatted()` et al ([#2251])\n\n### Changed\n\n- *Breaking*: excess command-arguments cause an error by default, see migration tips ([#2223])\n- *Breaking*: throw during Option construction for unsupported option flags, like multiple characters after single `-` ([#2270])\n  - note: support for dual long option flags added in Commander 13.1\n- *Breaking*: throw on multiple calls to `.parse()` if `storeOptionsAsProperties: true` ([#2299])\n- TypeScript: include implicit `this` in parameters for action handler callback ([#2197])\n\n### Deleted\n\n- *Breaking*: `Help.wrap()` refactored into `formatItem()` and `boxWrap()` ([#2251])\n\n### Migration Tips\n\n**Excess command-arguments**\n\nIt is now an error for the user to specify more command-arguments than are expected. (`allowExcessArguments` is now false by default.)\n\nOld code:\n\n```js\nprogram.option('-p, --port <number>', 'port number');\nprogram.action((options) => {\n  console.log(program.args);\n});\n```\n\nNow shows an error:\n\n```console\n$ node example.js a b c\nerror: too many arguments. Expected 0 arguments but got 3.\n```\n\nYou can declare the expected arguments. The help will then be more accurate too. Note that declaring\nnew arguments will change what is passed to the action handler.\n\n```js\nprogram.option('-p, --port <number>', 'port number');\nprogram.argument('[args...]', 'remote command and arguments'); // expecting zero or more arguments\nprogram.action((args, options) => {\n  console.log(args);\n});\n```\n\nOr you could suppress the error, useful for minimising changes in legacy code.\n\n```js\nprogram.option('-p, --port', 'port number');\nprogram.allowExcessArguments();\nprogram.action((options) => {\n  console.log(program.args);\n});\n```\n\n**Stricter option flag parsing**\n\nCommander now throws an error for option flag combinations that are not supported.\nIn particular, a short flag with multiple characters is now an error.\n\n```js\nprogram.option('-ws, --workspace'); // throws error\n```\n\nA short option has a single character:\n\n```js\nprogram.option('-w, --workspace');\n```\n\nOr from Commander 13.1 you can have an extra long flag instead of a short flag to allow a more memorable shortcut for the full name:\n\n```js\nprogram.option('--ws, --workspace');\n```\n\n## [13.0.0-0] (2024-12-07)\n\n(Released in 13.0.0)\n\n## [12.1.0] (2024-05-18)\n\n### Added\n\n- auto-detect special node flags `node --eval` and `node --print` when call `.parse()` with no arguments ([#2164])\n\n### Changed\n\n- prefix require of Node.js core modules with `node:` ([#2170])\n- format source files with Prettier ([#2180])\n- switch from StandardJS to directly calling ESLint for linting ([#2153])\n- extend security support for previous major version of Commander ([#2150])\n\n### Removed\n\n- removed unimplemented Option.fullDescription from TypeScript definition ([#2191])\n\n## [12.0.0] (2024-02-03)\n\n### Added\n\n- `.addHelpOption()` as another way of configuring built-in help option ([#2006])\n- `.helpCommand()` for configuring built-in help command ([#2087])\n\n### Fixed\n\n- *Breaking:* use non-zero exit code when spawned executable subcommand terminates due to a signal ([#2023])\n- *Breaking:* check `passThroughOptions` constraints when using `.addCommand` and throw if parent command does not have `.enablePositionalOptions()` enabled ([#1937])\n\n### Changed\n\n- *Breaking:* Commander 12 requires Node.js v18 or higher ([#2027])\n- *Breaking:* throw an error if add an option with a flag which is already in use ([#2055])\n- *Breaking:* throw an error if add a command with name or alias which is already in use ([#2059])\n- *Breaking:* throw error when calling `.storeOptionsAsProperties()` after setting an option value ([#1928])\n- replace non-standard JSDoc of `@api private` with documented `@private` ([#1949])\n- `.addHelpCommand()` now takes a Command (passing string or boolean still works as before but deprecated) ([#2087])\n- refactor internal implementation of built-in help option ([#2006])\n- refactor internal implementation of built-in help command ([#2087])\n\n### Deprecated\n\n- `.addHelpCommand()` passing string or boolean (use `.helpCommand()` or pass a Command) ([#2087])\n\n### Removed\n\n- *Breaking:* removed default export of a global Command instance from CommonJS (use the named `program` export instead) ([#2017])\n\n### Migration Tips\n\n**global program**\n\nIf you are using the [deprecated](./docs/deprecated.md#default-import-of-global-command-object) default import of the global Command object, you need to switch to using a named import (or create a new `Command`).\n\n```js\n// const program = require('commander');\nconst { program } = require('commander');\n```\n\n**option and command clashes**\n\nA couple of configuration problems now throw an error, which will pick up issues in existing programs:\n\n- adding an option which uses the same flag as a previous option\n- adding a command which uses the same name or alias as a previous command\n\n## [12.0.0-1] (2024-01-20)\n\n(Released in 12.0.0)\n\n## [12.0.0-0] (2023-11-11)\n\n(Released in 12.0.0)\n\n## [11.1.0] (2023-10-13)\n\n### Fixed\n\n- TypeScript: update `OptionValueSource` to allow any string, to match supported use of custom sources ([#1983])\n- TypeScript: add that `Command.version()` can also be used as getter ([#1982])\n- TypeScript: add null return type to `Commands.executableDir()`, for when not configured ([#1965])\n- subcommands with an executable handler and only a short help flag are now handled correctly by the parent's help command ([#1930])\n\n### Added\n\n- `registeredArguments` property on `Command` with the array of defined `Argument` (like `Command.options` for `Option`) ([#2010])\n- TypeScript declarations for Option properties: `envVar`, `presetArg` ([#2019])\n- TypeScript declarations for Argument properties: `argChoices`, `defaultValue`, `defaultValueDescription` ([#2019])\n- example file which shows how to configure help to display any custom usage in the list of subcommands ([#1896])\n\n### Changed\n\n- (developer) refactor TypeScript configs for multiple use-cases, and enable checks in JavaScript files in supporting editors ([#1969])\n\n### Deprecated\n\n- `Command._args` was private anyway, but now available as `registeredArguments` ([#2010])\n\n## [11.0.0] (2023-06-16)\n\n### Fixed\n\n- help command works when help option is disabled ([#1864])\n\n### Changed\n\n- leading and trailing spaces are now ignored by the .arguments() method ([#1874])\n- refine \"types\" exports for ESM to follow TypeScript guidelines ([#1886])\n- *Breaking:* Commander 11 requires Node.js v16 or higher\n\n## [10.0.1] (2023-04-15)\n\n### Added\n\n- improvements to documentation ([#1858], [#1859], [#1860])\n\n### Fixed\n\n- remove unused `Option.optionFlags` property from TypeScript definition ([#1844])\n\n### Changed\n\n- assume boolean option intended if caller passes string instead of hash to `.implies()` ([#1854])\n\n## [10.0.0] (2023-01-13)\n\n### Added\n\n- wrap command description in help ([#1804])\n\n### Changed\n\n- *Breaking:* Commander 10 requires Node.js v14 or higher\n\n## [9.5.0] (2023-01-07)\n\n### Added\n\n- `.getOptionValueSourceWithGlobals()` ([#1832])\n- `showGlobalOptions` for `.configureHelp{}` and `Help` ([#1828])\n\n## [9.4.1] (2022-09-30)\n\n### Fixed\n\n- `.setOptionValue()` now also clears option source ([#1795])\n- TypeScript: add `implied` to `OptionValueSource` for option values set by using `.implies()` ([#1794])\n- TypeScript : add `undefined` to return type of `.getOptionValueSource()` ([#1794])\n\n### Changed\n\n- additions to README\n\n## [9.4.0] (2022-07-15)\n\n### Added\n\n- `preSubcommand` hook called before direct subcommands ([#1763])\n\n### Fixed\n\n- export `InvalidOptionArgumentError` in esm ([#1756])\n\n### Changed\n\n- update dependencies ([#1767])\n\n## [9.3.0] (2022-05-28)\n\n### Added\n\n- `.summary()` for a short summary to use instead of description when listing subcommands in help ([#1726])\n- `Option.implies()` to set other option values when the option is specified ([#1724])\n- updated Chinese README with 9.x changes ([#1727])\n\n### Fixed\n\n- TypeScript: add `string[]` to `.options()` default value parameter type for use with variadic options ([#1721])\n\n### Deprecated\n\n- multi-character short option flag (e.g. `-ws`) ([#1718])\n\n## [9.2.0] (2022-04-15)\n\n### Added\n\n- conditional export of 'types' for upcoming TypeScript module resolution ([#1703])\n- example file showing two ways to add global options to subcommands ([#1708])\n\n### Fixed\n\n- detect option conflicts in parent commands of called subcommand ([#1710])\n\n### Changed\n\n- replace deprecated `String.prototype.substr` ([#1706])\n\n## [9.1.0] (2022-03-19)\n\n### Added\n\n- Option `.conflicts()` to set conflicting options which can not be specified together ([#1678])\n- (developer) CodeQL configuration for GitHub Actions ([#1698])\n\n## [9.0.0] (2022-01-28)\n\n### Added\n\n- simpler ECMAScript import ([#1589])\n- Option.preset() allows specifying value/arg for option when used without option-argument (especially optional, but also boolean option) ([#1652])\n- `.executableDir()` for custom search for subcommands ([#1571])\n- throw with helpful message if pass `Option` to `.option()` or `.requiredOption()` ([#1655])\n- .`error()` for generating errors from client code just like Commander generated errors, with support for  `.configureOutput()`, `.exitOverride()`, and `.showHelpAfterError()` ([#1675])\n- `.optsWithGlobals()` to return merged local and global options ([#1671])\n\n### Changed\n\n- *Breaking:* Commander 9 requires Node.js v12.20.0 or higher\n- update package-lock.json to lockfile@2 format ([#1659])\n- `showSuggestionAfterError` is now on by default ([#1657])\n- *Breaking:* default value specified for boolean option now always used as default value (see .preset() to match some previous behaviours) ([#1652])\n- default value for boolean option only shown in help if true/false ([#1652])\n- use command name as prefix for subcommand stand-alone executable name (with fallback to script name for backwards compatibility) ([#1571])\n- allow absolute path with `executableFile` ([#1571])\n- removed restriction that nested subcommands must specify `executableFile` ([#1571])\n- TypeScript: allow passing readonly string array to `.choices()` ([#1667])\n- TypeScript: allow passing readonly string array to `.parse()`, `.parseAsync()`, `.aliases()` ([#1669])\n\n### Fixed\n\n- option with optional argument not supplied on command line now works when option already has a value, whether from default value or from previous arguments ([#1652])\n\n### Removed\n\n- *Breaking:* removed internal fallback to `require.main.filename` when script not known from arguments passed to `.parse()` (can supply details using `.name()`, and `.executableDir()` or `executableFile`) ([#1571])\n\n## [9.0.0-1] (2022-01-15)\n\n(Released in 9.0.0)\n\n## [9.0.0-0] (2021-12-22)\n\n(Released in 9.0.0)\n\n## [8.3.0] (2021-10-22)\n\n### Added\n\n- `.getOptionValueSource()` and `.setOptionValueWithSource()`, where expected values for source are one of 'default', 'env', 'config', 'cli' ([#1613])\n\n### Deprecated\n\n- `.command('*')`, use default command instead ([#1612])\n- `on('command:*')`, use `.showSuggestionAfterError()` instead ([#1612])\n\n## [8.2.0] (2021-09-10)\n\n### Added\n\n- `.showSuggestionAfterError()` to show suggestions after unknown command or unknown option ([#1590])\n- add `Option` support for values from environment variables using `.env()` ([#1587])\n\n### Changed\n\n- show error for unknown global option before subcommand (rather than just help) ([#1590])\n\n### Removed\n\n- TypeScript declaration of unimplemented `Option` method `argumentRejected`\n\n## [8.1.0] (2021-07-27)\n\n### Added\n\n- `.copyInheritedSettings()` ([#1557])\n- update Chinese translations of documentation for Commander v8 ([#1570])\n- `Argument` methods for `.argRequired()` and `.argOptional()` ([#1567])\n\n## [8.0.0] (2021-06-25)\n\n### Added\n\n- `.argument(name, description)` for adding command-arguments ([#1490])\n  - supports default value for optional command-arguments ([#1508])\n  - supports custom processing function ([#1508])\n- `.createArgument()` factory method ([#1497])\n- `.addArgument()` ([#1490])\n- `Argument` supports `.choices()` ([#1525])\n- `.showHelpAfterError()` to display full help or a custom message after an error ([#1534])\n- `.hook()` with support for `'preAction'` and `'postAction'` callbacks ([#1514])\n- client typing of `.opts()` return type using TypeScript generics ([#1539])\n- the number of command-arguments is checked for programs without an action handler ([#1502])\n- `.getOptionValue()` and `.setOptionValue()` ([#1521])\n\n### Changed\n\n- refactor and simplify TypeScript declarations (with no default export) ([#1520])\n- `.parseAsync()` is now declared as `async` ([#1513])\n- *Breaking:* `Help` method `.visibleArguments()` returns array of `Argument` ([#1490])\n- *Breaking:* Commander 8 requires Node.js 12 or higher ([#1500])\n- *Breaking:* `CommanderError` code `commander.invalidOptionArgument` renamed `commander.invalidArgument` ([#1508])\n- *Breaking:* TypeScript declaration for `.addTextHelp()` callback no longer allows result of `undefined`, now just `string` ([#1516])\n- refactor `index.tab` into a file per class ([#1522])\n- remove help suggestion from \"unknown command\" error message (see `.showHelpAfterError()`) ([#1534])\n- `Command` property `.arg` initialised to empty array (was previously undefined) ([#1529])\n- update dependencies\n\n### Deprecated\n\n- second parameter of `cmd.description(desc, argDescriptions)` for adding argument descriptions ([#1490])\n  - (use new `.argument(name, description)` instead)\n- `InvalidOptionArgumentError` (replaced by `InvalidArgumentError`) ([#1508])\n\n### Removed\n\n- *Breaking:* TypeScript declaration for default export of global `Command` object ([#1520])\n  - (still available as named `program` export)\n\n### Migration Tips\n\nIf you have a simple program without an action handler, you will now get an error if\nthere are missing command-arguments.\n\n```js\nprogram\n  .option('-d, --debug')\n  .arguments('<file>');\nprogram.parse();\n```\n\n```sh\n$ node trivial.js \nerror: missing required argument 'file'\n```\n\nIf you want to show the help in this situation, you could check the arguments before parsing:\n\n```js\nif (process.argv.length === 2)\n  program.help();\nprogram.parse();\n```\n\nOr, you might choose to show the help after any user error:\n\n```js\nprogram.showHelpAfterError();\n```\n\n## [8.0.0-2] (2021-06-06)\n\n(Released in 8.0.0)\n\n## [8.0.0-1] (2021-05-30)\n\n(Released in 8.0.0)\n\n## [8.0.0-0] (2021-05-23)\n\n(Released in 8.0.0)\n\n## [7.2.0] (2021-03-22)\n\n### Added\n\n- TypeScript typing for `parent` property on `Command` ([#1475])\n- TypeScript typing for `.attributeName()` on `Option` ([#1483])\n- support information in package ([#1477])\n\n### Changed\n\n- improvements to error messages, README, and tests\n- update dependencies\n\n## [7.1.0] (2021-02-15)\n\n### Added\n\n- support for named imports from ECMAScript modules ([#1440])\n- add `.cjs` to list of expected script file extensions ([#1449])\n- allow using option choices and variadic together ([#1454])\n\n### Fixed\n\n- replace use of deprecated `process.mainModule` ([#1448])\n- regression for legacy `command('*')` and call when command line includes options ([#1464])\n- regression for `on('command:*', ...)` and call when command line includes unknown options ([#1464])\n- display best error for combination of unknown command and unknown option (i.e. unknown command) ([#1464])\n\n### Changed\n\n- make TypeScript typings tests stricter ([#1453])\n- improvements to README and tests\n\n## [7.0.0] (2021-01-15)\n\n### Added\n\n- `.enablePositionalOptions()` to let program and subcommand reuse same option ([#1427])\n- `.passThroughOptions()` to pass options through to other programs without needing `--` ([#1427])\n- `.allowExcessArguments(false)` to show an error message if there are too many command-arguments on command line for the action handler ([#1409])\n- `.configureOutput()` to modify use of stdout and stderr or customise display of errors ([#1387])\n- use `.addHelpText()` to add text before or after the built-in help, for just current command or also for all subcommands ([#1296])\n- enhance Option class ([#1331])\n  - allow hiding options from help\n  - allow restricting option arguments to a list of choices\n  - allow setting how default value is shown in help\n- `.createOption()` to support subclassing of automatically created options (like `.createCommand()`) ([#1380])\n- refactor the code generating the help into a separate public Help class ([#1365])\n  - support sorting subcommands and options in help\n  - support specifying wrap width (columns)\n  - allow subclassing Help class\n  - allow configuring Help class without subclassing\n\n### Changed\n\n- *Breaking:* options are stored safely by default, not as properties on the command ([#1409])\n  - this especially affects accessing options on program, use `program.opts()`\n  - revert behaviour with `.storeOptionsAsProperties()`\n- *Breaking:* action handlers are passed options and command separately ([#1409])\n- deprecated callback parameter to `.help()` and `.outputHelp()` (removed from README) ([#1296])\n- *Breaking:* errors now displayed using `process.stderr.write()` instead of `console.error()`\n- deprecate `.on('--help')` (removed from README) ([#1296])\n- initialise the command description to empty string (previously undefined) ([#1365])\n- document and annotate deprecated routines ([#1349])\n\n### Fixed\n\n- wrapping bugs in help ([#1365])\n  - first line of command description was wrapping two characters early\n  - pad width calculation was not including help option and help command\n  - pad width calculation was including hidden options and commands\n- improve backwards compatibility for custom command event listeners ([#1403])\n  \n### Deleted\n\n- *Breaking:* `.passCommandToAction()` ([#1409])\n  - no longer needed as action handler is passed options and command\n- *Breaking:* \"extra arguments\" parameter to action handler ([#1409])\n  - if being used to detect excess arguments, there is now an error available by setting `.allowExcessArguments(false)`\n\n### Migration Tips\n\nThe biggest change is the parsed option values. Previously the options were stored by default as properties on the command object, and now the options are stored separately.\n\nIf you wish to restore the old behaviour and get running quickly you can call `.storeOptionsAsProperties()`.\nTo allow you to move to the new code patterns incrementally, the action handler will be passed the command _twice_,\nto match the new \"options\" and \"command\" parameters (see below).\n\n**program options**\n\nUse the `.opts()` method to access the options. This is available on any command but is used most with the program.\n\n```js\nprogram.option('-d, --debug');\nprogram.parse();\n// Old code before Commander 7\nif (program.debug) console.log(`Program name is ${program.name()}`);\n```\n\n```js\n// New code\nconst options = program.opts();\nif (options.debug) console.log(`Program name is ${program.name()}`);\n```\n\n**action handler**\n\nThe action handler gets passed a parameter for each command-argument you declared. Previously by default the next parameter was the command object with the options as properties. Now the next two parameters are instead the options and the command. If you\nonly accessed the options there may be no code changes required.\n\n```js\nprogram\n  .command('compress <filename>')\n  .option('-t, --trace')\n  // Old code before Commander 7\n  .action((filename, cmd) => {\n    if (cmd.trace) console.log(`Command name is ${cmd.name()}`);\n  });\n```\n\n```js\n  // New code\n  .action((filename, options, command) => {\n    if (options.trace) console.log(`Command name is ${command.name()}`);\n  });\n```\n\nIf you already set `.storeOptionsAsProperties(false)` you may still need to adjust your code.\n\n```js\nprogram\n  .command('compress <filename>')\n  .storeOptionsAsProperties(false)\n  .option('-t, --trace')\n  // Old code before Commander 7\n  .action((filename, command) => {\n    if (command.opts().trace) console.log(`Command name is ${command.name()}`);\n  });\n```\n\n```js\n   // New code\n   .action((filename, options, command) => {\n      if (command.opts().trace) console.log(`Command name is ${command.name()}`);\n   });\n```\n\n## [7.0.0-2] (2020-12-14)\n\n(Released in 7.0.0)\n\n## [7.0.0-1] (2020-11-21)\n\n(Released in 7.0.0)\n\n## [7.0.0-0] (2020-10-25)\n\n(Released in 7.0.0)\n\n## [6.2.1] (2020-12-13)\n\n### Fixed\n\n- some tests failed if directory path included a space ([#1390])\n\n## [6.2.0] (2020-10-25)\n\n### Added\n\n- added 'tsx' file extension for stand-alone executable subcommands ([#1368])\n- documented second parameter to `.description()` to describe command arguments ([#1353])\n- documentation of special cases with options taking varying numbers of option-arguments ([#1332])\n- documentation for terminology ([#1361])\n  \n### Fixed\n\n- add missing TypeScript definition for `.addHelpCommand()' ([#1375])\n- removed blank line after \"Arguments:\" in help, to match \"Options:\" and \"Commands:\" ([#1360])\n\n### Changed\n\n- update dependencies\n\n## [6.1.0] (2020-08-28)\n\n### Added\n\n- include URL to relevant section of README for error for potential conflict between Command properties and option values ([#1306])\n- `.combineFlagAndOptionalValue(false)` to ease upgrade path from older versions of Commander ([#1326])\n- allow disabling the built-in help option using `.helpOption(false)` ([#1325])\n- allow just some arguments in `argumentDescription` to `.description()` ([#1323])\n\n### Changed\n\n- tidy async test and remove lint override ([#1312])\n\n### Fixed\n\n- executable subcommand launching when script path not known ([#1322])\n\n## [6.0.0] (2020-07-21)\n\n### Added\n\n- add support for variadic options ([#1250])\n- allow options to be added with just a short flag ([#1256])\n  - *Breaking* the option property has same case as flag. e.g. flag `-n` accessed as `opts().n` (previously uppercase)\n- *Breaking* throw an error if there might be a clash between option name and a Command property, with advice on how to resolve ([#1275])\n\n### Fixed\n\n- Options which contain -no- in the middle of the option flag should not be treated as negatable. ([#1301])\n\n## [6.0.0-0] (2020-06-20)\n\n(Released in 6.0.0)\n\n## [5.1.0] (2020-04-25)\n\n### Added\n\n- support for multiple command aliases, the first of which is shown in the auto-generated help ([#531], [#1236])\n- configuration support in `addCommand()` for `hidden` and `isDefault` ([#1232])\n\n### Fixed\n\n- omit masked help flags from the displayed help ([#645], [#1247])\n- remove old short help flag when change help flags using `helpOption` ([#1248])\n\n### Changed\n\n- remove use of `arguments` to improve auto-generated help in editors ([#1235])\n- rename `.command()` configuration `noHelp` to `hidden` (but not remove old support) ([#1232])\n- improvements to documentation\n- update dependencies\n- update tested versions of node\n- eliminate lint errors in TypeScript ([#1208])\n\n## [5.0.0] (2020-03-14)\n\n### Added\n\n* support for nested commands with action-handlers ([#1] [#764] [#1149])\n* `.addCommand()` for adding a separately configured command ([#764] [#1149])\n* allow a non-executable to be set as the default command ([#742] [#1149])\n* implicit help command when there are subcommands (previously only if executables) ([#1149])\n* customise implicit help command with `.addHelpCommand()` ([#1149])\n* display error message for unknown subcommand, by default ([#432] [#1088] [#1149])\n* display help for missing subcommand, by default ([#1088] [#1149])\n* combined short options as single argument may include boolean flags and value flag and value (e.g. `-a -b -p 80` can be written as `-abp80`) ([#1145])\n* `.parseOption()` includes short flag and long flag expansions ([#1145])\n* `.helpInformation()` returns help text as a string, previously a private routine ([#1169])\n* `.parse()` implicitly uses `process.argv` if arguments not specified ([#1172])\n* optionally specify where `.parse()` arguments \"from\", if not following node conventions ([#512] [#1172])\n* suggest help option along with unknown command error ([#1179])\n* TypeScript definition for `commands` property of `Command` ([#1184])\n* export `program` property ([#1195])\n* `createCommand` factory method to simplify subclassing ([#1191])\n\n### Fixed\n\n* preserve argument order in subcommands ([#508] [#962] [#1138])\n* do not emit `command:*` for executable subcommands ([#809] [#1149])\n* action handler called whether or not there are non-option arguments ([#1062] [#1149])\n* combining option short flag and value in single argument now works for subcommands ([#1145])\n* only add implicit help command when it will not conflict with other uses of argument ([#1153] [#1149])\n* implicit help command works with command aliases ([#948] [#1149])\n* options are validated whether or not there is an action handler ([#1149])\n\n### Changed\n\n* *Breaking* `.args` contains command arguments with just recognised options removed ([#1032] [#1138])\n* *Breaking* display error if required argument for command is missing ([#995] [#1149])\n* tighten TypeScript definition of custom option processing function passed to `.option()` ([#1119])\n* *Breaking* `.allowUnknownOption()` ([#802] [#1138])\n  * unknown options included in arguments passed to command action handler\n  * unknown options included in `.args`\n* only recognised option short flags and long flags are expanded (e.g. `-ab` or `--foo=bar`) ([#1145])\n* *Breaking* `.parseOptions()` ([#1138])\n  * `args` in returned result renamed `operands` and does not include anything after first unknown option\n  * `unknown` in returned result has arguments after first unknown option including operands, not just options and values\n* *Breaking* `.on('command:*', callback)` and other command events passed (changed) results from `.parseOptions`, i.e. operands and unknown  ([#1138])\n* refactor Option from prototype to class ([#1133])\n* refactor Command from prototype to class ([#1159])\n* changes to error handling ([#1165])\n  * throw for author error, not just display message\n  * preflight for variadic error\n  * add tips to missing subcommand executable\n* TypeScript fluent return types changed to be more subclass friendly, return `this` rather than `Command` ([#1180])\n* `.parseAsync` returns `Promise<this>` to be consistent with `.parse()` ([#1180])\n* update dependencies\n\n### Removed\n\n* removed EventEmitter from TypeScript definition for Command, eliminating implicit peer dependency on `@types/node` ([#1146])\n* removed private function `normalize` (the functionality has been integrated into `parseOptions`) ([#1145])\n* `parseExpectedArgs` is now private ([#1149])\n\n### Migration Tips\n\nIf you use `.on('command:*')` or more complicated tests to detect an unrecognised subcommand, you may be able to delete the code and rely on the default behaviour.\n\nIf you use `program.args` or more complicated tests to detect a missing subcommand, you may be able to delete the code and rely on the default behaviour.\n\nIf you use `.command('*')` to add a default command, you may be be able to switch to `isDefault:true` with a named command.\n\nIf you want to continue combining short options with optional values as though they were boolean flags, set `combineFlagAndOptionalValue(false)`\nto expand `-fb` to `-f -b` rather than `-f b`.\n\n## [5.0.0-4] (2020-03-03)\n\n(Released in 5.0.0)\n\n## [5.0.0-3] (2020-02-20)\n\n(Released in 5.0.0)\n\n## [5.0.0-2] (2020-02-10)\n\n(Released in 5.0.0)\n\n## [5.0.0-1] (2020-02-08)\n\n(Released in 5.0.0)\n\n## [5.0.0-0] (2020-02-02)\n\n(Released in 5.0.0)\n\n## [4.1.1] (2020-02-02)\n\n### Fixed\n\n* TypeScript definition for `.action()` should include Promise for async ([#1157])\n\n## [4.1.0] (2020-01-06)\n\n### Added\n\n* two routines to change how option values are handled, and eliminate name clashes with command properties ([#933] [#1102])\n  * see storeOptionsAsProperties and passCommandToAction in README\n* `.parseAsync` to use instead of `.parse` if supply async action handlers ([#806] [#1118])\n\n### Fixed\n\n* Remove trailing blanks from wrapped help text ([#1096])\n\n### Changed\n\n* update dependencies\n* extend security coverage for Commander 2.x to 2020-02-03\n* improvements to README\n* improvements to TypeScript definition documentation\n* move old versions out of main CHANGELOG\n* removed explicit use of `ts-node` in tests\n\n## [4.0.1] (2019-11-12)\n\n### Fixed\n\n* display help when requested, even if there are missing required options ([#1091])\n\n## [4.0.0] (2019-11-02)\n\n### Added\n\n* automatically wrap and indent help descriptions for options and commands ([#1051])\n* `.exitOverride()` allows override of calls to `process.exit` for additional error handling and to keep program running ([#1040])\n* support for declaring required options with `.requiredOptions()` ([#1071])\n* GitHub Actions support ([#1027])\n* translation links in README\n\n### Changed\n\n* dev: switch tests from Sinon+Should to Jest with major rewrite of tests ([#1035])\n* call default subcommand even when there are unknown options ([#1047])\n* *Breaking* Commander is only officially supported on Node 8 and above, and requires Node 6 ([#1053])\n\n### Fixed\n\n* *Breaking* keep command object out of program.args when action handler called ([#1048])\n  * also, action handler now passed array of unknown arguments\n* complain about unknown options when program argument supplied and action handler ([#1049])\n  * this changes parameters to `command:*` event to include unknown arguments\n* removed deprecated `customFds` option from call to `child_process.spawn` ([#1052])\n* rework TypeScript declarations to bring all types into imported namespace ([#1081])\n\n### Migration Tips\n\n#### Testing for no arguments\n\nIf you were previously using code like:\n\n```js\nif (!program.args.length) ...\n```\n\na partial replacement is:\n\n```js\nif (program.rawArgs.length < 3) ...\n```\n\n## [4.0.0-1] Prerelease (2019-10-08)\n\n(Released in 4.0.0)\n\n## [4.0.0-0] Prerelease (2019-10-01)\n\n(Released in 4.0.0)\n\n## [3.0.2] (2019-09-27)\n\n<!-- markdownlint-disable MD024 -->\n\n### Fixed\n\n* Improve tracking of executable subcommands.\n\n### Changed\n\n* update development dependencies\n\n## [3.0.1] (2019-08-30)\n\n### Added\n\n* .name and .usage to README ([#1010])\n* Table of Contents to README ([#1010])\n* TypeScript definition for `executableFile` in CommandOptions ([#1028])\n\n### Changed\n\n* consistently use `const` rather than `var` in README ([#1026])\n\n### Fixed\n\n* help for sub commands with custom executableFile ([#1018])\n\n## [3.0.0] / 2019-08-08\n\n* Add option to specify executable file name ([#999])\n  * e.g. `.command('clone', 'clone description', { executableFile: 'myClone' })`\n* Change docs for `.command` to contrast action handler vs git-style executable. ([#938] [#990])\n* **Breaking** Change TypeScript to use overloaded function for `.command`. ([#938] [#990])\n* Change to use straight quotes around strings in error messages (like 'this' instead of `this') ([#915])\n* Add TypeScript \"reference types\" for node ([#974])\n* Add support for hyphen as an option argument in subcommands ([#697])\n* Add support for a short option flag and its value to be concatenated for action handler subcommands ([#599])\n  * e.g. `-p 80` can also be supplied as `-p80`\n* Add executable arguments to spawn in win32, for git-style executables ([#611])\n  * e.g. `node --harmony myCommand.js clone`\n* Add parent command as prefix of subcommand in help ([#980])\n* Add optional custom description to `.version` ([#963])\n  * e.g. `program.version('0.0.1', '-v, --vers', 'output the current version')`\n* Add `.helpOption(flags, description)` routine to customise help flags and description ([#963])\n  * e.g. `.helpOption('-e, --HELP', 'read more information')`\n* Fix behavior of --no-* options ([#795])\n  * can now define both `--foo` and `--no-foo`\n  * **Breaking** custom event listeners: `--no-foo` on cli now emits `option:no-foo` (previously `option:foo`)\n  * **Breaking** default value: defining `--no-foo` after defining `--foo` leaves the default value unchanged (previously set it to false)\n  * allow boolean default value, such as from environment ([#987])\n* Increment inspector port for spawned subcommands ([#991])\n  * e.g. `node --inspect myCommand.js clone`\n\n### Migration Tips\n\nThe custom event for a negated option like `--no-foo` is `option:no-foo` (previously `option:foo`).\n\n```js\nprogram\n  .option('--no-foo')\n  .on('option:no-foo', () => {\n    console.log('removing foo');\n  });\n```\n\nWhen using TypeScript, adding a command does not allow an explicit `undefined` for an unwanted executable description (e.g\nfor a command with an action handler).\n\n```js\nprogram\n  .command('action1', undefined, { noHelp: true }) // No longer valid\n  .command('action2', { noHelp: true }) // Correct\n```\n\n## 3.0.0-0 Prerelease / 2019-07-28\n\n(Released as 3.0.0)\n\n## [2.20.1] (2019-09-29)\n\n### Fixed\n\n* Improve tracking of executable subcommands.\n\n### Changed\n\n* update development dependencies\n\n## 2.20.0 / 2019-04-02\n\n* fix: resolve symbolic links completely when hunting for subcommands (#935)\n* Update index.d.ts (#930)\n* Update Readme.md (#924)\n* Remove --save option as it isn't required anymore (#918)\n* Add link to the license file (#900)\n* Added example of receiving args from options (#858)\n* Added missing semicolon (#882)\n* Add extension to .eslintrc (#876)\n\n## 2.19.0 / 2018-10-02\n\n* Removed newline after Options and Commands headers (#864)\n* Bugfix - Error output (#862)\n* Fix to change default value to string (#856)\n\n## 2.18.0 / 2018-09-07\n\n* Standardize help output (#853)\n* chmod 644 travis.yml (#851)\n* add support for execute typescript subcommand via ts-node (#849)\n\n## 2.17.1 / 2018-08-07\n\n* Fix bug in command emit (#844)\n\n## 2.17.0 / 2018-08-03\n\n* fixed newline output after help information (#833)\n* Fix to emit the action even without command (#778)\n* npm update (#823)\n\n## 2.16.0 / 2018-06-29\n\n* Remove Makefile and `test/run` (#821)\n* Make 'npm test' run on Windows (#820)\n* Add badge to display install size (#807)\n* chore: cache node_modules (#814)\n* chore: remove Node.js 4 (EOL), add Node.js 10 (#813)\n* fixed typo in readme (#812)\n* Fix types (#804)\n* Update eslint to resolve vulnerabilities in lodash (#799)\n* updated readme with custom event listeners. (#791)\n* fix tests (#794)\n\n## 2.15.0 / 2018-03-07\n\n* Update downloads badge to point to graph of downloads over time instead of duplicating link to npm\n* Arguments description\n\n## 2.14.1 / 2018-02-07\n\n* Fix typing of help function\n\n## 2.14.0 / 2018-02-05\n\n* only register the option:version event once\n* Fixes issue #727: Passing empty string for option on command is set to undefined\n* enable eqeqeq rule\n* resolves #754 add linter configuration to project\n* resolves #560 respect custom name for version option\n* document how to override the version flag\n* document using options per command\n\n## 2.13.0 / 2018-01-09\n\n* Do not print default for --no-\n* remove trailing spaces in command help\n* Update CI's Node.js to LTS and latest version\n* typedefs: Command and Option types added to commander namespace\n\n## 2.12.2 / 2017-11-28\n\n* fix: typings are not shipped\n\n## 2.12.1 / 2017-11-23\n\n* Move @types/node to dev dependency\n\n## 2.12.0 / 2017-11-22\n\n* add attributeName() method to Option objects\n* Documentation updated for options with --no prefix\n* typings: `outputHelp` takes a string as the first parameter\n* typings: use overloads\n* feat(typings): update to match js api\n* Print default value in option help\n* Fix translation error\n* Fail when using same command and alias (#491)\n* feat(typings): add help callback\n* fix bug when description is add after command with options (#662)\n* Format js code\n* Rename History.md to CHANGELOG.md (#668)\n* feat(typings): add typings to support TypeScript (#646)\n* use current node\n\n## 2.11.0 / 2017-07-03\n\n* Fix help section order and padding (#652)\n* feature: support for signals to subcommands (#632)\n* Fixed #37, --help should not display first (#447)\n* Fix translation errors. (#570)\n* Add package-lock.json\n* Remove engines\n* Upgrade package version\n* Prefix events to prevent conflicts between commands and options (#494)\n* Removing dependency on graceful-readlink\n* Support setting name in #name function and make it chainable\n* Add .vscode directory to .gitignore (Visual Studio Code metadata)\n* Updated link to ruby commander in readme files\n\n## 2.10.0 / 2017-06-19\n\n* Update .travis.yml. drop support for older node.js versions.\n* Fix require arguments in README.md\n* On SemVer you do not start from 0.0.1\n* Add missing semi colon in readme\n* Add save param to npm install\n* node v6 travis test\n* Update Readme_zh-CN.md\n* Allow literal '--' to be passed-through as an argument\n* Test subcommand alias help\n* link build badge to master branch\n* Support the alias of Git style sub-command\n* added keyword commander for better search result on npm\n* Fix Sub-Subcommands\n* test node.js stable\n* Fixes TypeError when a command has an option called `--description`\n* Update README.md to make it beginner friendly and elaborate on the difference between angled and square brackets.\n* Add chinese Readme file\n\n## 2.9.0 / 2015-10-13\n\n* Add option `isDefault` to set default subcommand #415 @Qix-\n* Add callback to allow filtering or post-processing of help text #434 @djulien\n* Fix `undefined` text in help information close #414 #416 @zhiyelee\n\n## 2.8.1 / 2015-04-22\n\n* Back out `support multiline description` Close #396 #397\n\n## 2.8.0 / 2015-04-07\n\n* Add `process.execArg` support, execution args like `--harmony` will be passed to sub-commands #387 @DigitalIO @zhiyelee\n* Fix bug in Git-style sub-commands #372 @zhiyelee\n* Allow commands to be hidden from help #383 @tonylukasavage\n* When git-style sub-commands are in use, yet none are called, display help #382 @claylo\n* Add ability to specify arguments syntax for top-level command #258 @rrthomas\n* Support multiline descriptions #208 @zxqfox\n\n## 2.7.1 / 2015-03-11\n\n* Revert #347 (fix collisions when option and first arg have same name) which causes a bug in #367.\n\n## 2.7.0 / 2015-03-09\n\n* Fix git-style bug when installed globally. Close #335 #349 @zhiyelee\n* Fix collisions when option and first arg have same name. Close #346 #347 @tonylukasavage\n* Add support for camelCase on `opts()`. Close #353  @nkzawa\n* Add node.js 0.12 and io.js to travis.yml\n* Allow RegEx options. #337 @palanik\n* Fixes exit code when sub-command failing.  Close #260 #332 @pirelenito\n* git-style `bin` files in $PATH make sense. Close #196 #327  @zhiyelee\n\n## 2.6.0 / 2014-12-30\n\n* added `Command#allowUnknownOption` method. Close #138 #318 @doozr @zhiyelee\n* Add application description to the help msg. Close #112 @dalssoft\n\n## 2.5.1 / 2014-12-15\n\n* fixed two bugs incurred by variadic arguments. Close #291 @Quentin01 #302 @zhiyelee\n\n## 2.5.0 / 2014-10-24\n\n* add support for variadic arguments. Closes #277 @whitlockjc\n\n## 2.4.0 / 2014-10-17\n\n* fixed a bug on executing the coercion function of subcommands option. Closes #270\n* added `Command.prototype.name` to retrieve command name. Closes #264 #266 @tonylukasavage\n* added `Command.prototype.opts` to retrieve all the options as a simple object of key-value pairs. Closes #262 @tonylukasavage\n* fixed a bug on subcommand name. Closes #248 @jonathandelgado\n* fixed function normalize doesn’t honor option terminator. Closes #216 @abbr\n\n## 2.3.0 / 2014-07-16\n\n* add command alias'. Closes PR #210\n* fix: Typos. Closes #99\n* fix: Unused fs module. Closes #217\n\n## 2.2.0 / 2014-03-29\n\n* add passing of previous option value\n* fix: support subcommands on windows. Closes #142\n* Now the defaultValue passed as the second argument of the coercion function.\n\n## 2.1.0 / 2013-11-21\n\n* add: allow cflag style option params, unit test, fixes #174\n\n## 2.0.0 / 2013-07-18\n\n* remove input methods (.prompt, .confirm, etc)\n\n## 0.6.1 / 2012-06-01\n\n* Added: append (yes or no) on confirmation\n* Added: allow node.js v0.7.x\n\n## 0.6.0 / 2012-04-10\n\n* Added `.prompt(obj, callback)` support. Closes #49\n* Added default support to .choose(). Closes #41\n* Fixed the choice example\n\n## 0.5.1 / 2011-12-20\n\n* Fixed `password()` for recent nodes. Closes #36\n\n## 0.5.0 / 2011-12-04\n\n* Added sub-command option support [itay]\n\n## 0.4.3 / 2011-12-04\n\n* Fixed custom help ordering. Closes #32\n\n## 0.4.2 / 2011-11-24\n\n* Added travis support\n* Fixed: line-buffered input automatically trimmed. Closes #31\n\n## 0.4.1 / 2011-11-18\n\n* Removed listening for \"close\" on --help\n\n## 0.4.0 / 2011-11-15\n\n* Added support for `--`. Closes #24\n\n## 0.3.3 / 2011-11-14\n\n* Fixed: wait for close event when writing help info [Jerry Hamlet]\n\n## 0.3.2 / 2011-11-01\n\n* Fixed long flag definitions with values [felixge]\n\n## 0.3.1 / 2011-10-31\n\n* Changed `--version` short flag to `-V` from `-v`\n* Changed `.version()` so it's configurable [felixge]\n\n## 0.3.0 / 2011-10-31\n\n* Added support for long flags only. Closes #18\n\n## 0.2.1 / 2011-10-24\n\n* \"node\": \">= 0.4.x < 0.7.0\". Closes #20\n\n## 0.2.0 / 2011-09-26\n\n* Allow for defaults that are not just boolean. Default reassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs]\n\n## 0.1.0 / 2011-08-24\n\n* Added support for custom `--help` output\n\n## 0.0.5 / 2011-08-18\n\n* Changed: when the user enters nothing prompt for password again\n* Fixed issue with passwords beginning with numbers [NuckChorris]\n\n## 0.0.4 / 2011-08-15\n\n* Fixed `Commander#args`\n\n## 0.0.3 / 2011-08-15\n\n* Added default option value support\n\n## 0.0.2 / 2011-08-15\n\n* Added mask support to `Command#password(str[, mask], fn)`\n* Added `Command#password(str, fn)`\n\n## 0.0.1 / 2010-01-03\n\n* Initial release\n\n<!-- markdown reference links -->\n\n[#948]: https://github.com/tj/commander.js/issues/948\n[#1032]: https://github.com/tj/commander.js/issues/1032\n[#1250]: https://github.com/tj/commander.js/pull/1250\n[#1256]: https://github.com/tj/commander.js/pull/1256\n[#1275]: https://github.com/tj/commander.js/pull/1275\n[#1296]: https://github.com/tj/commander.js/pull/1296\n[#1301]: https://github.com/tj/commander.js/issues/1301\n[#1306]: https://github.com/tj/commander.js/pull/1306\n[#1312]: https://github.com/tj/commander.js/pull/1312\n[#1322]: https://github.com/tj/commander.js/pull/1322\n[#1323]: https://github.com/tj/commander.js/pull/1323\n[#1325]: https://github.com/tj/commander.js/pull/1325\n[#1326]: https://github.com/tj/commander.js/pull/1326\n[#1331]: https://github.com/tj/commander.js/pull/1331\n[#1332]: https://github.com/tj/commander.js/pull/1332\n[#1349]: https://github.com/tj/commander.js/pull/1349\n[#1353]: https://github.com/tj/commander.js/pull/1353\n[#1360]: https://github.com/tj/commander.js/pull/1360\n[#1361]: https://github.com/tj/commander.js/pull/1361\n[#1365]: https://github.com/tj/commander.js/pull/1365\n[#1368]: https://github.com/tj/commander.js/pull/1368\n[#1375]: https://github.com/tj/commander.js/pull/1375\n[#1380]: https://github.com/tj/commander.js/pull/1380\n[#1387]: https://github.com/tj/commander.js/pull/1387\n[#1390]: https://github.com/tj/commander.js/pull/1390\n[#1403]: https://github.com/tj/commander.js/pull/1403\n[#1409]: https://github.com/tj/commander.js/pull/1409\n[#1427]: https://github.com/tj/commander.js/pull/1427\n[#1440]: https://github.com/tj/commander.js/pull/1440\n[#1448]: https://github.com/tj/commander.js/pull/1448\n[#1449]: https://github.com/tj/commander.js/pull/1449\n[#1453]: https://github.com/tj/commander.js/pull/1453\n[#1454]: https://github.com/tj/commander.js/pull/1454\n[#1464]: https://github.com/tj/commander.js/pull/1464\n[#1475]: https://github.com/tj/commander.js/pull/1475\n[#1477]: https://github.com/tj/commander.js/pull/1477\n[#1483]: https://github.com/tj/commander.js/pull/1483\n[#1490]: https://github.com/tj/commander.js/pull/1490\n[#1497]: https://github.com/tj/commander.js/pull/1497\n[#1500]: https://github.com/tj/commander.js/pull/1500\n[#1502]: https://github.com/tj/commander.js/pull/1502\n[#1508]: https://github.com/tj/commander.js/pull/1508\n[#1513]: https://github.com/tj/commander.js/pull/1513\n[#1514]: https://github.com/tj/commander.js/pull/1514\n[#1516]: https://github.com/tj/commander.js/pull/1516\n[#1520]: https://github.com/tj/commander.js/pull/1520\n[#1521]: https://github.com/tj/commander.js/pull/1521\n[#1522]: https://github.com/tj/commander.js/pull/1522\n[#1525]: https://github.com/tj/commander.js/pull/1525\n[#1529]: https://github.com/tj/commander.js/pull/1529\n[#1534]: https://github.com/tj/commander.js/pull/1534\n[#1539]: https://github.com/tj/commander.js/pull/1539\n[#1557]: https://github.com/tj/commander.js/pull/1557\n[#1567]: https://github.com/tj/commander.js/pull/1567\n[#1570]: https://github.com/tj/commander.js/pull/1570\n[#1571]: https://github.com/tj/commander.js/pull/1571\n[#1587]: https://github.com/tj/commander.js/pull/1587\n[#1589]: https://github.com/tj/commander.js/pull/1589\n[#1590]: https://github.com/tj/commander.js/pull/1590\n[#1612]: https://github.com/tj/commander.js/pull/1612\n[#1613]: https://github.com/tj/commander.js/pull/1613\n[#1652]: https://github.com/tj/commander.js/pull/1652\n[#1655]: https://github.com/tj/commander.js/pull/1655\n[#1657]: https://github.com/tj/commander.js/pull/1657\n[#1659]: https://github.com/tj/commander.js/pull/1659\n[#1667]: https://github.com/tj/commander.js/pull/1667\n[#1669]: https://github.com/tj/commander.js/pull/1669\n[#1671]: https://github.com/tj/commander.js/pull/1671\n[#1675]: https://github.com/tj/commander.js/pull/1675\n[#1678]: https://github.com/tj/commander.js/pull/1678\n[#1698]: https://github.com/tj/commander.js/pull/1698\n[#1703]: https://github.com/tj/commander.js/pull/1703\n[#1706]: https://github.com/tj/commander.js/pull/1706\n[#1708]: https://github.com/tj/commander.js/pull/1708\n[#1710]: https://github.com/tj/commander.js/pull/1710\n[#1718]: https://github.com/tj/commander.js/pull/1718\n[#1721]: https://github.com/tj/commander.js/pull/1721\n[#1724]: https://github.com/tj/commander.js/pull/1724\n[#1726]: https://github.com/tj/commander.js/pull/1726\n[#1727]: https://github.com/tj/commander.js/pull/1727\n[#1756]: https://github.com/tj/commander.js/pull/1756\n[#1763]: https://github.com/tj/commander.js/pull/1763\n[#1767]: https://github.com/tj/commander.js/pull/1767\n[#1794]: https://github.com/tj/commander.js/pull/1794\n[#1795]: https://github.com/tj/commander.js/pull/1795\n[#1804]: https://github.com/tj/commander.js/pull/1804\n[#1832]: https://github.com/tj/commander.js/pull/1832\n[#1828]: https://github.com/tj/commander.js/pull/1828\n[#1844]: https://github.com/tj/commander.js/pull/1844\n[#1854]: https://github.com/tj/commander.js/pull/1854\n[#1858]: https://github.com/tj/commander.js/pull/1858\n[#1859]: https://github.com/tj/commander.js/pull/1859\n[#1860]: https://github.com/tj/commander.js/pull/1860\n[#1864]: https://github.com/tj/commander.js/pull/1864\n[#1874]: https://github.com/tj/commander.js/pull/1874\n[#1886]: https://github.com/tj/commander.js/pull/1886\n[#1896]: https://github.com/tj/commander.js/pull/1896\n[#1928]: https://github.com/tj/commander.js/pull/1928\n[#1930]: https://github.com/tj/commander.js/pull/1930\n[#1937]: https://github.com/tj/commander.js/pull/1937\n[#1949]: https://github.com/tj/commander.js/pull/1949\n[#1965]: https://github.com/tj/commander.js/pull/1965\n[#1969]: https://github.com/tj/commander.js/pull/1969\n[#1982]: https://github.com/tj/commander.js/pull/1982\n[#1983]: https://github.com/tj/commander.js/pull/1983\n[#2006]: https://github.com/tj/commander.js/pull/2006\n[#2010]: https://github.com/tj/commander.js/pull/2010\n[#2017]: https://github.com/tj/commander.js/pull/2017\n[#2019]: https://github.com/tj/commander.js/pull/2019\n[#2023]: https://github.com/tj/commander.js/pull/2023\n[#2027]: https://github.com/tj/commander.js/pull/2027\n[#2055]: https://github.com/tj/commander.js/pull/2055\n[#2059]: https://github.com/tj/commander.js/pull/2059\n[#2087]: https://github.com/tj/commander.js/pull/2087\n[#2150]: https://github.com/tj/commander.js/pull/2150\n[#2153]: https://github.com/tj/commander.js/pull/2153\n[#2164]: https://github.com/tj/commander.js/pull/2164\n[#2170]: https://github.com/tj/commander.js/pull/2170\n[#2180]: https://github.com/tj/commander.js/pull/2180\n[#2191]: https://github.com/tj/commander.js/pull/2191\n[#2197]: https://github.com/tj/commander.js/pull/2197\n[#2223]: https://github.com/tj/commander.js/pull/2223\n[#2251]: https://github.com/tj/commander.js/pull/2251\n[#2270]: https://github.com/tj/commander.js/pull/2270\n[#2299]: https://github.com/tj/commander.js/pull/2299\n[#2312]: https://github.com/tj/commander.js/pull/2312\n[#2328]: https://github.com/tj/commander.js/pull/2328\n[#2339]: https://github.com/tj/commander.js/pull/2339\n[#2348]: https://github.com/tj/commander.js/pull/2348\n[#2350]: https://github.com/tj/commander.js/pull/2350\n[#2359]: https://github.com/tj/commander.js/pull/2359\n[#2369]: https://github.com/tj/commander.js/pull/2369\n[#2394]: https://github.com/tj/commander.js/pull/2394\n[#2395]: https://github.com/tj/commander.js/pull/2395\n[#2396]: https://github.com/tj/commander.js/pull/2396\n[#2409]: https://github.com/tj/commander.js/pull/2409\n[#2410]: https://github.com/tj/commander.js/pull/2410\n[#2427]: https://github.com/tj/commander.js/pull/2427\n[#2428]: https://github.com/tj/commander.js/pull/2428\n[#2462]: https://github.com/tj/commander.js/pull/2462\n[#2465]: https://github.com/tj/commander.js/pull/2465\n\n<!-- Referenced in 5.x -->\n[#1]: https://github.com/tj/commander.js/issues/1\n[#432]: https://github.com/tj/commander.js/issues/432\n[#508]: https://github.com/tj/commander.js/issues/508\n[#512]: https://github.com/tj/commander.js/issues/512\n[#531]: https://github.com/tj/commander.js/issues/531\n[#645]: https://github.com/tj/commander.js/issues/645\n[#742]: https://github.com/tj/commander.js/issues/742\n[#764]: https://github.com/tj/commander.js/issues/764\n[#802]: https://github.com/tj/commander.js/issues/802\n[#809]: https://github.com/tj/commander.js/issues/809\n[#962]: https://github.com/tj/commander.js/issues/962\n[#995]: https://github.com/tj/commander.js/issues/995\n[#1062]: https://github.com/tj/commander.js/pull/1062\n[#1088]: https://github.com/tj/commander.js/issues/1088\n[#1119]: https://github.com/tj/commander.js/pull/1119\n[#1133]: https://github.com/tj/commander.js/pull/1133\n[#1138]: https://github.com/tj/commander.js/pull/1138\n[#1145]: https://github.com/tj/commander.js/pull/1145\n[#1146]: https://github.com/tj/commander.js/pull/1146\n[#1149]: https://github.com/tj/commander.js/pull/1149\n[#1153]: https://github.com/tj/commander.js/issues/1153\n[#1159]: https://github.com/tj/commander.js/pull/1159\n[#1165]: https://github.com/tj/commander.js/pull/1165\n[#1169]: https://github.com/tj/commander.js/pull/1169\n[#1172]: https://github.com/tj/commander.js/pull/1172\n[#1179]: https://github.com/tj/commander.js/pull/1179\n[#1180]: https://github.com/tj/commander.js/pull/1180\n[#1184]: https://github.com/tj/commander.js/pull/1184\n[#1191]: https://github.com/tj/commander.js/pull/1191\n[#1195]: https://github.com/tj/commander.js/pull/1195\n[#1208]: https://github.com/tj/commander.js/pull/1208\n[#1232]: https://github.com/tj/commander.js/pull/1232\n[#1235]: https://github.com/tj/commander.js/pull/1235\n[#1236]: https://github.com/tj/commander.js/pull/1236\n[#1247]: https://github.com/tj/commander.js/pull/1247\n[#1248]: https://github.com/tj/commander.js/pull/1248\n\n<!-- Referenced in 4.x -->\n[#933]: https://github.com/tj/commander.js/pull/933\n[#1027]: https://github.com/tj/commander.js/pull/1027\n[#1035]: https://github.com/tj/commander.js/pull/1035\n[#1040]: https://github.com/tj/commander.js/pull/1040\n[#1047]: https://github.com/tj/commander.js/pull/1047\n[#1048]: https://github.com/tj/commander.js/pull/1048\n[#1049]: https://github.com/tj/commander.js/pull/1049\n[#1051]: https://github.com/tj/commander.js/pull/1051\n[#1052]: https://github.com/tj/commander.js/pull/1052\n[#1053]: https://github.com/tj/commander.js/pull/1053\n[#1071]: https://github.com/tj/commander.js/pull/1071\n[#1081]: https://github.com/tj/commander.js/pull/1081\n[#1091]: https://github.com/tj/commander.js/pull/1091\n[#1096]: https://github.com/tj/commander.js/pull/1096\n[#1102]: https://github.com/tj/commander.js/pull/1102\n[#1118]: https://github.com/tj/commander.js/pull/1118\n[#1157]: https://github.com/tj/commander.js/pull/1157\n[#806]: https://github.com/tj/commander.js/issues/806\n\n<!-- Referenced in 3.x -->\n[#599]: https://github.com/tj/commander.js/issues/599\n[#611]: https://github.com/tj/commander.js/issues/611\n[#697]: https://github.com/tj/commander.js/issues/697\n[#795]: https://github.com/tj/commander.js/issues/795\n[#915]: https://github.com/tj/commander.js/issues/915\n[#938]: https://github.com/tj/commander.js/issues/938\n[#963]: https://github.com/tj/commander.js/issues/963\n[#974]: https://github.com/tj/commander.js/issues/974\n[#980]: https://github.com/tj/commander.js/issues/980\n[#987]: https://github.com/tj/commander.js/issues/987\n[#990]: https://github.com/tj/commander.js/issues/990\n[#991]: https://github.com/tj/commander.js/issues/991\n[#999]: https://github.com/tj/commander.js/issues/999\n[#1010]: https://github.com/tj/commander.js/pull/1010\n[#1018]: https://github.com/tj/commander.js/pull/1018\n[#1026]: https://github.com/tj/commander.js/pull/1026\n[#1028]: https://github.com/tj/commander.js/pull/1028\n\n[Unreleased]: https://github.com/tj/commander.js/compare/master...develop\n[14.0.3]: https://github.com/tj/commander.js/compare/v14.0.2...v14.0.3\n[14.0.2]: https://github.com/tj/commander.js/compare/v14.0.1...v14.0.2\n[14.0.1]: https://github.com/tj/commander.js/compare/v14.0.0...v14.0.1\n[14.0.0]: https://github.com/tj/commander.js/compare/v13.1.0...v14.0.0\n[13.1.0]: https://github.com/tj/commander.js/compare/v13.0.0...v13.1.0\n[13.0.0]: https://github.com/tj/commander.js/compare/v12.1.0...v13.0.0\n[13.0.0-0]: https://github.com/tj/commander.js/compare/v12.1.0...v13.0.0-0\n[12.1.0]: https://github.com/tj/commander.js/compare/v12.0.0...v12.1.0\n[12.0.0]: https://github.com/tj/commander.js/compare/v11.1.0...v12.0.0\n[12.0.0-1]: https://github.com/tj/commander.js/compare/v12.0.0-0...v12.0.0-1\n[12.0.0-0]: https://github.com/tj/commander.js/compare/v11.1.0...v12.0.0-0\n[11.1.0]: https://github.com/tj/commander.js/compare/v11.0.0...v11.1.0\n[11.0.0]: https://github.com/tj/commander.js/compare/v10.0.1...v11.0.0\n[10.0.1]: https://github.com/tj/commander.js/compare/v10.0.0...v10.0.1\n[10.0.0]: https://github.com/tj/commander.js/compare/v9.5.0...v10.0.0\n[9.5.0]: https://github.com/tj/commander.js/compare/v9.4.1...v9.5.0\n[9.4.1]: https://github.com/tj/commander.js/compare/v9.4.0...v9.4.1\n[9.4.0]: https://github.com/tj/commander.js/compare/v9.3.0...v9.4.0\n[9.3.0]: https://github.com/tj/commander.js/compare/v9.2.0...v9.3.0\n[9.2.0]: https://github.com/tj/commander.js/compare/v9.1.0...v9.2.0\n[9.1.0]: https://github.com/tj/commander.js/compare/v9.0.0...v9.1.0\n[9.0.0]: https://github.com/tj/commander.js/compare/v8.3.0...v9.0.0\n[9.0.0-1]: https://github.com/tj/commander.js/compare/v9.0.0-0...v9.0.0-1\n[9.0.0-0]: https://github.com/tj/commander.js/compare/v8.3.0...v9.0.0-0\n[8.3.0]: https://github.com/tj/commander.js/compare/v8.2.0...v8.3.0\n[8.2.0]: https://github.com/tj/commander.js/compare/v8.1.0...v8.2.0\n[8.1.0]: https://github.com/tj/commander.js/compare/v8.0.0...v8.1.0\n[8.0.0]: https://github.com/tj/commander.js/compare/v7.2.0...v8.0.0\n[8.0.0-2]: https://github.com/tj/commander.js/compare/v8.0.0-1...v8.0.0-2\n[8.0.0-1]: https://github.com/tj/commander.js/compare/v8.0.0-0...v8.0.0-1\n[8.0.0-0]: https://github.com/tj/commander.js/compare/v7.2.0...v8.0.0-0\n[7.2.0]: https://github.com/tj/commander.js/compare/v7.1.0...v7.2.0\n[7.1.0]: https://github.com/tj/commander.js/compare/v7.0.0...v7.1.0\n[7.0.0]: https://github.com/tj/commander.js/compare/v6.2.1...v7.0.0\n[7.0.0-2]: https://github.com/tj/commander.js/compare/v7.0.0-1...v7.0.0-2\n[7.0.0-1]: https://github.com/tj/commander.js/compare/v7.0.0-0...v7.0.0-1\n[7.0.0-0]: https://github.com/tj/commander.js/compare/v6.2.0...v7.0.0-0\n[6.2.1]: https://github.com/tj/commander.js/compare/v6.2.0..v6.2.1\n[6.2.0]: https://github.com/tj/commander.js/compare/v6.1.0..v6.2.0\n[6.1.0]: https://github.com/tj/commander.js/compare/v6.0.0..v6.1.0\n[6.0.0]: https://github.com/tj/commander.js/compare/v5.1.0..v6.0.0\n[6.0.0-0]: https://github.com/tj/commander.js/compare/v5.1.0..v6.0.0-0\n[5.1.0]: https://github.com/tj/commander.js/compare/v5.0.0..v5.1.0\n[5.0.0]: https://github.com/tj/commander.js/compare/v4.1.1..v5.0.0\n[5.0.0-4]: https://github.com/tj/commander.js/compare/v5.0.0-3..v5.0.0-4\n[5.0.0-3]: https://github.com/tj/commander.js/compare/v5.0.0-2..v5.0.0-3\n[5.0.0-2]: https://github.com/tj/commander.js/compare/v5.0.0-1..v5.0.0-2\n[5.0.0-1]: https://github.com/tj/commander.js/compare/v5.0.0-0..v5.0.0-1\n[5.0.0-0]: https://github.com/tj/commander.js/compare/v4.1.1..v5.0.0-0\n[4.1.1]: https://github.com/tj/commander.js/compare/v4.1.0..v4.1.1\n[4.1.0]: https://github.com/tj/commander.js/compare/v4.0.1..v4.1.0\n[4.0.1]: https://github.com/tj/commander.js/compare/v4.0.0..v4.0.1\n[4.0.0]: https://github.com/tj/commander.js/compare/v3.0.2..v4.0.0\n[4.0.0-1]: https://github.com/tj/commander.js/compare/v4.0.0-0..v4.0.0-1\n[4.0.0-0]: https://github.com/tj/commander.js/compare/v3.0.2...v4.0.0-0\n[3.0.2]: https://github.com/tj/commander.js/compare/v3.0.1...v3.0.2\n[3.0.1]: https://github.com/tj/commander.js/compare/v3.0.0...v3.0.1\n[3.0.0]: https://github.com/tj/commander.js/compare/v2.20.1...v3.0.0\n[2.20.1]: https://github.com/tj/commander.js/compare/v2.20.0...v2.20.1\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\n## Issues\n\nNew issues are welcome, whether questions or suggestions or reporting bugs.\nYou are also welcome to contribute by adding helpful comments on an existing issue.\n\nWe love reproducible code examples in questions and answers.\n\nIf you get a satisfactory reply to a question then please close your issue, but it is ok to leave an issue open for more replies or interest. Inactive issues may get closed after one month if they have an answer,\nor after six months otherwise.\n\n## Pull Requests\n\nPull Requests will be considered. Please submit pull requests against the develop branch.\n\nFollow the existing code style. Check the tests succeed, including format and lint.\n\n- `npm run test`\n- `npm run check`\n\nDon't update the CHANGELOG or command version number. That gets done by maintainers when preparing the release.\n\nUseful things to include in your request description are:\n\n- what problem are you solving?\n- what Issues does this relate to?\n- suggested summary for CHANGELOG\n\nThere are a lot of forms of documentation which could need updating for a change in functionality. It\nis ok if you want to show us the code to discuss before doing the extra work, and\nyou should say so in your comments so we focus on the concept first before talking about all the other pieces:\n\n- TypeScript typings\n- JSDoc documentation in code\n- tests\n- README\n- examples/\n\nCommander currently has zero production dependencies. That isn't a hard requirement, but is a simple story. Requests which add a dependency are much less likely to be accepted, and we are likely to ask for alternative approaches to avoid the dependency.\n\n- <https://devrant.com/rants/1854993/package-tsunami>\n- <https://dev.to/leoat12/the-nodemodules-problem-29dc>\n"
  },
  {
    "path": "LICENSE",
    "content": "(The MIT License)\n\nCopyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "Readme.md",
    "content": "# Commander.js\n\n[![Build Status](https://github.com/tj/commander.js/workflows/build/badge.svg)](https://github.com/tj/commander.js/actions?query=workflow%3A%22build%22)\n[![NPM Version](http://img.shields.io/npm/v/commander.svg?style=flat)](https://www.npmjs.org/package/commander)\n[![NPM Downloads](https://img.shields.io/npm/dm/commander.svg?style=flat)](https://npmcharts.com/compare/commander?minimal=true)\n[![Install Size](https://packagephobia.now.sh/badge?p=commander)](https://packagephobia.now.sh/result?p=commander)\n\nThe complete solution for [node.js](http://nodejs.org) command-line interfaces.\n\nRead this in other languages: English | [简体中文](./Readme_zh-CN.md)\n\n- [Commander.js](#commanderjs)\n  - [Installation](#installation)\n  - [Quick Start](#quick-start)\n  - [Declaring _program_ variable](#declaring-program-variable)\n  - [Options](#options)\n    - [Common option types, boolean and value](#common-option-types-boolean-and-value)\n    - [Default option value](#default-option-value)\n    - [Other option types, negatable boolean and boolean|value](#other-option-types-negatable-boolean-and-booleanvalue)\n    - [Required option](#required-option)\n    - [Variadic option](#variadic-option)\n    - [Version option](#version-option)\n    - [More configuration](#more-configuration)\n    - [Custom option processing](#custom-option-processing)\n  - [Commands](#commands)\n    - [Command-arguments](#command-arguments)\n      - [More configuration](#more-configuration-1)\n      - [Custom argument processing](#custom-argument-processing)\n    - [Action handler](#action-handler)\n    - [Stand-alone executable (sub)commands](#stand-alone-executable-subcommands)\n    - [Life cycle hooks](#life-cycle-hooks)\n  - [Automated help](#automated-help)\n    - [Custom help](#custom-help)\n    - [Display help after errors](#display-help-after-errors)\n    - [Display help from code](#display-help-from-code)\n    - [.name](#name)\n    - [.usage](#usage)\n    - [.description and .summary](#description-and-summary)\n    - [.helpOption(flags, description)](#helpoptionflags-description)\n    - [.helpCommand()](#helpcommand)\n    - [Help Groups](#help-groups)\n    - [More configuration](#more-configuration-2)\n  - [Custom event listeners](#custom-event-listeners)\n  - [Bits and pieces](#bits-and-pieces)\n    - [.parse() and .parseAsync()](#parse-and-parseasync)\n    - [Parsing Configuration](#parsing-configuration)\n    - [Legacy options as properties](#legacy-options-as-properties)\n    - [TypeScript](#typescript)\n    - [createCommand()](#createcommand)\n    - [Node options such as `--harmony`](#node-options-such-as---harmony)\n    - [Debugging stand-alone executable subcommands](#debugging-stand-alone-executable-subcommands)\n    - [npm run-script](#npm-run-script)\n    - [Display error](#display-error)\n    - [Override exit and output handling](#override-exit-and-output-handling)\n    - [Additional documentation](#additional-documentation)\n  - [Support](#support)\n    - [Commander for enterprise](#commander-for-enterprise)\n\nFor information about terms used in this document see: [terminology](./docs/terminology.md)\n\n## Installation\n\n```sh\nnpm install commander\n```\n\n## Quick Start\n\nYou write code to describe your command line interface.\nCommander looks after parsing the arguments into options and command-arguments,\ndisplays usage errors for problems, and implements a help system.\n\nCommander is strict and displays an error for unrecognised options.\nThe two most used option types are a boolean option, and an option which takes its value from the following argument.\n\nExample file: [split.js](./examples/split.js)\n\n```js\nconst { program } = require('commander');\n\nprogram\n  .option('--first')\n  .option('-s, --separator <char>')\n  .argument('<string>');\n\nprogram.parse();\n\nconst options = program.opts();\nconst limit = options.first ? 1 : undefined;\nconsole.log(program.args[0].split(options.separator, limit));\n```\n\n```console\n$ node split.js -s / --fits a/b/c\nerror: unknown option '--fits'\n(Did you mean --first?)\n$ node split.js -s / --first a/b/c\n[ 'a' ]\n```\n\nHere is a more complete program using a subcommand and with descriptions for the help. In a multi-command program, you have an action handler for each command (or stand-alone executables for the commands).\n\nExample file: [string-util.js](./examples/string-util.js)\n\n```js\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram\n  .name('string-util')\n  .description('CLI to some JavaScript string utilities')\n  .version('0.8.0');\n\nprogram.command('split')\n  .description('Split a string into substrings and display as an array')\n  .argument('<string>', 'string to split')\n  .option('--first', 'display just the first substring')\n  .option('-s, --separator <char>', 'separator character', ',')\n  .action((str, options) => {\n    const limit = options.first ? 1 : undefined;\n    console.log(str.split(options.separator, limit));\n  });\n\nprogram.parse();\n```\n\n```console\n$ node string-util.js help split\nUsage: string-util split [options] <string>\n\nSplit a string into substrings and display as an array.\n\nArguments:\n  string                  string to split\n\nOptions:\n  --first                 display just the first substring\n  -s, --separator <char>  separator character (default: \",\")\n  -h, --help              display help for command\n\n$ node string-util.js split --separator=/ a/b/c\n[ 'a', 'b', 'c' ]\n```\n\nMore samples can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory.\n\n## Declaring _program_ variable\n\nCommander exports a global object which is convenient for quick programs.\nThis is used in the examples in this README for brevity.\n\n```js\n// CommonJS (.cjs)\nconst { program } = require('commander');\n```\n\nFor larger programs which may use commander in multiple ways, including unit testing, it is better to create a local `Command` object to use.\n\n```js\n// CommonJS (.cjs)\nconst { Command } = require('commander');\nconst program = new Command();\n```\n\n```js\n// ECMAScript (.mjs)\nimport { Command } from 'commander';\nconst program = new Command();\n```\n\n```ts\n// TypeScript (.ts)\nimport { Command } from 'commander';\nconst program = new Command();\n```\n\n## Options\n\nOptions are defined with the `.option()` method, also serving as documentation for the options. Each option can have a short flag (single character) and a long name, separated by a comma, a space, or a vertical bar (`|`). To allow a wider range of short-ish flags than just single characters, you may also have two long options.\n\n```js\nprogram\n  .option('-p, --port <number>', 'server port number')\n  .option('--trace', 'add extra debugging output')\n  .option('--ws, --workspace <name>', 'use a custom workspace')\n```\n\nThe parsed options can be accessed by calling `.opts()` on a `Command` object, and are passed to the action handler.\n\nMulti-word options like `--template-engine` are normalized to camelCase option names, resulting in properties such as `program.opts().templateEngine`.\n\nAn option and its option-argument can be separated by a space, or combined into the same argument. The option-argument can follow the short option directly, or follow an `=` for a long option.\n\n```sh\nserve -p 80\nserve -p80\nserve --port 80\nserve --port=80\n```\n\nYou can use `--` to indicate the end of the options, and any remaining arguments will be used without being interpreted.\n\nBy default, options on the command line are not positional, and can be specified before or after other arguments.\n\nThere are additional related routines for when `.opts()` is not enough:\n\n- `.optsWithGlobals()` returns merged local and global option values\n- `.getOptionValue()` and `.setOptionValue()` work with a single option value\n- `.getOptionValueSource()` and `.setOptionValueWithSource()` include where the option value came from\n\n### Common option types, boolean and value\n\nThe two most used option types are a boolean option, and an option which takes its value\nfrom the following argument (declared with angle brackets like `--expect <value>`). Both are `undefined` unless specified on command line.\n\nExample file: [options-common.js](./examples/options-common.js)\n\n```js\nprogram\n  .option('-d, --debug', 'output extra debugging')\n  .option('-s, --small', 'small pizza size')\n  .option('-p, --pizza-type <type>', 'flavour of pizza');\n\nprogram.parse(process.argv);\n\nconst options = program.opts();\nif (options.debug) console.log(options);\nconsole.log('pizza details:');\nif (options.small) console.log('- small pizza size');\nif (options.pizzaType) console.log(`- ${options.pizzaType}`);\n```\n\n```console\n$ pizza-options -p\nerror: option '-p, --pizza-type <type>' argument missing\n$ pizza-options -d -s -p vegetarian\n{ debug: true, small: true, pizzaType: 'vegetarian' }\npizza details:\n- small pizza size\n- vegetarian\n$ pizza-options --pizza-type=cheese\npizza details:\n- cheese\n```\n\nMultiple boolean short options may be combined following the dash, and may be followed by a single short option taking a value.\nFor example, `-d -s -p cheese` may be written as `-ds -p cheese` or even `-dsp cheese`.\n\nOptions with an expected option-argument are greedy and will consume the following argument whatever the value.\nSo `--id -xyz` reads `-xyz` as the option-argument.\n\n`program.parse(arguments)` processes the arguments, leaving any args not consumed by the program options in the `program.args` array. The parameter is optional and defaults to `process.argv`.\n\n### Default option value\n\nYou can specify a default value for an option.\n\nExample file: [options-defaults.js](./examples/options-defaults.js)\n\n```js\nprogram\n  .option('-c, --cheese <type>', 'add the specified type of cheese', 'blue');\n\nprogram.parse();\n\nconsole.log(`cheese: ${program.opts().cheese}`);\n```\n\n```console\n$ pizza-options\ncheese: blue\n$ pizza-options --cheese stilton\ncheese: stilton\n```\n\n### Other option types, negatable boolean and boolean|value\n\nYou can define a boolean option long name with a leading `no-` to set the option value to `false` when used.\nDefined alone, this also makes the option `true` by default.\n\nIf you define `--foo` first, adding `--no-foo` does not change the default value from what it would\notherwise be.\n\nExample file: [options-negatable.js](./examples/options-negatable.js)\n\n```js\nprogram\n  .option('--no-sauce', 'Remove sauce')\n  .option('--cheese <flavour>', 'cheese flavour', 'mozzarella')\n  .option('--no-cheese', 'plain with no cheese')\n  .parse();\n\nconst options = program.opts();\nconst sauceStr = options.sauce ? 'sauce' : 'no sauce';\nconst cheeseStr = (options.cheese === false) ? 'no cheese' : `${options.cheese} cheese`;\nconsole.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`);\n```\n\n```console\n$ pizza-options\nYou ordered a pizza with sauce and mozzarella cheese\n$ pizza-options --sauce\nerror: unknown option '--sauce'\n$ pizza-options --cheese=blue\nYou ordered a pizza with sauce and blue cheese\n$ pizza-options --no-sauce --no-cheese\nYou ordered a pizza with no sauce and no cheese\n```\n\nYou can specify an option which may be used as a boolean option but may optionally take an option-argument\n(declared with square brackets, like `--optional [value]`).\n\nExample file: [options-boolean-or-value.js](./examples/options-boolean-or-value.js)\n\n```js\nprogram\n  .option('-c, --cheese [type]', 'Add cheese with optional type');\n\nprogram.parse(process.argv);\n\nconst options = program.opts();\nif (options.cheese === undefined) console.log('no cheese');\nelse if (options.cheese === true) console.log('add cheese');\nelse console.log(`add cheese type ${options.cheese}`);\n```\n\n```console\n$ pizza-options\nno cheese\n$ pizza-options --cheese\nadd cheese\n$ pizza-options --cheese mozzarella\nadd cheese type mozzarella\n```\n\nOptions with an optional option-argument are not greedy and will ignore arguments starting with a dash.\nSo `id` behaves as a boolean option for `--id -ABCD`, but you can use a combined form if needed like `--id=-ABCD`.\nNegative numbers are special and are accepted as an option-argument.\n\nFor information about possible ambiguous cases, see [options taking varying arguments](./docs/options-in-depth.md).\n\n### Required option\n\nYou may specify a required (mandatory) option using `.requiredOption()`. The option must have a value after parsing, usually specified on the command line, or perhaps from a default value (e.g., from environment). \n\nThe method is otherwise the same as `.option()` in format, taking flags and description, and optional default value or custom processing.\n\nExample file: [options-required.js](./examples/options-required.js)\n\n```js\nprogram\n  .requiredOption('-c, --cheese <type>', 'pizza must have cheese');\n\nprogram.parse();\n```\n\n```console\n$ pizza\nerror: required option '-c, --cheese <type>' not specified\n```\n\n### Variadic option\n\nYou may make an option variadic by appending `...` to the value placeholder when declaring the option. On the command line you\ncan then specify multiple option-arguments, and the parsed option value will be an array. The extra arguments\nare read until the first argument starting with a dash. The special argument `--` stops option processing entirely. If a value\nis specified in the same argument as the option, then no further values are read.\n\nExample file: [options-variadic.js](./examples/options-variadic.js)\n\n```js\nprogram\n  .option('-n, --number <numbers...>', 'specify numbers')\n  .option('-l, --letter [letters...]', 'specify letters');\n\nprogram.parse();\n\nconsole.log('Options: ', program.opts());\nconsole.log('Remaining arguments: ', program.args);\n```\n\n```console\n$ collect -n 1 2 3 --letter a b c\nOptions:  { number: [ '1', '2', '3' ], letter: [ 'a', 'b', 'c' ] }\nRemaining arguments:  []\n$ collect --letter=A -n80 operand\nOptions:  { number: [ '80' ], letter: [ 'A' ] }\nRemaining arguments:  [ 'operand' ]\n$ collect --letter -n 1 -n 2 3 -- operand\nOptions:  { number: [ '1', '2', '3' ], letter: true }\nRemaining arguments:  [ 'operand' ]\n```\n\nFor information about possible ambiguous cases, see [options taking varying arguments](./docs/options-in-depth.md).\n\n### Version option\n\nThe optional `.version()` method adds handling for displaying the command version. The default option flags are `-V` and `--version`. When used, the command prints the version number and exits.\n\n```js\nprogram.version('0.0.1');\n```\n\n```console\n$ ./examples/pizza -V\n0.0.1\n```\n\nYou may change the flags and description by passing additional parameters to the `.version()` method, using\nthe same syntax for flags as the `.option()` method.\n\n```js\nprogram.version('0.0.1', '-v, --vers', 'output the current version');\n```\n\n### More configuration\n\nYou can add most options using the `.option()` method, but there are some additional features available\nby constructing an `Option` explicitly for less common cases.\n\nExample files: [options-extra.js](./examples/options-extra.js), [options-env.js](./examples/options-env.js), [options-conflicts.js](./examples/options-conflicts.js), [options-implies.js](./examples/options-implies.js)\n\n```js\nprogram\n  .addOption(new Option('-s, --secret').hideHelp())\n  .addOption(new Option('-t, --timeout <delay>', 'timeout in seconds').default(60, 'one minute'))\n  .addOption(new Option('-d, --drink <size>', 'drink size').choices(['small', 'medium', 'large']))\n  .addOption(new Option('-p, --port <number>', 'port number').env('PORT'))\n  .addOption(new Option('--donate [amount]', 'optional donation in dollars').preset('20').argParser(parseFloat))\n  .addOption(new Option('--disable-server', 'disables the server').conflicts('port'))\n  .addOption(new Option('--free-drink', 'small drink included free ').implies({ drink: 'small' }));\n```\n\n```console\n$ extra --help\nUsage: help [options]\n\nOptions:\n  -t, --timeout <delay>  timeout in seconds (default: one minute)\n  -d, --drink <size>     drink cup size (choices: \"small\", \"medium\", \"large\")\n  -p, --port <number>    port number (env: PORT)\n  --donate [amount]      optional donation in dollars (preset: \"20\")\n  --disable-server       disables the server\n  --free-drink           small drink included free\n  -h, --help             display help for command\n\n$ extra --drink huge\nerror: option '-d, --drink <size>' argument 'huge' is invalid. Allowed choices are small, medium, large.\n\n$ PORT=80 extra --donate --free-drink\nOptions:  { timeout: 60, donate: 20, port: '80', freeDrink: true, drink: 'small' }\n\n$ extra --disable-server --port 8000\nerror: option '--disable-server' cannot be used with option '-p, --port <number>'\n```\n\nSpecify a required (mandatory) option using the `Option` method `.makeOptionMandatory()`. This matches the `Command` method [`.requiredOption()`](#required-option).\n\n### Custom option processing\n\nYou may specify a function to do custom processing of option-arguments. The callback function receives two parameters,\nthe user specified option-argument and the previous value for the option. It returns the new value for the option.\n\nThis allows you to coerce the option-argument to the desired type, or accumulate values, or do entirely custom processing.\n\nYou can optionally specify the default/starting value for the option after the function parameter.\n\nExample file: [options-custom-processing.js](./examples/options-custom-processing.js)\n\n```js\nfunction myParseInt(value, dummyPrevious) {\n  // parseInt takes a string and a radix\n  const parsedValue = parseInt(value, 10);\n  if (isNaN(parsedValue)) {\n    throw new commander.InvalidArgumentError('Not a number.');\n  }\n  return parsedValue;\n}\n\nfunction increaseVerbosity(dummyValue, previous) {\n  return previous + 1;\n}\n\nfunction collect(value, previous) {\n  return previous.concat([value]);\n}\n\nfunction commaSeparatedList(value, dummyPrevious) {\n  return value.split(',');\n}\n\nprogram\n  .option('-f, --float <number>', 'float argument', parseFloat)\n  .option('-i, --integer <number>', 'integer argument', myParseInt)\n  .option('-v, --verbose', 'verbosity that can be increased', increaseVerbosity, 0)\n  .option('-c, --collect <value>', 'repeatable value', collect, [])\n  .option('-l, --list <items>', 'comma separated list', commaSeparatedList)\n;\n\nprogram.parse();\n\nconst options = program.opts();\nif (options.float !== undefined) console.log(`float: ${options.float}`);\nif (options.integer !== undefined) console.log(`integer: ${options.integer}`);\nif (options.verbose > 0) console.log(`verbosity: ${options.verbose}`);\nif (options.collect.length > 0) console.log(options.collect);\nif (options.list !== undefined) console.log(options.list);\n```\n\n```console\n$ custom -f 1e2\nfloat: 100\n$ custom --integer 2\ninteger: 2\n$ custom -v -v -v\nverbose: 3\n$ custom -c a -c b -c c\n[ 'a', 'b', 'c' ]\n$ custom --list x,y,z\n[ 'x', 'y', 'z' ]\n```\n\n## Commands\n\nYou can specify (sub)commands using `.command()` or `.addCommand()`. There are two ways these can be implemented: using an `.action()` handler attached to the command; or as a stand-alone executable file. (More detail about this later.)\n\nSubcommands may be nested. Example file: [nestedCommands.js](./examples/nestedCommands.js).\n\nIn the first parameter to `.command()` you specify the command name. You may append the command-arguments after the command name, or specify them separately using `.argument()`. The arguments may be `<required>` or `[optional]`, and the last argument may also be `variadic...`.\n\nYou can use `.addCommand()` to add an already configured subcommand to the program.\n\nFor example:\n\n```js\n// Command implemented using action handler (description is supplied separately to `.command`)\n// Returns new command for configuring.\nprogram\n  .command('clone <source> [destination]')\n  .description('clone a repository into a newly created directory')\n  .action((source, destination) => {\n    console.log('clone command called');\n  });\n\n// Command implemented using stand-alone executable file, indicated by adding description as second parameter to `.command`.\n// Returns `this` for adding more commands.\nprogram\n  .command('start <service>', 'start named service')\n  .command('stop [service]', 'stop named service, or all if no name supplied');\n\n// Command prepared separately.\n// Returns `this` for adding more commands.\nprogram\n  .addCommand(build.makeBuildCommand());\n```\n\nConfiguration options can be passed with the call to `.command()` and `.addCommand()`. Specifying `hidden: true` will\nremove the command from the generated help output. Specifying `isDefault: true` will run the subcommand if no other\nsubcommand is specified. (Example file: [defaultCommand.js](./examples/defaultCommand.js).)\n\nYou can add alternative names for a command with `.alias()`. (Example file: [alias.js](./examples/alias.js).)\n\n`.command()` automatically copies the inherited settings from the parent command to the newly created subcommand. This is only done during creation; any later setting changes to the parent are not inherited.\n\nFor safety, `.addCommand()` does not automatically copy the inherited settings from the parent command. There is a helper routine `.copyInheritedSettings()` for copying the settings when they are wanted.\n\n### Command-arguments\n\nFor subcommands, you can specify the argument syntax in the call to `.command()` (as shown above). This\nis the only method usable for subcommands implemented using a stand-alone executable.\n\nAlternatively, you can instead use the following method. To configure a command, you can use `.argument()` to specify each expected command-argument.\nYou supply the argument name and an optional description. The argument may be `<required>` or `[optional]`.\nYou can specify a default value for an optional command-argument.\n\nExample file: [argument.js](./examples/argument.js)\n\n```js\nprogram\n  .version('0.1.0')\n  .argument('<username>', 'user to login')\n  .argument('[password]', 'password for user, if required', 'no password given')\n  .action((username, password) => {\n    console.log('username:', username);\n    console.log('password:', password);\n  });\n```\n\nThe last argument of a command can be variadic, and _only_ the last argument.  To make an argument variadic, simply\nappend `...` to the argument name.\n\nA variadic argument is passed to the action handler as an array.\n\n```js\nprogram\n  .version('0.1.0')\n  .command('rmdir')\n  .argument('<dirs...>')\n  .action(function (dirs) {\n    dirs.forEach((dir) => {\n      console.log('rmdir %s', dir);\n    });\n  });\n```\n\nThere is a convenience method to add multiple arguments at once, but without descriptions:\n\n```js\nprogram\n  .arguments('<username> <password>');\n```\n\n#### More configuration\n\nThere are some additional features available by constructing an `Argument` explicitly for less common cases.\n\nExample file: [arguments-extra.js](./examples/arguments-extra.js)\n\n```js\nprogram\n  .addArgument(new commander.Argument('<drink-size>', 'drink cup size').choices(['small', 'medium', 'large']))\n  .addArgument(new commander.Argument('[timeout]', 'timeout in seconds').default(60, 'one minute'))\n```\n\n#### Custom argument processing\n\nYou may specify a function to do custom processing of command-arguments (like for option-arguments).\nThe callback function receives two parameters, the user specified command-argument and the previous value for the argument.\nIt returns the new value for the argument.\n\nThe processed argument values are passed to the action handler, and saved as `.processedArgs`.\n\nYou can optionally specify the default/starting value for the argument after the function parameter.\n\nExample file: [arguments-custom-processing.js](./examples/arguments-custom-processing.js)\n\n```js\nprogram\n  .command('add')\n  .argument('<first>', 'integer argument', myParseInt)\n  .argument('[second]', 'integer argument', myParseInt, 1000)\n  .action((first, second) => {\n    console.log(`${first} + ${second} = ${first + second}`);\n  })\n;\n```\n\n### Action handler\n\nThe action handler gets passed a parameter for each command-argument you declared, and two additional parameters\nwhich are the parsed options and the command object itself.\n\nExample file: [thank.js](./examples/thank.js)\n\n```js\nprogram\n  .argument('<name>')\n  .option('-t, --title <honorific>', 'title to use before name')\n  .option('-d, --debug', 'display some debugging')\n  .action((name, options, command) => {\n    if (options.debug) {\n      console.error('Called %s with options %o', command.name(), options);\n    }\n    const title = options.title ? `${options.title} ` : '';\n    console.log(`Thank-you ${title}${name}`);\n  });\n```\n\nIf you prefer, you can work with the command directly and skip declaring the parameters for the action handler. If you use a function expression (but not an arrow function), the `this` keyword is set to the running command.\n\nExample file: [action-this.js](./examples/action-this.js)\n\n```js\nprogram\n  .command('serve')\n  .argument('<script>')\n  .option('-p, --port <number>', 'port number', 80)\n  .action(function() {\n    console.error('Run script %s on port %s', this.args[0], this.opts().port);\n  });\n```\n\nYou may supply an `async` action handler, in which case you call `.parseAsync()` rather than `.parse()`.\n\n```js\nasync function run() { /* code goes here */ }\n\nasync function main() {\n  program\n    .command('run')\n    .action(run);\n  await program.parseAsync(process.argv);\n}\n```\n\nA command's options and arguments on the command line are validated when the command is used. Any unknown options, missing arguments, or excess arguments will be reported as an error. \n\nYou can suppress the unknown option check with `.allowUnknownOption()`. You can suppress the excess arguments check with `.allowExcessArguments()`.\n\n### Stand-alone executable (sub)commands\n\nWhen `.command()` is invoked with a description argument, this tells Commander that you're going to use stand-alone executables for subcommands.\nCommander will search the files in the directory of the entry script for a file with the name combination `command-subcommand` (like `pm-install` or `pm-search` in the example below). The search includes trying common file extensions, like `.js`.\nYou may specify a custom name (and path) with the `executableFile` configuration option.\nYou may specify a custom search directory for subcommands with `.executableDir()`.\n\nYou handle the options for an executable (sub)command in the executable, and don't declare them at the top-level.\n\nExample file: [pm](./examples/pm)\n\n```js\nprogram\n  .name('pm')\n  .version('0.1.0')\n  .command('install [package-names...]', 'install one or more packages')\n  .command('search [query]', 'search with optional query')\n  .command('update', 'update installed packages', { executableFile: 'myUpdateSubCommand' })\n  .command('list', 'list packages installed', { isDefault: true });\n\nprogram.parse(process.argv);\n```\n\nIf the program is designed to be installed globally, make sure the executables have proper modes, like `755`.\n\n### Life cycle hooks\n\nYou can add callback hooks to a command for life cycle events.\n\nExample file: [hook.js](./examples/hook.js)\n\n```js\nprogram\n  .option('-t, --trace', 'display trace statements for commands')\n  .hook('preAction', (thisCommand, actionCommand) => {\n    if (thisCommand.opts().trace) {\n      console.log(`About to call action handler for subcommand: ${actionCommand.name()}`);\n      console.log('arguments: %O', actionCommand.args);\n      console.log('options: %o', actionCommand.opts());\n    }\n  });\n```\n\nThe callback hook can be `async`, in which case you call `.parseAsync()` rather than `.parse()`. You can add multiple hooks per event.\n\nThe supported events are:\n\n| event name | when hook called | callback parameters |\n| :-- | :-- | :-- |\n| `preAction`, `postAction` |  before/after action handler for this command and its nested subcommands |   `(thisCommand, actionCommand)` |\n| `preSubcommand` | before parsing direct subcommand  | `(thisCommand, subcommand)` |\n\nFor an overview of the life cycle events, see [parsing life cycle and hooks](./docs/parsing-and-hooks.md).\n\n## Automated help\n\nThe help information is auto-generated based on the information commander already knows about your program. The default\nhelp option is `-h,--help`.\n\nExample file: [pizza](./examples/pizza)\n\n```console\n$ node ./examples/pizza --help\nUsage: pizza [options]\n\nAn application for pizza ordering\n\nOptions:\n  -p, --peppers        Add peppers\n  -c, --cheese <type>  Add the specified type of cheese (default: \"marble\")\n  -C, --no-cheese      You do not want any cheese\n  -h, --help           display help for command\n```\n\nA `help` command is added by default if your command has subcommands. It can be used alone, or with a subcommand name to show\nfurther help for the subcommand. These are effectively the same if the `shell` program has implicit help:\n\n```sh\nshell help\nshell --help\n\nshell help spawn\nshell spawn --help\n```\n\nLong descriptions are wrapped to fit the available width. (However, a description that includes a line-break followed by whitespace is assumed to be pre-formatted and not wrapped.)\n\n### Custom help\n\nYou can add extra text to be displayed along with the built-in help.\n\nExample file: [custom-help](./examples/custom-help)\n\n```js\nprogram\n  .option('-f, --foo', 'enable some foo');\n\nprogram.addHelpText('after', `\n\nExample call:\n  $ custom-help --help`);\n```\n\nYields the following help output:\n\n```Text\nUsage: custom-help [options]\n\nOptions:\n  -f, --foo   enable some foo\n  -h, --help  display help for command\n\nExample call:\n  $ custom-help --help\n```\n\nThe positions in order displayed are:\n\n- `beforeAll`: add to the program for a global banner or header\n- `before`: display extra information before built-in help\n- `after`: display extra information after built-in help\n- `afterAll`: add to the program for a global footer (epilog)\n\nThe positions \"beforeAll\" and \"afterAll\" apply to the command and all its subcommands.\n\nThe second parameter can be a string, or a function returning a string. The function is passed a context object for your convenience. The properties are:\n\n- `error`: a boolean for whether the help is being displayed due to a usage error\n- `command`: the `Command` which is displaying the help\n\n### Display help after errors\n\nThe default behaviour for usage errors is to just display a short error message.\nYou can change the behaviour to show the full help or a custom help message after an error.\n\n```js\nprogram.showHelpAfterError();\n// or\nprogram.showHelpAfterError('(add --help for additional information)');\n```\n\n```console\n$ pizza --unknown\nerror: unknown option '--unknown'\n(add --help for additional information)\n```\n\nThe default behaviour is to suggest correct spelling after an error for an unknown command or option. You\ncan disable this.\n\n```js\nprogram.showSuggestionAfterError(false);\n```\n\n```console\n$ pizza --hepl\nerror: unknown option '--hepl'\n(Did you mean --help?)\n```\n\n### Display help from code\n\n`.help()`: display help information and exit immediately. You can optionally pass `{ error: true }` to display on stderr and exit with an error status.\n\n`.outputHelp()`: output help information without exiting. You can optionally pass `{ error: true }` to display on stderr.\n\n`.helpInformation()`: get the built-in command help information as a string for processing or displaying yourself.\n\n### .name\n\nThe command name appears in the help, and is also used for locating stand-alone executable subcommands.\n\nYou may specify the program name using `.name()` or in the `Command` constructor. For the program, Commander will\nfall back to using the script name from the full arguments passed into `.parse()`. However, the script name varies\ndepending on how your program is launched, so you may wish to specify it explicitly.\n\n```js\nprogram.name('pizza');\nconst pm = new Command('pm');\n```\n\nSubcommands get a name when specified using `.command()`. If you create the subcommand yourself to use with `.addCommand()`,\nthen set the name using `.name()` or in the `Command` constructor.\n\n### .usage\n\nThis allows you to customise the usage description in the first line of the help. Given:\n\n```js\nprogram\n  .name(\"my-command\")\n  .usage(\"[global options] command\")\n```\n\nThe help will start with:\n\n```Text\nUsage: my-command [global options] command\n```\n\n### .description and .summary\n\nThe description appears in the help for the command. You can optionally supply a shorter\nsummary to use when listed as a subcommand of the program.\n\n```js\nprogram\n  .command(\"duplicate\")\n  .summary(\"make a copy\")\n  .description(`Make a copy of the current project.\nThis may require additional disk space.\n  `);\n```\n\n### .helpOption(flags, description)\n\nBy default, every command has a help option. You may change the default help flags and description. Pass `false` to disable the built-in help option.\n\n```js\nprogram\n  .helpOption('-e, --HELP', 'read more information');\n```\n\nAlternatively, use `.addHelpOption()` to add an option you construct yourself.\n\n### .helpCommand()\n\nA help command is added by default if your command has subcommands. You can explicitly turn the implicit help command on or off with `.helpCommand(true)` and `.helpCommand(false)`.\n\nYou can both turn on and customise the help command by supplying the name and description:\n\n```js\nprogram.helpCommand('assist [command]', 'show assistance');\n```\n\nAlternatively, use `.addHelpCommand()` to add a command you construct yourself.\n\n### Help Groups\n\nThe help by default lists options under the the heading `Options:` and commands under `Commands:`. You can create your own groups\nwith different headings. \n\n- The high-level way is to set the desired group heading while adding the options and commands, using `.optionsGroup()` and `.commandsGroup()`. \n- The low-level way is using `.helpGroup()` on an individual `Option` or `Command`.\n\nExample file: [help-groups.js](./examples/help-groups.js)\n\n### More configuration\n\nThe built-in help is formatted using the `Help` class.\nYou can configure the help by modifying data properties and methods using `.configureHelp()`, or by subclassing `Help` using `.createHelp()` .\n\nSimple properties include `sortSubcommands`, `sortOptions`, and `showGlobalOptions`. You can add color using the style methods like `.styleTitle()`.\n\nFor more detail and examples of changing the displayed text, color, and layout, see: [Help in Depth](./docs/help-in-depth.md).\n\n## Custom event listeners\n\nYou can execute custom actions by listening to `command` and `option` events.\n\n```js\nprogram.on('option:verbose', function () {\n  process.env.VERBOSE = this.opts().verbose;\n});\n```\n\n## Bits and pieces\n\n### .parse() and .parseAsync()\n\nCall with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!\n\nOr, call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:\n\n- `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that\n- `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged\n- `'user'`: just user arguments\n\nFor example:\n\n```js\nprogram.parse(); // parse process.argv and auto-detect electron and special node flags\nprogram.parse(process.argv); // assume argv[0] is app and argv[1] is script\nprogram.parse(['--port', '80'], { from: 'user' }); // just user supplied arguments, nothing special about argv[0]\n```\n\nUse `.parseAsync()` instead of `.parse()` if any of your action handlers are async.\n\n### Parsing Configuration\n\nIf the default parsing does not suit your needs, there are some behaviours to support other usage patterns.\n\nBy default, program options are recognised before and after subcommands. To only look for program options before subcommands, use `.enablePositionalOptions()`. This lets you use\nan option for a different purpose in subcommands.\n\nExample file: [positional-options.js](./examples/positional-options.js)\n\nWith positional options, the `-b` is a program option in the first line and a subcommand option in the second line:\n\n```sh\nprogram -b subcommand\nprogram subcommand -b\n```\n\nBy default, options are recognised before and after command-arguments. To only process options that come\nbefore the command-arguments, use `.passThroughOptions()`. This lets you pass the arguments and following options through to another program\nwithout needing to use `--` to end the option processing.\nTo use pass through options in a subcommand, the program needs to enable positional options.\n\nExample file: [pass-through-options.js](./examples/pass-through-options.js)\n\nWith pass through options, the `--port=80` is a program option in the first line and passed through as a command-argument in the second line:\n\n```sh\nprogram --port=80 arg\nprogram arg --port=80\n```\n\nBy default, the option processing shows an error for an unknown option. To have an unknown option treated as an ordinary command-argument and continue looking for options, use `.allowUnknownOption()`. This lets you mix known and unknown options.\n\nBy default, the argument processing displays an error for more command-arguments than expected.\nTo suppress the error for excess arguments, use `.allowExcessArguments()`.\n\n### Legacy options as properties\n\nBefore Commander 7, the option values were stored as properties on the command.\nThis was convenient to code, but the downside was possible clashes with\nexisting properties of `Command`. \n\nYou can revert to the old behaviour to run unmodified legacy code by using `.storeOptionsAsProperties()`.\n\n```js\nprogram\n  .storeOptionsAsProperties()\n  .option('-d, --debug')\n  .action((commandAndOptions) => {\n    if (commandAndOptions.debug) {\n      console.error(`Called ${commandAndOptions.name()}`);\n    }\n  });\n```\n\n### TypeScript\n\n**extra-typings:** There is an optional project to infer extra type information from the option and argument definitions.\nThis adds strong typing to the options returned by `.opts()` and the parameters to `.action()`.\nFor more, see the repo: [commander-js/extra-typings](https://github.com/commander-js/extra-typings).\n\n```ts\nimport { Command } from '@commander-js/extra-typings';\n```\n\n**ts-node:** If you use `ts-node` and stand-alone executable subcommands written as `.ts` files, you need to call your program through node to get the subcommands called correctly, e.g.:\n\n```sh\nnode -r ts-node/register pm.ts\n```\n\n### createCommand()\n\nThis factory function creates a new command. It is exported and may be used instead of using `new`, like:\n\n```js\nconst { createCommand } = require('commander');\nconst program = createCommand();\n```\n\n`createCommand()` is also a method of the `Command` object, and creates a new command rather than a subcommand. This gets used internally\nwhen creating subcommands using `.command()`, and you may override it to\ncustomise the new subcommand. Example file: [custom-command-class.js](./examples/custom-command-class.js).\n\n### Node options such as `--harmony`\n\nYou can enable `--harmony` option in two ways:\n\n- Use `#! /usr/bin/env node --harmony` in the subcommands scripts. (Note: Windows does not support this pattern.)\n- Use the `--harmony` option when calling the command, like `node --harmony examples/pm publish`. The `--harmony` option will be preserved when spawning subcommand processes.\n\n### Debugging stand-alone executable subcommands\n\nAn executable subcommand is launched as a separate child process.\n\nIf you are using the node inspector for [debugging](https://nodejs.org/en/docs/guides/debugging-getting-started/) executable subcommands using `node --inspect` et al.,\nthe inspector port is incremented by 1 for the spawned subcommand.\n\nIf you are using VSCode to debug executable subcommands you need to set the `\"autoAttachChildProcesses\": true` flag in your `launch.json` configuration.\n\n### npm run-script\n\nBy default, when you call your program using `run-script`, `npm` will parse any options on the command-line and they will not reach your program. Use\n `--` to stop the npm option parsing and pass through all the arguments.\n\n The synopsis for [`npm run-script`](https://docs.npmjs.com/cli/v9/commands/npm-run-script) explicitly shows the `--` for this reason:\n\n```console\nnpm run-script <command> [-- <args>]\n```\n\n### Display error\n\nThis routine is available to invoke the Commander error handling for your own error conditions. (See also the next section about exit handling.)\n\nAs well as the error message, you can optionally specify the `exitCode` (used with `process.exit()`)\nand `code` (used with `CommanderError`).\n\n```js\nprogram.error('Password must be longer than four characters');\nprogram.error('Custom processing has failed', { exitCode: 2, code: 'my.custom.error' });\n```\n\n### Override exit and output handling\n\nBy default, Commander calls `process.exit()` when it detects errors, or after displaying the help or version. You can override\nthis behaviour and optionally supply a callback. The default override throws a `CommanderError`.\n\nThe override callback is passed a `CommanderError` with the properties:\n- `exitCode`: number\n- `code`: string \n- `message`: string\n\nCommander expects the callback to terminate the normal program flow, and will call `process.exit()` if the callback returns.\nThe normal display of error messages or version or help is not affected by the override, which is called after the display.\n\n```js\nprogram.exitOverride();\n\ntry {\n  program.parse(process.argv);\n} catch (err) {\n  // custom processing...\n}\n```\n\nBy default, Commander is configured for a command-line application and writes to stdout and stderr.\nYou can modify this behaviour for custom applications. In addition, you can modify the display of error messages.\n\nExample file: [configure-output.js](./examples/configure-output.js)\n\n```js\nfunction errorColor(str) {\n  // Add ANSI escape codes to display text in red.\n  return `\\x1b[31m${str}\\x1b[0m`;\n}\n\nprogram\n  .configureOutput({\n    // Visibly override write routines as example!\n    writeOut: (str) => process.stdout.write(`[OUT] ${str}`),\n    writeErr: (str) => process.stdout.write(`[ERR] ${str}`),\n    // Highlight errors in color.\n    outputError: (str, write) => write(errorColor(str))\n  });\n```\n\n### Additional documentation\n\nThere is more information available about:\n\n- [deprecated](./docs/deprecated.md) features still supported for backwards compatibility\n- [Help in Depth](./docs/help-in-depth.md) configuring help output\n- [options taking varying arguments](./docs/options-in-depth.md)\n- [parsing life cycle and hooks](./docs/parsing-and-hooks.md)\n- [Release Policy](./docs/release-policy.md)\n\n## Support\n\nThe current version of Commander is fully supported on Long Term Support versions of Node.js, and requires at least v20.\n\nOlder major versions of Commander receive security updates for 12 months. For more see: [Release Policy](./docs/release-policy.md).\n\nThe main forum for free and community support is the project [Issues](https://github.com/tj/commander.js/issues) on GitHub.\n\n### Commander for enterprise\n\nAvailable as part of the Tidelift Subscription\n\nThe maintainers of Commander and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-commander?utm_source=npm-commander&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)\n"
  },
  {
    "path": "Readme_zh-CN.md",
    "content": "# Commander.js\n\n[![Build Status](https://github.com/tj/commander.js/workflows/build/badge.svg)](https://github.com/tj/commander.js/actions?query=workflow%3A%22build%22)\n[![NPM Version](http://img.shields.io/npm/v/commander.svg?style=flat)](https://www.npmjs.org/package/commander)\n[![NPM Downloads](https://img.shields.io/npm/dm/commander.svg?style=flat)](https://npmcharts.com/compare/commander?minimal=true)\n[![Install Size](https://packagephobia.now.sh/badge?p=commander)](https://packagephobia.now.sh/result?p=commander)\n\n完整的 [node.js](http://nodejs.org) 命令行解决方案。\n\n使用其他语言阅读：[English](./Readme.md) | 简体中文\n\n- [Commander.js](#commanderjs)\n  - [安装](#%e5%ae%89%e8%a3%85)\n  - [快速开始](#%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B)\n  - [声明 program 变量](#%e5%a3%b0%e6%98%8e-program-%e5%8f%98%e9%87%8f)\n  - [选项](#%e9%80%89%e9%a1%b9)\n    - [常用选项类型，boolean 型选项和带参数的选项](#%e5%b8%b8%e7%94%a8%e9%80%89%e9%a1%b9%e7%b1%bb%e5%9e%8bboolean-%e5%9e%8b%e9%80%89%e9%a1%b9%e5%92%8c%e5%b8%a6%e5%8f%82%e6%95%b0%e9%80%89%e9%a1%b9)\n    - [选项的默认值](#%E9%80%89%E9%A1%B9%E7%9A%84%E9%BB%98%E8%AE%A4%E5%80%BC)\n    - [其他的选项类型，取反选项，以及可选参数的选项](#%E5%85%B6%E4%BB%96%E7%9A%84%E9%80%89%E9%A1%B9%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%8F%96%E5%8F%8D%E9%80%89%E9%A1%B9%EF%BC%8C%E4%BB%A5%E5%8F%8A%E5%8F%AF%E9%80%89%E5%8F%82%E6%95%B0%E7%9A%84%E9%80%89%E9%A1%B9)\n    - [必填选项](#%e5%bf%85%e5%a1%ab%e9%80%89%e9%a1%b9)\n    - [变长参数选项](#%e5%8f%98%e9%95%bf%e5%8f%82%e6%95%b0%e9%80%89%e9%a1%b9)\n    - [版本选项](#%e7%89%88%e6%9c%ac%e9%80%89%e9%a1%b9)\n    - [其他选项配置](#%E5%85%B6%E4%BB%96%E9%80%89%E9%A1%B9%E9%85%8D%E7%BD%AE)\n    - [自定义选项处理](#%E8%87%AA%E5%AE%9A%E4%B9%89%E9%80%89%E9%A1%B9%E5%A4%84%E7%90%86)\n  - [命令](#%e5%91%bd%e4%bb%a4)\n    - [命令参数](#%E5%91%BD%E4%BB%A4%E5%8F%82%E6%95%B0)\n      - [其他参数配置](#%E5%85%B6%E4%BB%96%E5%8F%82%E6%95%B0%E9%85%8D%E7%BD%AE)\n      - [自定义参数处理](#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8F%82%E6%95%B0%E5%A4%84%E7%90%86)\n    - [处理函数](#%E5%A4%84%E7%90%86%E5%87%BD%E6%95%B0)\n    - [独立的可执行（子）命令](#%E7%8B%AC%E7%AB%8B%E7%9A%84%E5%8F%AF%E6%89%A7%E8%A1%8C%EF%BC%88%E5%AD%90%EF%BC%89%E5%91%BD%E4%BB%A4)\n    - [生命周期钩子](#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD%90)\n  - [自动化帮助信息](#%e8%87%aa%e5%8a%a8%e5%8c%96%e5%b8%ae%e5%8a%a9%e4%bf%a1%e6%81%af)\n    - [自定义帮助](#%e8%87%aa%e5%ae%9a%e4%b9%89%e5%b8%ae%e5%8a%a9)\n    - [在出错后展示帮助信息](#%E5%9C%A8%E5%87%BA%E9%94%99%E5%90%8E%E5%B1%95%E7%A4%BA%E5%B8%AE%E5%8A%A9%E4%BF%A1%E6%81%AF)\n    - [使用代码展示帮助信息](#%E4%BD%BF%E7%94%A8%E4%BB%A3%E7%A0%81%E5%B1%95%E7%A4%BA%E5%B8%AE%E5%8A%A9%E4%BF%A1%E6%81%AF)\n    - [.name](#name)\n    - [.usage](#usage)\n    - [.description 和 .summary](#description-%E5%92%8C-summary)\n    - [.helpOption(flags, description)](#helpoptionflags-description)\n    - [.addHelpCommand()](#addhelpcommand)\n    - [其他帮助配置](#%E5%85%B6%E4%BB%96%E5%B8%AE%E5%8A%A9%E9%85%8D%E7%BD%AE)\n  - [自定义事件监听](#%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6%e7%9b%91%e5%90%ac)\n  - [零碎知识](#%e9%9b%b6%e7%a2%8e%e7%9f%a5%e8%af%86)\n    - [.parse() 和 .parseAsync()](#parse-%e5%92%8c-parseasync)\n    - [解析配置](#%E8%A7%A3%E6%9E%90%E9%85%8D%E7%BD%AE)\n    - [作为属性的遗留选项](#%E4%BD%9C%E4%B8%BA%E5%B1%9E%E6%80%A7%E7%9A%84%E9%81%97%E7%95%99%E9%80%89%E9%A1%B9)\n    - [TypeScript](#typescript)\n    - [createCommand()](#createCommand)\n    - [Node 选项，如 --harmony](#node-%E9%80%89%E9%A1%B9%EF%BC%8C%E5%A6%82---harmony)\n    - [调试子命令](#%e8%b0%83%e8%af%95%e5%ad%90%e5%91%bd%e4%bb%a4)\n    - [显示错误](#%E6%98%BE%E7%A4%BA%E9%94%99%E8%AF%AF)\n    - [重写退出和输出](#%E9%87%8D%E5%86%99%E9%80%80%E5%87%BA%E5%92%8C%E8%BE%93%E5%87%BA)\n    - [其他文档](#%E5%85%B6%E4%BB%96%E6%96%87%E6%A1%A3)\n  - [支持](#%e6%94%af%e6%8c%81)\n    - [企业使用 Commander](#%e4%bc%81%e4%b8%9a%e4%bd%bf%e7%94%a8-commander)\n\n关于本文档中使用的术语，请见[术语表](./docs/zh-CN/%E6%9C%AF%E8%AF%AD%E8%A1%A8.md)\n\n## 安装\n\n```sh\nnpm install commander\n```\n\n## 快速开始\n\n编写代码来描述你的命令行界面。\nCommander 负责将参数解析为选项和命令参数，为问题显示使用错误，并实现一个有帮助的系统。\n\nCommander 是严格的，并且会针对无法识别的选项显示错误。\n两种最常用的选项类型是布尔选项，和从参数中获取值的选项。\n\n示例代码：[split.js](./examples/split.js)\n\n```js\nconst { program } = require('commander');\n\nprogram\n  .option('--first')\n  .option('-s, --separator <char>')\n  .argument('<string>');\n\nprogram.parse();\n\nconst options = program.opts();\nconst limit = options.first ? 1 : undefined;\nconsole.log(program.args[0].split(options.separator, limit));\n```\n\n```console\n$ node split.js -s / --fits a/b/c\nerror: unknown option '--fits'\n(Did you mean --first?)\n$ node split.js -s / --first a/b/c\n[ 'a' ]\n```\n\n这是一个使用子命令并带有帮助描述的更完整的程序。在多命令程序中，每个命令（或命令的独立可执行文件）都有一个操作处理程序。\n\n示例代码：[string-util.js](./examples/string-util.js)\n\n```js\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram\n  .name('string-util')\n  .description('CLI to some JavaScript string utilities')\n  .version('0.8.0');\n\nprogram.command('split')\n  .description('Split a string into substrings and display as an array')\n  .argument('<string>', 'string to split')\n  .option('--first', 'display just the first substring')\n  .option('-s, --separator <char>', 'separator character', ',')\n  .action((str, options) => {\n    const limit = options.first ? 1 : undefined;\n    console.log(str.split(options.separator, limit));\n  });\n\nprogram.parse();\n```\n\n```console\n$ node string-util.js help split\nUsage: string-util split [options] <string>\n\nSplit a string into substrings and display as an array.\n\nArguments:\n  string                  string to split\n\nOptions:\n  --first                 display just the first substring\n  -s, --separator <char>  separator character (default: \",\")\n  -h, --help              display help for command\n\n$ node string-util.js split --separator=/ a/b/c\n[ 'a', 'b', 'c' ]\n```\n\n更多示例可以在 [examples](https://github.com/tj/commander.js/tree/master/examples) 目录中找到。\n\n## 声明 program 变量\n\n为简化使用，Commander 提供了一个全局对象。本文档的示例代码均按此方法使用：\n\n```js\n// CommonJS (.cjs)\nconst { program } = require('commander');\n```\n\n如果程序较为复杂，用户需要以多种方式来使用 Commander，如单元测试等。创建本地 Command 对象是一种更好的方式：\n\n```js\n// CommonJS (.cjs)\nconst { Command } = require('commander');\nconst program = new Command();\n```\n\n```js\n// ECMAScript (.mjs)\nimport { Command } from 'commander';\nconst program = new Command();\n```\n\n```ts\n// TypeScript (.ts)\nimport { Command } from 'commander';\nconst program = new Command();\n```\n\n## 选项\n\nCommander 使用`.option()`方法来定义选项，同时可以附加选项的简介。每个选项可以定义一个短选项名称（-后面接单个字符）和一个长选项名称（--后面接一个或多个单词），使用逗号、空格或`|`分隔。\n\n解析后的选项可以通过`Command`对象上的`.opts()`方法获取，同时会被传递给命令处理函数。\n\n对于多个单词的长选项，选项名会转为驼峰命名法（camel-case），例如`--template-engine`选项可通过`program.opts().templateEngine`获取。\n\n选项及其选项参数可以用空格分隔，也可以组合成同一个参数。选项参数可以直接跟在短选项之后，也可以在长选项后面加上 `=`。\n\n```sh\nserve -p 80\nserve -p80\nserve --port 80\nserve --port=80\n```\n\n`--`可以标记选项的结束，后续的参数均不会被命令解释，可以正常使用。\n\n默认情况下，选项在命令行中的顺序不固定，一个选项可以在其他参数之前或之后指定。\n\n当`.opts()`不够用时，还有其他相关方法：\n\n- `.optsWithGlobals()`返回合并的本地和全局选项值\n- `.getOptionValue()`和`.setOptionValue()`操作单个选项的值\n- `.getOptionValueSource()`和`.setOptionValueWithSource()`包括选项值的来源\n\n### 常用选项类型，boolean 型选项和带参数选项\n\n有两种最常用的选项，一类是 boolean 型选项，选项无需配置参数，另一类选项则可以设置参数（使用尖括号声明在该选项后，如`--expect <value>`）。如果在命令行中不指定具体的选项及参数，则会被定义为`undefined`。\n\n示例代码：[options-common.js](./examples/options-common.js)\n\n```js\nprogram\n  .option('-d, --debug', 'output extra debugging')\n  .option('-s, --small', 'small pizza size')\n  .option('-p, --pizza-type <type>', 'flavour of pizza');\n\nprogram.parse(process.argv);\n\nconst options = program.opts();\nif (options.debug) console.log(options);\nconsole.log('pizza details:');\nif (options.small) console.log('- small pizza size');\nif (options.pizzaType) console.log(`- ${options.pizzaType}`);\n```\n\n```console\n$ pizza-options -p\nerror: option '-p, --pizza-type <type>' argument missing\n$ pizza-options -d -s -p vegetarian\n{ debug: true, small: true, pizzaType: 'vegetarian' }\npizza details:\n- small pizza size\n- vegetarian\n$ pizza-options --pizza-type=cheese\npizza details:\n- cheese\n```\n\n多个布尔短选项可以在破折号之后组合在一起，并且可以跟一个取值的单一选项。\n例如 `-d -s -p cheese` 可以写成 `-ds -p cheese` 甚至 `-dsp cheese`。\n\n具有预期选项参数的选项是贪婪的，并且无论值如何，都会消耗参数。\n所以 `--id -xyz` 读取 `-xyz` 作为选项参数。\n\n通过`program.parse(arguments)`方法处理参数，没有被使用的选项会存放在`program.args`数组中。该方法的参数是可选的，默认值为`process.argv`。\n\n### 选项的默认值\n\n选项可以设置一个默认值。\n\n示例代码：[options-defaults.js](./examples/options-defaults.js)\n\n```js\nprogram\n  .option('-c, --cheese <type>', 'add the specified type of cheese', 'blue');\n\nprogram.parse();\n\nconsole.log(`cheese: ${program.opts().cheese}`);\n```\n\n```console\n$ pizza-options\ncheese: blue\n$ pizza-options --cheese stilton\ncheese: stilton\n```\n\n### 其他的选项类型，取反选项，以及可选参数的选项\n\n可以定义一个以`no-`开头的 boolean 型长选项。在命令行中使用该选项时，会将对应选项的值置为`false`。当只定义了带`no-`的选项，未定义对应不带`no-`的选项时，该选项的默认值会被置为`true`。\n\n如果已经定义了`--foo`，那么再定义`--no-foo`并不会改变它本来的默认值。\n\n示例代码：[options-negatable.js](./examples/options-negatable.js)\n\n```js\nprogram\n  .option('--no-sauce', 'Remove sauce')\n  .option('--cheese <flavour>', 'cheese flavour', 'mozzarella')\n  .option('--no-cheese', 'plain with no cheese')\n  .parse();\n\nconst options = program.opts();\nconst sauceStr = options.sauce ? 'sauce' : 'no sauce';\nconst cheeseStr = (options.cheese === false) ? 'no cheese' : `${options.cheese} cheese`;\nconsole.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`);\n```\n\n```console\n$ pizza-options\nYou ordered a pizza with sauce and mozzarella cheese\n$ pizza-options --sauce\nerror: unknown option '--sauce'\n$ pizza-options --cheese=blue\nYou ordered a pizza with sauce and blue cheese\n$ pizza-options --no-sauce --no-cheese\nYou ordered a pizza with no sauce and no cheese\n```\n\n选项的参数使用方括号声明表示参数是可选参数（如`--optional [value]`）。该选项在不带参数时可用作 boolean 选项，在带有参数时则从参数中得到值。\n\n示例代码：[options-boolean-or-value.js](./examples/options-boolean-or-value.js)\n\n```js\nprogram\n  .option('-c, --cheese [type]', 'Add cheese with optional type');\n\nprogram.parse(process.argv);\n\nconst options = program.opts();\nif (options.cheese === undefined) console.log('no cheese');\nelse if (options.cheese === true) console.log('add cheese');\nelse console.log(`add cheese type ${options.cheese}`);\n```\n\n```console\n$ pizza-options\nno cheese\n$ pizza-options --cheese\nadd cheese\n$ pizza-options --cheese mozzarella\nadd cheese type mozzarella\n```\n\n带有可选选项参数的选项不是贪婪的，并且会忽略以破折号开头的参数。因此对于`--id -5`，`id`表现为布尔选项，但如果需要，您可以使用组合形式，例如 `--id=-5`。\n\n关于可能有歧义的用例，请见[可变参数的选项](./docs/zh-CN/%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0%E7%9A%84%E9%80%89%E9%A1%B9.md)。\n\n### 必填选项\n\n通过`.requiredOption()`方法可以设置选项为必填。必填选项要么设有默认值，要么必须在命令行中输入，对应的属性字段在解析时必定会有赋值。该方法其余参数与`.option()`一致。\n\n示例代码：[options-required.js](./examples/options-required.js)\n\n```js\nprogram\n  .requiredOption('-c, --cheese <type>', 'pizza must have cheese');\n\nprogram.parse();\n```\n\n```console\n$ pizza\nerror: required option '-c, --cheese <type>' not specified\n```\n\n### 变长参数选项\n\n定义选项时，可以通过使用`...`来设置参数为可变长参数。在命令行中，用户可以输入多个参数，解析后会以数组形式存储在对应属性字段中。在输入下一个选项前（`-`或`--`开头），用户输入的指令均会被视作变长参数。与普通参数一样的是，可以通过`--`标记当前命令的结束。\n\n示例代码：[options-variadic.js](./examples/options-variadic.js)\n\n```js\nprogram\n  .option('-n, --number <numbers...>', 'specify numbers')\n  .option('-l, --letter [letters...]', 'specify letters');\n\nprogram.parse();\n\nconsole.log('Options: ', program.opts());\nconsole.log('Remaining arguments: ', program.args);\n```\n\n```console\n$ collect -n 1 2 3 --letter a b c\nOptions:  { number: [ '1', '2', '3' ], letter: [ 'a', 'b', 'c' ] }\nRemaining arguments:  []\n$ collect --letter=A -n80 operand\nOptions:  { number: [ '80' ], letter: [ 'A' ] }\nRemaining arguments:  [ 'operand' ]\n$ collect --letter -n 1 -n 2 3 -- operand\nOptions:  { number: [ '1', '2', '3' ], letter: true }\nRemaining arguments:  [ 'operand' ]\n```\n\n关于可能有歧义的用例，请见[可变参数的选项](./docs/zh-CN/%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0%E7%9A%84%E9%80%89%E9%A1%B9.md)。\n\n### 版本选项\n\n`.version()`方法可以设置版本，其默认选项为`-V`和`--version`，设置了版本后，命令行会输出当前的版本号。\n\n```js\nprogram.version('0.0.1');\n```\n\n```console\n$ ./examples/pizza -V\n0.0.1\n```\n\n版本选项也支持自定义设置选项名称，可以在`.version()`方法里再传递一些参数（长选项名称、描述信息），用法与`.option()`方法类似。\n\n```bash\nprogram.version('0.0.1', '-v, --vers', 'output the current version');\n```\n\n### 其他选项配置\n\n大多数情况下，选项均可通过`.option()`方法添加。但对某些不常见的用例，也可以直接构造`Option`对象，对选项进行更详尽的配置。\n\n示例代码：[options-extra.js](./examples/options-extra.js), [options-env.js](./examples/options-env.js), [options-conflicts.js](./examples/options-conflicts.js), [options-implies.js](./examples/options-implies.js)\n\n```js\nprogram\n  .addOption(new Option('-s, --secret').hideHelp())\n  .addOption(new Option('-t, --timeout <delay>', 'timeout in seconds').default(60, 'one minute'))\n  .addOption(new Option('-d, --drink <size>', 'drink size').choices(['small', 'medium', 'large']))\n  .addOption(new Option('-p, --port <number>', 'port number').env('PORT'))\n  .addOption(new Option('--donate [amount]', 'optional donation in dollars').preset('20').argParser(parseFloat))\n  .addOption(new Option('--disable-server', 'disables the server').conflicts('port'))\n  .addOption(new Option('--free-drink', 'small drink included free ').implies({ drink: 'small' }));\n```\n\n```console\n$ extra --help\nUsage: help [options]\n\nOptions:\n  -t, --timeout <delay>  timeout in seconds (default: one minute)\n  -d, --drink <size>     drink cup size (choices: \"small\", \"medium\", \"large\")\n  -p, --port <number>    port number (env: PORT)\n  --donate [amount]      optional donation in dollars (preset: \"20\")\n  --disable-server       disables the server\n  --free-drink           small drink included free\n  -h, --help             display help for command\n\n$ extra --drink huge\nerror: option '-d, --drink <size>' argument 'huge' is invalid. Allowed choices are small, medium, large.\n\n$ PORT=80 extra --donate --free-drink\nOptions:  { timeout: 60, donate: 20, port: '80', freeDrink: true, drink: 'small' }\n\n$ extra --disable-server --port 8000\nerror: option '--disable-server' cannot be used with option '-p, --port <number>'\n```\n\n### 自定义选项处理\n\n选项的参数可以通过自定义函数来处理，该函数接收两个参数，即用户新输入的参数值和当前已有的参数值（即上一次调用自定义处理函数后的返回值），返回新的选项参数值。\n\n自定义函数适用场景包括参数类型转换，参数暂存，或者其他自定义处理的场景。\n\n可以在自定义函数的后面设置选项参数的默认值或初始值（例如参数用列表暂存时需要设置一个初始空列表)。\n\n示例代码：[options-custom-processing.js](./examples/options-custom-processing.js)\n\n```js\nfunction myParseInt(value, dummyPrevious) {\n  // parseInt 参数为字符串和进制数\n  const parsedValue = parseInt(value, 10);\n  if (isNaN(parsedValue)) {\n    throw new commander.InvalidArgumentError('Not a number.');\n  }\n  return parsedValue;\n}\n\nfunction increaseVerbosity(dummyValue, previous) {\n  return previous + 1;\n}\n\nfunction collect(value, previous) {\n  return previous.concat([value]);\n}\n\nfunction commaSeparatedList(value, dummyPrevious) {\n  return value.split(',');\n}\n\nprogram\n  .option('-f, --float <number>', 'float argument', parseFloat)\n  .option('-i, --integer <number>', 'integer argument', myParseInt)\n  .option('-v, --verbose', 'verbosity that can be increased', increaseVerbosity, 0)\n  .option('-c, --collect <value>', 'repeatable value', collect, [])\n  .option('-l, --list <items>', 'comma separated list', commaSeparatedList)\n;\n\nprogram.parse();\n\nconst options = program.opts();\nif (options.float !== undefined) console.log(`float: ${options.float}`);\nif (options.integer !== undefined) console.log(`integer: ${options.integer}`);\nif (options.verbose > 0) console.log(`verbosity: ${options.verbose}`);\nif (options.collect.length > 0) console.log(options.collect);\nif (options.list !== undefined) console.log(options.list);\n```\n\n```console\n$ custom -f 1e2\nfloat: 100\n$ custom --integer 2\ninteger: 2\n$ custom -v -v -v\nverbose: 3\n$ custom -c a -c b -c c\n[ 'a', 'b', 'c' ]\n$ custom --list x,y,z\n[ 'x', 'y', 'z' ]\n```\n\n## 命令\n\n通过`.command()`或`.addCommand()`可以配置命令，有两种实现方式：为命令绑定处理函数，或者将命令单独写成一个可执行文件（详述见后文）。子命令支持嵌套（[示例代码](./examples/nestedCommands.js)）。\n\n`.command()`的第一个参数为命令名称。命令参数可以跟在名称后面，也可以用`.argument()`单独指定。参数可为必选的（尖括号表示）、可选的（方括号表示）或变长参数（点号表示，如果使用，只能是最后一个参数）。\n\n使用`.addCommand()`向`program`增加配置好的子命令。\n\n例如:\n\n```js\n// 通过绑定处理函数实现命令（这里的指令描述为放在`.command`中）\n// 返回新生成的命令（即该子命令）以供继续配置\nprogram\n  .command('clone <source> [destination]')\n  .description('clone a repository into a newly created directory')\n  .action((source, destination) => {\n    console.log('clone command called');\n  });\n\n// 通过独立的的可执行文件实现命令 (注意这里指令描述是作为`.command`的第二个参数)\n// 返回最顶层的命令以供继续添加子命令\nprogram\n  .command('start <service>', 'start named service')\n  .command('stop [service]', 'stop named service, or all if no name supplied');\n\n// 分别装配命令\n// 返回最顶层的命令以供继续添加子命令\nprogram\n  .addCommand(build.makeBuildCommand());\n```\n\n使用`.command()`和`addCommand()`来指定选项的相关设置。当设置`hidden: true`时，该命令不会打印在帮助信息里。当设置`isDefault: true`时，若没有指定其他子命令，则会默认执行这个命令（[样例](./examples/defaultCommand.js)）。\n\n### 命令参数\n\n如上所述，子命令的参数可以通过`.command()`指定。对于有独立可执行文件的子命令来说，参数只能以这种方法指定。而对其他子命令，参数也可用以下方法。\n\n在`Command`对象上使用`.argument()`来按次序指定命令参数。该方法接受参数名称和参数描述。参数可为必选的（尖括号表示，例如`<required>`）或可选的（方括号表示，例如`[optional]`）。\n\n示例代码：[argument.js](./examples/argument.js)\n\n```js\nprogram\n  .version('0.1.0')\n  .argument('<username>', 'user to login')\n  .argument('[password]', 'password for user, if required', 'no password given')\n  .action((username, password) => {\n    console.log('username:', username);\n    console.log('password:', password);\n  });\n```\n\n在参数名后加上`...`来声明可变参数，且只有最后一个参数支持这种用法。可变参数会以数组的形式传递给处理函数。例如：\n\n```js\nprogram\n  .version('0.1.0')\n  .command('rmdir')\n  .argument('<dirs...>')\n  .action(function (dirs) {\n    dirs.forEach((dir) => {\n      console.log('rmdir %s', dir);\n    });\n  });\n```\n\n有一种便捷方式可以一次性指定多个参数，但不包含参数描述：\n\n```js\nprogram\n  .arguments('<username> <password>');\n```\n\n#### 其他参数配置\n\n有少数附加功能可以直接构造`Argument`对象，对参数进行更详尽的配置。\n\n示例代码：[arguments-extra.js](./examples/arguments-extra.js)\n\n```js\nprogram\n  .addArgument(new commander.Argument('<drink-size>', 'drink cup size').choices(['small', 'medium', 'large']))\n  .addArgument(new commander.Argument('[timeout]', 'timeout in seconds').default(60, 'one minute'))\n```\n\n#### 自定义参数处理\n\n选项的参数可以通过自定义函数来处理（与处理选项参数时类似），该函数接收两个参数：用户新输入的参数值和当前已有的参数值（即上一次调用自定义处理函数后的返回值），返回新的命令参数值。\n\n处理后的参数值会传递给命令处理函数，同时可通过`.processedArgs`获取。\n\n可以在自定义函数的后面设置命令参数的默认值或初始值。\n\n示例代码：[arguments-custom-processing.js](./examples/arguments-custom-processing.js)\n\n```js\nprogram\n  .command('add')\n  .argument('<first>', 'integer argument', myParseInt)\n  .argument('[second]', 'integer argument', myParseInt, 1000)\n  .action((first, second) => {\n    console.log(`${first} + ${second} = ${first + second}`);\n  })\n;\n```\n\n### 处理函数\n\n命令处理函数的参数，为该命令声明的所有参数，除此之外还会附加两个额外参数：一个是解析出的选项，另一个则是该命令对象自身。\n\n示例代码：[thank.js](./examples/thank.js)\n\n```js\nprogram\n  .argument('<name>')\n  .option('-t, --title <honorific>', 'title to use before name')\n  .option('-d, --debug', 'display some debugging')\n  .action((name, options, command) => {\n    if (options.debug) {\n      console.error('Called %s with options %o', command.name(), options);\n    }\n    const title = options.title ? `${options.title} ` : '';\n    console.log(`Thank-you ${title}${name}`);\n  });\n```\n\n如果你愿意，你可以跳过为处理函数声明参数直接使用 command。 `this` 关键字设置为运行命令，可以在函数表达式中使用（但不能从箭头函数中使用）。\n\n示例代码：[action-this.js](./examples/action-this.js)\n\n```js\nprogram\n  .command('serve')\n  .argument('<script>')\n  .option('-p, --port <number>', 'port number', 80)\n  .action(function() {\n    console.error('Run script %s on port %s', this.args[0], this.opts().port);\n  });\n```\n\n处理函数支持`async`，相应的，需要使用`.parseAsync`代替`.parse`。\n\n```js\nasync function run() { /* 在这里编写代码 */ }\n\nasync function main() {\n  program\n    .command('run')\n    .action(run);\n  await program.parseAsync(process.argv);\n}\n```\n\n使用命令时，所给的选项和命令参数会被验证是否有效。凡是有未知的选项，或缺少所需的命令参数，都会报错。\n如要允许使用未知的选项，可以调用`.allowUnknownOption()`。默认情况下，传入过多的参数并不报错，但也可以通过调用`.allowExcessArguments(false)`来启用过多参数的报错。\n\n### 独立的可执行（子）命令\n\n当`.command()`带有描述参数时，就意味着使用独立的可执行文件作为子命令。\nCommander 会尝试在入口脚本的目录中搜索名称组合为 `command-subcommand` 的文件，如以下示例中的 `pm-install` 或 `pm-search`。搜索包括尝试常见的文件扩展名，如`.js`。\n你可以使用 `executableFile` 配置选项指定自定义名称（和路径）。\n你可以使用 `.executableDir()` 为子命令指定自定义搜索目录。\n\n你可以在可执行文件里处理（子）命令的选项，而不必在顶层声明它们。\n\n示例代码：[pm](./examples/pm)\n\n```js\nprogram\n  .name('pm')\n  .version('0.1.0')\n  .command('install [name]', 'install one or more packages')\n  .command('search [query]', 'search with optional query')\n  .command('update', 'update installed packages', { executableFile: 'myUpdateSubCommand' })\n  .command('list', 'list packages installed', { isDefault: true });\n\nprogram.parse(process.argv);\n```\n\n如果该命令需要支持全局安装，请确保有对应的权限，例如`755`。\n\n### 生命周期钩子\n\n可以在命令的生命周期事件上设置回调函数。\n\n示例代码：[hook.js](./examples/hook.js)\n\n```js\nprogram\n  .option('-t, --trace', 'display trace statements for commands')\n  .hook('preAction', (thisCommand, actionCommand) => {\n    if (thisCommand.opts().trace) {\n      console.log(`About to call action handler for subcommand: ${actionCommand.name()}`);\n      console.log('arguments: %O', actionCommand.args);\n      console.log('options: %o', actionCommand.opts());\n    }\n  });\n```\n\n钩子函数支持`async`，相应的，需要使用`.parseAsync`代替`.parse`。一个事件上可以添加多个钩子。\n\n支持的事件有：\n\n| 事件名称 | 触发时机 | 参数列表 |\n| :-- | :-- | :-- |\n| `preAction`, `postAction` | 本命令或其子命令的处理函数执行前/后 |   `(thisCommand, actionCommand)` |\n| `preSubcommand` | 在其直接子命令解析之前调用  | `(thisCommand, subcommand)` |\n\n## 自动化帮助信息\n\n帮助信息是 Commander 基于你的程序自动生成的，默认的帮助选项是`-h,--help`。\n\n示例代码：[pizza](./examples/pizza)\n\n```console\n$ node ./examples/pizza --help\nUsage: pizza [options]\n\nAn application for pizza ordering\n\nOptions:\n  -p, --peppers        Add peppers\n  -c, --cheese <type>  Add the specified type of cheese (default: \"marble\")\n  -C, --no-cheese      You do not want any cheese\n  -h, --help           display help for command\n```\n\n如果你的命令中包含了子命令，会默认添加`help`命令，它可以单独使用，也可以与子命令一起使用来提示更多帮助信息。用法与`shell`程序类似：\n\n```sh\nshell help\nshell --help\n\nshell help spawn\nshell spawn --help\n```\n\n### 自定义帮助\n\n可以添加额外的帮助信息，与内建的帮助一同展示。\n\n示例代码：[custom-help](./examples/custom-help)\n\n```js\nprogram\n  .option('-f, --foo', 'enable some foo');\n\nprogram.addHelpText('after', `\n\nExample call:\n  $ custom-help --help`);\n```\n\n将会输出以下的帮助信息：\n\n```Text\nUsage: custom-help [options]\n\nOptions:\n  -f, --foo   enable some foo\n  -h, --help  display help for command\n\nExample call:\n  $ custom-help --help\n```\n\n位置参数对应的展示方式如下：\n\n- `beforeAll`：作为全局标头栏展示\n- `before`：在内建帮助信息之前展示\n- `after`：在内建帮助信息之后展示\n- `afterAll`：作为全局末尾栏展示\n\n`beforeAll`和`afterAll`两个参数作用于命令及其所有的子命令。\n\n第二个参数可以是一个字符串，也可以是一个返回字符串的函数。对后者而言，为便于使用，该函数可以接受一个上下文对象，它有如下属性：\n\n- `error`：boolean 值，代表该帮助信息是否由于不当使用而展示\n- `command`：代表展示该帮助信息的`Command`对象\n\n### 在出错后展示帮助信息\n\n默认情况下，出现命令用法错误时只会显示错误信息。可以选择在出错后展示完整的帮助或自定义的帮助信息。\n\n```js\nprogram.showHelpAfterError();\n// 或者\nprogram.showHelpAfterError('(add --help for additional information)');\n```\n\n```console\n$ pizza --unknown\nerror: unknown option '--unknown'\n(add --help for additional information)\n```\n\n默认行为是在出现未知命令或选项错误后建议正确拼写。你可以禁用此功能。\n\n```js\nprogram.showSuggestionAfterError(false);\n```\n\n```console\n$ pizza --hepl\nerror: unknown option '--hepl'\n(Did you mean --help?)\n```\n\n### 使用代码展示帮助信息\n\n`.help()`：展示帮助信息并退出。可以通过传入`{ error: true }`来让帮助信息从 stderr 输出，并以代表错误的状态码退出程序。\n\n`.outputHelp()`：只展示帮助信息，不退出程序。传入`{ error: true }`可以让帮助信息从 stderr 输出。\n\n`.helpInformation()`：得到字符串形式的内建的帮助信息，以便用于自定义的处理及展示。\n\n### .name\n\n命令名称出现在帮助中，也用于定位独立的可执行子命令。\n\n你可以使用 `.name()` 或在 Command 构造函数中指定程序名称。对于 program ，Commander 会使用传递给 `.parse()` 的完整参数中的脚本名称。但是，脚本名称会根据程序的启动方式而有所不同，因此您可能希望明确指定它。\n\n```js\nprogram.name('pizza');\nconst pm = new Command('pm');\n```\n\n使用 `.command()` 指定时，子命令会获得名称。如果您自己创建子命令以与 `.addCommand()` 一起使用，则使用 `.name()` 或在 Command 构造函数中设置名称。\n\n### .usage\n\n通过这个选项可以修改帮助信息的首行提示，例如：\n\n```js\nprogram\n  .name(\"my-command\")\n  .usage(\"[global options] command\")\n```\n\n帮助信息开头如下：\n\n```Text\nUsage: my-command [global options] command\n```\n\n### .description 和 .summary\n\ndescription 出现在命令的帮助中。当列为程序的子命令时，你可以选择提供更短的 summary 以供使用。\n\n```js\nprogram\n  .command(\"duplicate\")\n  .summary(\"make a copy\")\n  .description(`Make a copy of the current project.\nThis may require additional disk space.\n  `);\n```\n\n### .helpOption(flags, description)\n\n每一个命令都带有一个默认的帮助选项。你可以改变 `flags` 和 `description` 参数。传入 `false` 则会禁用内建的帮助信息。\n\n```js\nprogram\n  .helpOption('-e, --HELP', 'read more information');\n```\n\n### .addHelpCommand()\n\n如果一个命令拥有子命令，它也将有一个默认的帮助子命令。使用`.addHelpCommand()`和`.addHelpCommand(false)`可以打开或关闭默认的帮助子命令。\n\n也可以自定义名字和描述：\n\n```js\nprogram.addHelpCommand('assist [command]', 'show assistance');\n```\n\n### 其他帮助配置\n\n内建帮助信息通过`Help`类进行格式化。如有需要，可以使用`.configureHelp()`来更改其数据属性和方法，或使用`.createHelp()`来创建子类，从而配置`Help`类的行为。\n\n数据属性包括：\n\n- `helpWidth`：指明帮助信息的宽度。可在单元测试中使用。\n- `sortSubcommands`：以字母序排列子命令\n- `sortOptions`：以字母序排列选项\n\n可以得到可视化的参数列表，选项列表，以及子命令列表。列表的每个元素都具有`_term_`和`_description_`属性，并可以对其进行格式化。关于其使用方式，请参考`.formatHelp()`。\n\n示例代码：[configure-help.js](./examples/configure-help.js)\n\n```js\nprogram.configureHelp({\n  sortSubcommands: true,\n  subcommandTerm: (cmd) => cmd.name() // 显示名称，而非用法\n});\n```\n\n## 自定义事件监听\n\n监听命令和选项可以执行自定义函数。\n\n```js\nprogram.on('option:verbose', function () {\n  process.env.VERBOSE = this.opts().verbose;\n});\n```\n\n## 零碎知识\n\n### .parse() 和 .parseAsync()\n\n`.parse`的第一个参数是要解析的字符串数组，也可以省略参数而使用`process.argv`。\n\n如果参数遵循与 node 不同的约定，可以在第二个参数中传递`from`选项：\n\n- `node`：默认值，`argv[0]`是应用，`argv[1]`是要跑的脚本，后续为用户参数；\n- `electron`：`argv[1]`根据 electron 应用是否打包而变化；\n- `user`：来自用户的所有参数。\n\n例如：\n\n```js\nprogram.parse(process.argv); // 指明，按 node 约定\nprogram.parse(); // 默认，自动识别 electron\nprogram.parse(['-f', 'filename'], { from: 'user' });\n```\n\n### 解析配置\n\n当默认的解析方式无法满足需要，Commander 也提供了其他的解析行为。\n\n默认情况下，程序的选项在子命令前后均可被识别。如要只允许选项出现在子命令之前，可以使用`.enablePositionalOptions()`。这样可以在命令和子命令中使用意义不同的同名选项。\n\n示例代码：[positional-options.js](./examples/positional-options.js)\n\n当启用了带顺序的选项解析，以下程序中，`-b`选项在第一行中将被解析为程序顶层的选项，而在第二行中则被解析为子命令的选项：\n\n```sh\nprogram -b subcommand\nprogram subcommand -b\n```\n\n默认情况下，选项在命令参数前后均可被识别。如要使选项仅在命令参数前被识别，可以使用`.passThroughOptions()`。这样可以把参数和跟随的选项传递给另一程序，而无需使用`--`来终止选项解析。\n如要在子命令中使用此功能，必须首先启用带顺序的选项解析。\n\n示例代码：[pass-through-options.js](./examples/pass-through-options.js)\n\n当启用此功能时，以下程序中，`--port=80`在第一行中会被解析为程序的选项，而在第二行中则会被解析为一个命令参数：\n\n```sh\nprogram --port=80 arg\nprogram arg --port=80\n```\n\n默认情况下，使用未知选项会提示错误。如要将未知选项视作普通命令参数，并继续处理其他部分，可以使用`.allowUnknownOption()`。这样可以混用已知和未知的选项。\n\n默认情况下，传入过多的命令参数并不会报错。可以使用`.allowExcessArguments(false)`来启用这一检查。\n\n### 作为属性的遗留选项\n\n在 Commander 7 以前，选项的值是作为属性存储在命令对象上的。\n这种处理方式便于实现，但缺点在于，选项可能会与`Command`的已有属性相冲突。通过使用`.storeOptionsAsProperties()`，可以恢复到这种旧的处理方式，并可以不加改动地继续运行遗留代码。\n\n```js\nprogram\n  .storeOptionsAsProperties()\n  .option('-d, --debug')\n  .action((commandAndOptions) => {\n    if (commandAndOptions.debug) {\n      console.error(`Called ${commandAndOptions.name()}`);\n    }\n  });\n```\n\n### TypeScript\n\n如果你使用 ts-node，并有`.ts`文件作为独立可执行文件，那么需要用 node 运行你的程序以使子命令能正确调用，例如：\n\n```sh\nnode -r ts-node/register pm.ts\n```\n\n### createCommand()\n\n使用这个工厂方法可以创建新命令，此时不需要使用`new`，如\n\n```bash\nconst { createCommand } = require('commander');\nconst program = createCommand();\n```\n\n`createCommand`同时也是`Command`对象的一个方法，可以创建一个新的命令（而非子命令），使用`.command()`创建子命令时内部会调用该方法，具体使用方式可参考 [custom-command-class.js](./examples/custom-command-class.js)。\n\n### Node 选项，如 --harmony\n\n要使用`--harmony`等选项有以下两种方式：\n\n- 在子命令脚本中加上`#!/usr/bin/env node --harmony`。注：Windows 系统不支持；\n- 调用时加上`--harmony`参数，例如`node --harmony examples/pm publish`。`--harmony`选项在开启子进程时仍会保留。\n\n### 调试子命令\n\n一个可执行的子命令会作为单独的子进程执行。\n\n如果使用 node inspector 的`node -inspect`等命令来[调试](https://nodejs.org/en/docs/guides/debugging-getting-started/)可执行命令，对于生成的子命令，inspector 端口会递增 1。\n\n如果想使用 VSCode 调试，则需要在`launch.json`配置文件里设置`\"autoAttachChildProcesses\": true`。\n\n### 显示错误\n\n你可用于针对自己的错误情况调用 Commander 错误处理。（另请参阅下一节有关退出处理的内容）\n\n除了错误消息，你还可以选择指定 `exitCode`（与 `process.exit` 一起使用）和 `code`（与 `CommanderError` 一起使用）\n\n```js\nprogram.error('Password must be longer than four characters');\nprogram.error('Custom processing has failed', { exitCode: 2, code: 'my.custom.error' });\n```\n\n### 重写退出和输出\n\n默认情况下，在检测到错误、打印帮助信息或版本信息时 Commander 会调用`process.exit`方法。其默认实现会抛出一个`CommanderError`，可以重写该方法并提供一个回调函数（可选）。\n\n回调函数的参数为`CommanderError`，属性包括 Number 型的`exitCode`、String 型的`code`和`message`。子命令完成调用后会开始异步处理。正常情况下，打印错误信息、帮助信息或版本信息不会被重写影响，因为重写会发生在打印之后。\n\n```js\nprogram.exitOverride();\n\ntry {\n  program.parse(process.argv);\n} catch (err) {\n  // 自定义处理...\n}\n```\n\nCommander 默认用作命令行应用，其输出写入 stdout 和 stderr。\n对于其他应用类型，这一行为可以修改。并且可以修改错误信息的展示方式。\n\n示例代码：[configure-output.js](./examples/configure-output.js)\n\n```js\nfunction errorColor(str) {\n  // 添加 ANSI 转义字符，以将文本输出为红色\n  return `\\x1b[31m${str}\\x1b[0m`;\n}\n\nprogram\n  .configureOutput({\n    // 此处使输出变得容易区分\n    writeOut: (str) => process.stdout.write(`[OUT] ${str}`),\n    writeErr: (str) => process.stdout.write(`[ERR] ${str}`),\n    // 将错误高亮显示\n    outputError: (str, write) => write(errorColor(str))\n  });\n```\n\n### 其他文档\n\n请参考关于如下话题的其他文档：\n\n- [不再推荐使用的功能](./docs/zh-CN/%E4%B8%8D%E5%86%8D%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8%E7%9A%84%E5%8A%9F%E8%83%BD.md)。这些功能仍受到支持，以保证向后兼容。\n- [可变参数的选项](./docs/zh-CN/%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0%E7%9A%84%E9%80%89%E9%A1%B9.md)\n\n## 支持\n\n当前版本的 Commander 在 LTS 版本的 Node.js 上完全支持。并且至少需要 v18。\n（使用更低版本 Node.js 的用户建议安装更低版本的 Commander）\n\n社区支持请访问项目的 [Issues](https://github.com/tj/commander.js/issues)。\n\n### 企业使用 Commander\n\n作为 Tidelift 订阅的一部分。\n\nCommander 和很多其他包的维护者已与 Tidelift 合作，面向企业提供开源依赖的商业支持与维护。企业可以向相关依赖包的维护者支付一定的费用，帮助企业节省时间，降低风险，改进代码运行情况。[了解更多](https://tidelift.com/subscription/pkg/npm-commander?utm_source=npm-commander&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://tidelift.com/security).\nTidelift will coordinate the fix and disclosure.\n\nPlease do not report security vulnerabilities through public GitHub issues or pull requests.\n"
  },
  {
    "path": "docs/deprecated.md",
    "content": "# Deprecated\n\nThese features are deprecated, which means they may go away in a future major version of Commander.\nThey are currently still available for backwards compatibility, but should not be used in new code.\n\n- [Deprecated](#deprecated)\n    - [RegExp .option() parameter](#regexp-option-parameter)\n    - [noHelp](#nohelp)\n    - [Callback to .help() and .outputHelp()](#callback-to-help-and-outputhelp)\n    - [.on('--help')](#on--help)\n    - [.on('command:\\*')](#oncommand)\n    - [.command('\\*')](#command)\n    - [cmd.description(cmdDescription, argDescriptions)](#cmddescriptioncmddescription-argdescriptions)\n    - [InvalidOptionArgumentError](#invalidoptionargumenterror)\n    - [Import from `commander/esm.mjs`](#import-from-commanderesmmjs)\n    - [cmd.\\_args](#cmd_args)\n    - [.addHelpCommand(string|boolean|undefined)](#addhelpcommandstringbooleanundefined)\n  - [Removed](#removed)\n    - [Short option flag longer than a single character](#short-option-flag-longer-than-a-single-character)\n    - [Default import of global Command object](#default-import-of-global-command-object)\n\n### RegExp .option() parameter\n\nThe `.option()` method allowed a RegExp as the third parameter to restrict what values were accepted.\n\n```js\nprogram.option('-c,--coffee <type>', 'coffee', /short-white|long-black/);\n```\n\nRemoved from README in Commander v3. Deprecated from Commander v7.\n\nThe newer functionality is the Option `.choices()` method, or using a custom option processing function.\n\n### noHelp\n\nThis was an option passed to `.command()` to hide the command from the built-in help:\n\n```js\nprogram.command('example', 'example command', { noHelp: true });\n```\n\nThe option was renamed `hidden` in Commander v5.1. Deprecated from Commander v7.\n\n### Callback to .help() and .outputHelp()\n\nThese routines allowed a callback parameter to process the built-in help before display.\n\n```js\nprogram.outputHelp((text) => {\n  return colors.red(text);\n});\n```\n\nThe newer approach is to directly access the built-in help text using `.helpInformation()`.\n\n```js\nconsole.error(colors.red(program.helpInformation()));\n```\n\nDeprecated from Commander v7.\n\n### .on('--help')\n\nThis was the way to add custom help after the built-in help. From Commander v3.0.0 this used the custom long help option flags, if changed.\n\n```js\nprogram.on('--help', function() {\n  console.log('')\n  console.log('Examples:');\n  console.log('  $ custom-help --help');\n  console.log('  $ custom-help -h');\n});\n```\n\nThe replacement is `.addHelpText()`:\n\n```js\nprogram.addHelpText('after', `\nExamples:\n  $ custom-help --help\n  $ custom-help -h`\n);\n```\n\nDeprecated from Commander v7.\n\n### .on('command:*')\n\nThis was emitted when the command argument did not match a known subcommand (as part of the implementation of `.command('*')`).\n\nOne use was for adding an error for an unknown subcommand. An error is now the default built-in behaviour.\n\nA second related use was for making a suggestion for an unknown subcommand. The replacement built-in support is `.showSuggestionAfterError()`,\nor for custom behaviour catch the `commander.unknownCommand` error.\n\nDeprecated from Commander v8.3.\n\n### .command('*')\n\nThis was used to add a default command to the program.\n\n```js\nprogram\n  .command('*')\n  .action(() => console.log('List files by default...'));\n```\n\nYou may now pass a configuration option of `isDefault: true` when adding a command, whether using a subcommand with an action handler or a stand-alone executable subcommand.\n\n```js\nprogram\n  .command('list', { isDefault: true })\n  .action(() => console.log('List files by default...'));\n```\n\nRemoved from README in Commander v5. Deprecated from Commander v8.3.\n\n### cmd.description(cmdDescription, argDescriptions)\n\nThis was used to add command argument descriptions for the help.\n\n```js\nprogram\n  .command('price <book>')\n  .description('show price of book', {\n    book: 'ISBN number for book'\n  });\n```\n\nThe new approach is to use the `.argument()` method.\n\n```js\nprogram\n  .command('price')\n  .description('show price of book')\n  .argument('<book>', 'ISBN number for book');\n```\n\nDeprecated from Commander v8.\n\n### InvalidOptionArgumentError\n\nThis was used for throwing an error from custom option processing, for a nice error message.\n\n```js\nfunction myParseInt(value, dummyPrevious) {\n  // parseInt takes a string and a radix\n  const parsedValue = parseInt(value, 10);\n  if (isNaN(parsedValue)) {\n    throw new commander.InvalidOptionArgumentError('Not a number.');\n  }\n  return parsedValue;\n}\n```\n\nThe replacement is `InvalidArgumentError` since can be used now for custom command-argument processing too.\n\n```js\nfunction myParseInt(value, dummyPrevious) {\n  // parseInt takes a string and a radix\n  const parsedValue = parseInt(value, 10);\n  if (isNaN(parsedValue)) {\n    throw new commander.InvalidArgumentError('Not a number.');\n  }\n  return parsedValue;\n}\n```\n\nDeprecated from Commander v8.\n\n### Import from `commander/esm.mjs`\n\nThe first support for named imports required an explicit entry file.\n\n```js\nimport { Command } from 'commander/esm.mjs';\n```\n\nThis is no longer required, just import directly from the module.\n\n```js\nimport { Command } from 'commander';\n```\n\nREADME updated in Commander v9. Deprecated from Commander v9.\n\n### cmd._args\n\nThis was always private, but was previously the only way to access the command `Argument` array.\n\n```js\nconst registeredArguments = program._args;\n```\n\nThe registered command arguments are now accessible via `.registeredArguments`.\n\n```js\nconst registeredArguments = program.registeredArguments;\n```\n\nDeprecated from Commander v11.\n\n### .addHelpCommand(string|boolean|undefined)\n\nThis was originally used with a variety of parameters, but not by passing a Command object despite the \"add\" name.\n\n```js\nprogram.addHelpCommand('assist  [command]');\nprogram.addHelpCommand('assist', 'show assistance');\nprogram.addHelpCommand(false);\n\n```\n\nIn new code you configure the help command with `.helpCommand()`. Or use `.addHelpCommand()` which now takes a Command object, like `.addCommand()`.\n\n```js\nprogram.helpCommand('assist [command]');\nprogram.helpCommand('assist', 'show assistance');\nprogram.helpCommand(false);\n\nprogram.addHelpCommand(new Command('assist').argument('[command]').description('show assistance'));\n```\n\n- Removed from README in Commander v12.\n- Deprecated from Commander v12.\n\n## Removed\n\n### Short option flag longer than a single character\n\nShort option flags like `-ws` were never supported, but the old README did not make this clear. The README now states that short options are a single character.\n\n- README updated in Commander v3.\n- Deprecated from Commander v9.\n- Throws an exception in Commander v13. Deprecated and gone!\n- Replacement added in Commander v13.1 with support for dual long options, like `--ws, --workspace`.\n\n### Default import of global Command object\n\nThe default import was a global Command object.\n\n```js\nconst program = require('commander');\n```\n\nThe global Command object is exported as `program` from Commander v5, or import the Command object.\n\n```js\nconst { program } = require('commander');\n// or\nconst { Command } = require('commander');\nconst program = new Command()\n```\n\n- Removed from README in Commander v5.\n- Deprecated from Commander v7.\n- Removed from TypeScript declarations in Commander v8.\n- Removed from CommonJS in Commander v12. Deprecated and gone!\n"
  },
  {
    "path": "docs/help-in-depth.md",
    "content": "# Help in Depth\n\nThe built-in help is formatted using the Help class.\nYou can configure the Help behaviour by modifying data properties and methods using `.configureHelp()`, or by subclassing using `.createHelp()` if you prefer.\n\nExample file: [configure-help.js](../examples/configure-help.js)\n\n```js\nprogram.configureHelp({\n  sortSubcommands: true,\n  subcommandTerm: (cmd) => cmd.name() // Just show the name, instead of short usage.\n});\n```\n\n- [Help in Depth](#help-in-depth)\n  - [Data Properties](#data-properties)\n  - [Stringify and Style](#stringify-and-style)\n  - [Layout](#layout)\n\n## Data Properties\n\nThe data properties are:\n\n- `helpWidth`: specify the wrap width, useful for unit tests\n- `minWidthToWrap`: specify required width to allow wrapping (default 40)\n- `showGlobalOptions`: show a section with the global options from the parent command(s)\n- `sortSubcommands`: sort the subcommands alphabetically\n- `sortOptions`: sort the options alphabetically\n\nExample files:\n- [configure-help.js](../examples/configure-help.js)\n- [global-options-nested.js](../examples/global-options-nested.js)\n\n## Stringify and Style\n\nThe `Help` object has narrowly focused methods to allow customising the displayed help.\n\nThe stringify routines take an object (`Command` or `Option` or `Argument`) and produce a string. For example you could change the way subcommands are listed:\n\n```js\nprogram.configureHelp({\n  subcommandTerm: (cmd) => cmd.name() // just show the name instead of usage\n});\n```\n\nThe style routines take just a string. For example to make the titles bold:\n\n```js\nimport { styleText } from 'node:util';\nprogram.configureHelp({\n   styleTitle: (str) => styleText('bold', str)\n});\n```\n\nThere is built-in support for detecting whether the output has colors, and respecting environment variables for `NO_COLOR`, `FORCE_COLOR`, and `CLIFORCE_COLOR`. The style routines always get called and color is stripped afterwards if needed using `Command.configureOutput().stripColor()`.\n\nThis annotated help output shows where the stringify and style routines are used. The first output is for a program with subcommands, and the second output is for a subcommand with arguments. \n\n\n```text\nUsage: color-help [options] [command]\n<-1--> <-------------2-------------->\n       <---a----> <---b---> <---c--->\n\nprogram description\n<--------3-------->\n\nOptions:\n<--1--->\n  -h, --help               display help for command\n  <---4---->               <---------5------------>\n\nCommands:\n<---1--->\n  print [options] <files>  print files\n  <----------6---------->  <----7---->\n  <-b-> <---c---> <--d-->\n```\n\n|  | stringify(object) | style(string) | default style |\n| - | - | - | - |\n| 1 | | styleTitle | |\n| 2 | commandUsage | styleUsage | a, b, c, d |\n| 3 | commandDescription | styleCommandDescription | styleDescriptionText |\n| 4 | optionTerm | styleOptionTerm | styleOptionText |\n| 5 | optionDescription | styleOptionDescription | styleDescriptionText |\n| 6 | subcommandTerm | styleSubcommandTerm | b, c, d |\n| 7 | subcommandDescription | styleSubcommandDescription |  styleDescriptionText|\n| 8 | argumentTerm | styleArgumentTerm | styleArgumentText |\n| 9 | argumentDescription | styleArgumentDescription | styleDescriptionText |\n| a | | styleCommandText | |\n| b | | styleOptionText | |\n| c | | styleSubcommandText | |\n| d | | styleArgumentText | |\n\n```text\nUsage: color-help print [options] <files...>\n<-1--> <---------------2------------------->\n       <---a----> <-c-> <---b---> <---d---->\n\nArguments:\n<---1---->\n  files  files to queue for printing\n  <-8->  <------------9------------>\n...\n```\n\nColor example files:\n\n- [color-help.mjs](../examples/color-help.mjs)\n- [color-help-replacement.mjs](../examples/color-help-replacement.mjs)\n\nStringify example files (`subcommandTerm`):\n\n- [help-subcommands-usage.js](../examples/help-subcommands-usage.js)\n- [configure-help.js](../examples/configure-help.js)\n\n## Layout\n\nUtility methods which control the layout include `padWidth`, `boxWrap`, and `formatItem`. These can be overridden to change the layout or replace with an alternative implementation.\n\nExample files:\n\n- `formatItem`: [help-centered.mjs](../examples/help-centered.mjs)\n- `formatItem`: [man-style-help.mjs](../examples/man-style-help.mjs)\n- `boxwrap`: [color-help-replacement.mjs](../examples/color-help-replacement.mjs)\n\n"
  },
  {
    "path": "docs/options-in-depth.md",
    "content": "<!-- omit from toc -->\n# Options in Depth\n\nThe README covers declaring and using options, and mostly parsing will work the way you and your users expect. This page covers some special cases\nand subtle issues in depth.\n\n- [Options taking varying numbers of option-arguments](#options-taking-varying-numbers-of-option-arguments)\n  - [Parsing ambiguity](#parsing-ambiguity)\n    - [Alternative: Make `--` part of your syntax](#alternative-make----part-of-your-syntax)\n    - [Alternative: Put options last](#alternative-put-options-last)\n    - [Alternative: Use options instead of command-arguments](#alternative-use-options-instead-of-command-arguments)\n- [Combining short options, and options taking arguments](#combining-short-options-and-options-taking-arguments)\n  - [Combining short options as if boolean](#combining-short-options-as-if-boolean)\n\n## Options taking varying numbers of option-arguments\n\nCertain options take a varying number of arguments:\n\n```js\nprogram\n   .option('-c, --compress [percentage]') // 0 or 1\n   .option('--preprocess <file...>') // 1 or more\n   .option('--test [name...]') // 0 or more\n```\n\nThis section uses examples with options taking 0 or 1 arguments, but the discussions also apply to variadic options taking more arguments.\n\nFor information about terms used in this document see: [terminology](./terminology.md)\n\n### Parsing ambiguity\n\nThere is a potential downside to be aware of. If a command has both\ncommand-arguments and options with varying option-arguments, this introduces a parsing ambiguity which may affect the user of your program.\nCommander looks for option-arguments first, but the user may\nintend the argument following the option as a command or command-argument.\n\n```js\nprogram\n  .name('cook')\n  .argument('[technique]')\n  .option('-i, --ingredient [ingredient]', 'add cheese or given ingredient')\n  .action((technique, options) => {\n    console.log(`technique: ${technique}`);\n    const ingredient = (options.ingredient === true) ? 'cheese' : options.ingredient;\n    console.log(`ingredient: ${ingredient}`);\n  });\n\nprogram.parse();\n```\n\n```sh\n$ cook scrambled\ntechnique: scrambled\ningredient: undefined\n\n$ cook -i\ntechnique: undefined\ningredient: cheese\n\n$ cook -i egg\ntechnique: undefined\ningredient: egg\n\n$ cook -i scrambled  # oops\ntechnique: undefined\ningredient: scrambled\n```\n\nThe explicit way to resolve this is use `--` to indicate the end of the options and option-arguments:\n\n```sh\n$ node cook.js -i -- scrambled\ntechnique: scrambled\ningredient: cheese\n```\n\nIf you want to avoid your users needing to learn when to use `--`, there are a few approaches you could take.\n\n#### Alternative: Make `--` part of your syntax\n\nRather than trying to teach your users what `--` does, you could just make it part of your syntax.\n\n```js\nprogram.usage('[options] -- [technique]');\n```\n\n```sh\n$ cook --help\nUsage: cook [options] -- [technique]\n\nOptions:\n  -i, --ingredient [ingredient]  add cheese or given ingredient\n  -h, --help                     display help for command\n\n$ cook -- scrambled\ntechnique: scrambled\ningredient: undefined\n\n$ cook -i -- scrambled\ntechnique: scrambled\ningredient: cheese\n```\n\n#### Alternative: Put options last\n\nCommander follows the GNU convention for parsing and allows options before or after the command-arguments, or intermingled.\nSo by putting the options last, the command-arguments do not get confused with the option-arguments.\n\n```js\nprogram.usage('[technique] [options]');\n```\n\n```sh\n$ cook --help\nUsage: cook [technique] [options]\n\nOptions:\n  -i, --ingredient [ingredient]  add cheese or given ingredient\n  -h, --help                     display help for command\n\n$ node cook.js scrambled -i\ntechnique: scrambled\ningredient: cheese\n```\n\n#### Alternative: Use options instead of command-arguments\n\nThis is a bit more radical, but completely avoids the parsing ambiguity!\n\n```js\nprogram\n  .name('cook')\n  .option('-t, --technique <technique>', 'cooking technique')\n  .option('-i, --ingredient [ingredient]', 'add cheese or given ingredient')\n  .action((options) => {\n    console.log(`technique: ${options.technique}`);\n    const ingredient = (options.ingredient === true) ? 'cheese' : options.ingredient;\n    console.log(`ingredient: ${ingredient}`);\n  });\n```\n\n```sh\n$ cook -i -t scrambled\ntechnique: scrambled\ningredient: cheese\n```\n\n## Combining short options, and options taking arguments\n\nMultiple boolean short options can be combined after a single `-`, like `ls -al`. You can also include just\na single short option which might take a value, as any following characters will\nbe taken as the value.\n\nThis means that by default you can not combine short options which may take an argument.\n\n```js\nprogram\n  .name('collect')\n  .option(\"-o, --other [count]\", \"other serving(s)\")\n  .option(\"-v, --vegan [count]\", \"vegan serving(s)\")\n  .option(\"-l, --halal [count]\", \"halal serving(s)\");\nprogram.parse(process.argv);\n\nconst opts = program.opts();\nif (opts.other) console.log(`other servings: ${opts.other}`);\nif (opts.vegan) console.log(`vegan servings: ${opts.vegan}`);\nif (opts.halal) console.log(`halal servings: ${opts.halal}`);\n```\n\n```sh\n$ collect -o 3\nother servings: 3\n$ collect -o3\nother servings: 3\n$ collect -l -v\nvegan servings: true\nhalal servings: true\n$ collect -lv  # oops\nhalal servings: v\n```\n\nIf you wish to use options taking varying arguments as boolean options, you need to specify them separately.\n\n```console\n$ collect -a -v -l\nany servings: true\nvegan servings: true\nhalal servings: true\n```\n\n### Combining short options as if boolean\n\nBefore Commander v5, combining a short option and the value was not supported, and combined short flags were always expanded.\nSo `-avl` expanded to `-a -v -l`.\n\nIf you want backwards compatible behaviour, or prefer combining short options as booleans to combining short option and value,\nyou may change the behaviour.\n\nTo modify the parsing of options taking an optional value:\n\n```js\n.combineFlagAndOptionalValue(true)  // `-v45` is treated like `--vegan=45`, this is the default behaviour\n.combineFlagAndOptionalValue(false) // `-vl` is treated like `-v -l`\n```\n"
  },
  {
    "path": "docs/parsing-and-hooks.md",
    "content": "# Parsing life cycle and hooks\n\nThe processing starts with an array of args. Each command processes and removes the options it understands, and passes the remaining args to the next subcommand.\nThe final command calls the action handler.\n\nStarting with top-level command (program):\n\n- parse options: parse recognised options (for this command) and remove from args\n- parse env: look for environment variables (for this command)\n- process implied: set any implied option values (for this command)\n- if the first arg is a subcommand\n    - call `preSubcommand` hooks\n    - pass remaining arguments to subcommand, and process same way\n\nOnce reach final (leaf) command:\n\n- check for missing mandatory options\n- check for conflicting options\n- check for unknown options\n- process remaining args as command-arguments\n- call `preAction` hooks\n- call action handler\n- call `postAction` hooks\n"
  },
  {
    "path": "docs/release-policy.md",
    "content": "# Release Policy\n\nWe follow [Semantic Versioning](http://semver.org/spec/v2.0.0.html), and limit breaking changes to major versions.\n\nThere are major releases about every six months. We do a major release and bump the minimum required node version when LTS Node.js versions reach end-of-life.\n\nThe release notes for major versions highlight breaking changes, and include a section of migration tips for common changes required.\nThe [Changelog](../CHANGELOG.md) lists release notes for all versions.\n\nThe current release line gets all updates: features, bug fixes, and security updates. Older maintenance versions get just security updates for 12 months.\n\n| Version | First Release | Release Note |  Status | End of Life |\n| ------- | ------------- | - | ------- | ----------- |\n| 14.x | 2025-05-18 | [14.0.0](https://github.com/tj/commander.js/releases/tag/v14.0.0) | current | - |\n| 13.x | 2024-12-30 | [13.0.0](https://github.com/tj/commander.js/releases/tag/v13.0.0) | maintenance | 2026-05-18 |\n| <13 | | | end of life | |\n"
  },
  {
    "path": "docs/terminology.md",
    "content": "# Terminology\n\nThe command line arguments are made up of options, option-arguments, commands, and command-arguments.\n\n| Term | Explanation |\n| --- | --- |\n| option | an argument which is a `-` followed by a character, or `--` followed by a word (or hyphenated words), like `-s` or `--short` |\n| option-argument| some options can take an argument |\n| command | a program or command can have subcommands |\n| command-argument | argument for the command (and not an option or option-argument) |\n\nFor example:\n\n```sh\nmy-utility command -o --option option-argument command-argument-1 command-argument-2\n```\n\nIn other references options are sometimes called flags, and command-arguments are sometimes called positional arguments or operands.\n"
  },
  {
    "path": "docs/zh-CN/不再推荐使用的功能.md",
    "content": "# 不再推荐使用的功能\n\n本文中列出的功能不再推荐使用。它们在 Commander 未来的主要版本（major version）中可能被移除。为保证后向兼容，这些功能目前还可以使用，但它们不应被用在新代码中。\n\n- [不再推荐使用的功能](#%E4%B8%8D%E5%86%8D%E6%8E%A8%E8%8D%90%E4%BD%BF%E7%94%A8%E7%9A%84%E5%8A%9F%E8%83%BD)\n  - [.option() 方法的正则表达式参数](#option-%E6%96%B9%E6%B3%95%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%8F%82%E6%95%B0)\n  - [noHelp](#nohelp)\n  - [默认导入的全局 Command 对象](#%E9%BB%98%E8%AE%A4%E5%AF%BC%E5%85%A5%E7%9A%84%E5%85%A8%E5%B1%80-command-%E5%AF%B9%E8%B1%A1)\n  - [.help() 与 .outputHelp() 的回调函数参数](#help-%E4%B8%8E-outputhelp-%E7%9A%84%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0)\n  - [.on('--help')](#on--help)\n  - [.on('command:*')](#oncommand)\n  - [.command('*')](#command)\n  - [cmd.description(cmdDescription, argDescriptions)](#cmddescriptioncmddescription-argdescriptions)\n  - [InvalidOptionArgumentError](#invalidoptionargumenterror)\n  - [短选项标志长于单个字符](#%E7%9F%AD%E9%80%89%E9%A1%B9%E6%A0%87%E5%BF%97%E9%95%BF%E4%BA%8E%E5%8D%95%E4%B8%AA%E5%AD%97%E7%AC%A6)\n\n\n## .option() 方法的正则表达式参数\n\n`.option()`方法可以接受一个正则表达式作为第三个参数，以规定可以接受的选项参数值。\n\n```js\nprogram.option('-c,--coffee <type>', 'coffee', /short-white|long-black/);\n```\n\n该功能从 Commander v3 的文档中被移除。自 Commander v7 起，该功能不再推荐使用。\n\n新的写法是使用`Option`对象的`.choices()`方法，或者使用自定义选项处理函数。\n\n## noHelp\n\n此选项曾被用作传入`.command()`方法，以在内建的帮助信息中隐藏该命令：\n\n```js\nprogram.command('example', 'example command', { noHelp: true });\n```\n\n在 Commander v5.1 中，该选项被更名为`hidden`。自 Commander v7 起`noHelp`不再推荐使用。\n\n## 默认导入的全局 Command 对象\n\nCommander 的默认导入曾是一个全局的`Command`对象。\n\n```js\nconst program = require('commander');\n```\n\n自 Commander v5 后，全局`Command`对象作为 `program`被导出。或者也可以导入`Command`对象。\n\n```js\nconst { program } = require('commander');\n// 或者\nconst { Command } = require('commander');\nconst program = new Command()\n```\n\n- 此功能在 Commander v5 的文档中被移除。\n- 自 Commander v7 起不再推荐使用。\n- 在 Commander v8 的 TypeScript 定义文件中被移除。\n\n## .help() 与 .outputHelp() 的回调函数参数\n\n这两个方法曾允许传入一个回调函数，以在展示前处理帮助信息。\n\n```js\nprogram.outputHelp((text) => {\n  return colors.red(text);\n});\n```\n\n新的写法是直接通过调用`.helpInformation()`来获取帮助文本。\n\n```js\nconsole.error(colors.red(program.helpInformation()));\n```\n\n自 Commander v7 起不再推荐使用。\n\n## .on('--help')\n\n此功能曾被用作在内建的帮助信息后输出自定义的帮助信息。自 Commander v3.0.0 起，如果有自定义的帮助选项，则此方法使用该自定义的帮助选项。\n\n```js\nprogram.on('--help', function() {\n  console.log('')\n  console.log('Examples:');\n  console.log('  $ custom-help --help');\n  console.log('  $ custom-help -h');\n});\n```\n\n替代的方法是使用`.addHelpText()`：\n\n```js\nprogram.addHelpText('after', `\nExamples:\n  $ custom-help --help\n  $ custom-help -h`\n);\n```\n\n自 Commander v7 起不再推荐使用。\n\n## .on('command:*')\n\n当命令参数与已知子命令不匹配时发出此消息（作为 `.command('')` 实现的一部分）。\n\n一种用途是为未知子命令添加错误。错误现在是默认的内置行为。\n\n第二个相关用途是为未知子命令提出建议。替换内置支持是 `.showSuggestionAfterError()`，或者对于自定义行为捕获 `commander.unknownCommand` 错误。\n\n自 Commander v8.3 起不再推荐使用。\n\n## .command('*')\n\n这用于向程序添加默认命令。\n\n```js\nprogram\n  .command('*')\n  .action(() => console.log('List files by default...'));\n```\n\n你现在可以在添加命令时传递 `isDefault: true` 的配置选项，无论是使用带有动作处理程序的子命令还是独立的可执行子命令。\n\n```js\nprogram\n  .command('list', { isDefault: true })\n  .action(() => console.log('List files by default...'));\n```\n\n从 Commander v5 的 README 中删除。自 Commander v8.3 起不再推荐使用。\n\n## cmd.description(cmdDescription, argDescriptions)\n\n此功能曾用来为命令参数添加描述信息。\n\n```js\nprogram\n  .command('price <book>')\n  .description('show price of book', {\n    book: 'ISBN number for book'\n  });\n```\n\n新的写法是使用`.argument()`方法。\n\n```js\nprogram\n  .command('price')\n  .description('show price of book')\n  .argument('<book>', 'ISBN number for book');\n```\n\n自 Commander v8 起不再推荐使用。\n\n## InvalidOptionArgumentError\n\n此类曾被用来在自定义选项处理中抛出错误，以显示错误信息。\n\n```js\nfunction myParseInt(value, dummyPrevious) {\n  // parseInt 参数为字符串和进制数\n  const parsedValue = parseInt(value, 10);\n  if (isNaN(parsedValue)) {\n    throw new commander.InvalidOptionArgumentError('Not a number.');\n  }\n  return parsedValue;\n}\n```\n\n替代的类是`InvalidArgumentError`，它也可用于自定义命令参数处理。\n\n```js\nfunction myParseInt(value, dummyPrevious) {\n  // parseInt 参数为字符串和进制数\n  const parsedValue = parseInt(value, 10);\n  if (isNaN(parsedValue)) {\n    throw new commander.InvalidArgumentError('Not a number.');\n  }\n  return parsedValue;\n}\n```\n\n自 Commander v8 起不再推荐使用。\n\n## 短选项标志长于单个字符\n\n短选项从未支持像 `-ws` 的标识，但旧的 README 并没有明确说明这一点。README 现在声明短选项是单个字符。\n\nREADME 在 Commander v3 更新。自 Commander v9 起不再推荐使用。\n"
  },
  {
    "path": "docs/zh-CN/可变参数的选项.md",
    "content": "# 可变参数的选项\n\nREADME 文档介绍了选项的声明与使用。大多数情况下，选项的解析行为，与您和您程序用户的期望相符。本文将详述一些特殊用例和细节问题。\n\n- [可变参数的选项](#%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0%E7%9A%84%E9%80%89%E9%A1%B9)\n\t- [解析中的歧义](#%E8%A7%A3%E6%9E%90%E4%B8%AD%E7%9A%84%E6%AD%A7%E4%B9%89)\n\t\t- [方案一：让`--`成为语法的一部分](#%E6%96%B9%E6%A1%88%E4%B8%80%EF%BC%9A%E8%AE%A9%60--%60%E6%88%90%E4%B8%BA%E8%AF%AD%E6%B3%95%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86)\n\t\t- [方案二：把选项放在最后](#%E6%96%B9%E6%A1%88%E4%BA%8C%EF%BC%9A%E6%8A%8A%E9%80%89%E9%A1%B9%E6%94%BE%E5%9C%A8%E6%9C%80%E5%90%8E)\n\t\t- [方案三：使用选项替代命令参数](#%E6%96%B9%E6%A1%88%E4%B8%89%EF%BC%9A%E4%BD%BF%E7%94%A8%E9%80%89%E9%A1%B9%E6%9B%BF%E4%BB%A3%E5%91%BD%E4%BB%A4%E5%8F%82%E6%95%B0)\n\t- [合并短选项，和带有参数的选项](#%E5%90%88%E5%B9%B6%E7%9F%AD%E9%80%89%E9%A1%B9%E5%92%8C%E5%B8%A6%E6%9C%89%E5%8F%82%E6%95%B0%E7%9A%84%E9%80%89%E9%A1%B9)\n\t\t- [将短选项视作 boolean 类型选项合并](#%E5%B0%86%E7%9F%AD%E9%80%89%E9%A1%B9%E8%A7%86%E4%BD%9C-boolean-%E7%B1%BB%E5%9E%8B%E9%80%89%E9%A1%B9%E5%90%88%E5%B9%B6)\n\n有些选项可以接受可变数量的参数：\n\n```js\nprogram\n   .option('-c, --compress [percentage]') // 0 或 1 个参数\n   .option('--preprocess <file...>') // 至少 1 个参数\n   .option('--test [name...]') // 0 或多个参数\n```\n\n本文中使用的示例代码接受 0 或 1 个参数。但相关的讨论对接受更多参数的选项同样适用。\n\n关于本文档中使用的术语，参见[术语表](./%E6%9C%AF%E8%AF%AD%E8%A1%A8.md)。\n\n## 解析中的歧义\n\n解析选项时，有一些潜在的问题值得注意。当一个命令既有命令参数，又有选项的时候，在解析过程中有可能出现歧义。这可能会影响用户使用您的程序。\nCommander 首先解析选项的参数，而用户有可能想将选项后面跟的参数作为命令，或是作为命令参数进行解析。\n\n```js\nprogram\n  .name('cook')\n  .argument('[technique]')\n  .option('-i, --ingredient [ingredient]', 'add cheese or given ingredient')\n  .action((technique, options) => {\n    console.log(`technique: ${technique}`);\n    const ingredient = (options.ingredient === true) ? 'cheese' : options.ingredient;\n    console.log(`ingredient: ${ingredient}`);\n  });\n\nprogram.parse();\n```\n\n```sh\n$ cook scrambled\ntechnique: scrambled\ningredient: undefined\n\n$ cook -i\ntechnique: undefined\ningredient: cheese\n\n$ cook -i egg\ntechnique: undefined\ningredient: egg\n\n$ cook -i scrambled  # oops\ntechnique: undefined\ningredient: scrambled\n```\n\n可以通过使用`--`来表示选项和选项参数部分的结束，以此来显式地解决这一冲突：\n\n```sh\n$ node cook.js -i -- scrambled\ntechnique: scrambled\ningredient: cheese\n```\n\n如果不希望强制用户掌握这种使用`--`的写法，您可以尝试以下几种方案。\n\n### 方案一：让`--`成为语法的一部分\n\n与其让用户理解`--`的用法，您也可以直接把它作为程序语法的一部分。\n\n```js\nprogram.usage('[options] -- [technique]');\n```\n\n```sh\n$ cook --help\nUsage: cook [options] -- [technique]\n\nOptions:\n  -i, --ingredient [ingredient]  add cheese or given ingredient\n  -h, --help                     display help for command\n\n$ cook -- scrambled\ntechnique: scrambled\ningredient: undefined\n\n$ cook -i -- scrambled\ntechnique: scrambled\ningredient: cheese\n```\n\n### 方案二：把选项放在最后\n\nCommander 遵循 GNU 解析命令的惯例，允许选项出现在命令参数之前或者之后，也可以将选项和命令参数相互穿插。\n因此，通过要求把选项放在最后，命令参数就不会和选项参数相混淆。\n\n```js\nprogram.usage('[technique] [options]');\n```\n\n```sh\n$ cook --help\nUsage: cook [technique] [options]\n\nOptions:\n  -i, --ingredient [ingredient]  add cheese or given ingredient\n  -h, --help                     display help for command\n\n$ node cook.js scrambled -i\ntechnique: scrambled\ningredient: cheese\n```\n\n### 方案三：使用选项替代命令参数\n\n这个方案虽然有点激进，但是可以完美避免解析中的歧义。\n\n```js\nprogram\n  .name('cook')\n  .option('-t, --technique <technique>', 'cooking technique')\n  .option('-i, --ingredient [ingredient]', 'add cheese or given ingredient')\n  .action((options) => {\n    console.log(`technique: ${options.technique}`);\n    const ingredient = (options.ingredient === true) ? 'cheese' : options.ingredient;\n    console.log(`ingredient: ${ingredient}`);\n  });\n```\n\n```sh\n$ cook -i -t scrambled\ntechnique: scrambled\ningredient: cheese\n```\n\n## 合并短选项和带有参数的选项\n\n多个 boolean 型的短选项可以合并起来写在同一个`-`号后面，比如`ls -al`。同时，你也可以在其中包括一个接受参数的短选项，此时，任何跟在其后的字符都将被视作这个选项的值。\n\n这就是说，默认情况下并不可以把多个带参数的选项合并起来。\n\n```js\nprogram\n  .name('collect')\n  .option(\"-o, --other [count]\", \"other serving(s)\")\n  .option(\"-v, --vegan [count]\", \"vegan serving(s)\")\n  .option(\"-l, --halal [count]\", \"halal serving(s)\");\nprogram.parse(process.argv);\n\nconst opts = program.opts();\nif (opts.other) console.log(`other servings: ${opts.other}`);\nif (opts.vegan) console.log(`vegan servings: ${opts.vegan}`);\nif (opts.halal) console.log(`halal servings: ${opts.halal}`);\n```\n\n```sh\n$ collect -o 3\nother servings: 3\n$ collect -o3\nother servings: 3\n$ collect -l -v\nvegan servings: true\nhalal servings: true\n$ collect -lv  # oops\nhalal servings: v\n```\n\n如果需要使用多个既可用作 boolean，又可以接受参数的选项，只能把它们分别声明。\n\n```\n$ collect -a -v -l\nany servings: true\nvegan servings: true\nhalal servings: true\n```\n\n### 将短选项视作 boolean 类型选项合并\n\n在 Commander v5 之前，并不支持合并短选项和值。合并的 boolean 类型选项会被展开。\n因此，`-avl`将被展开为`-a -v -l`。\n\n如果您需要后向兼容，或是倾向于在短选项合并的时候把它们视作 boolean 类型，可以改变此行为：\n\n```js\n.combineFlagAndOptionalValue(true)  // `-v45` 被视为 `--vegan=45`，这是默认的行为\n.combineFlagAndOptionalValue(false) // `-vl` 被视为 `-v -l`\n```\n"
  },
  {
    "path": "docs/zh-CN/术语表.md",
    "content": "# 术语表\n\n命令行参数由选项（options）、选项参数（option-arguments）、命令（commands），以及命令参数（command-arguments）组成。\n\n|术语|解释|\n|---|---|\n|选项（option）|`-`后跟单个字母，或`--`后跟单词（或以`-`连接的多个单词），例如`-s`及`--short`|\n|选项参数（option-argument）|有的选项可以接受一个参数|\n|命令（command）|一个程序或命令可以包含子命令|\n|命令参数（command-argument）|传给命令的参数（不包含选项或选项参数）|\n\n例如：\n\n```sh\nmy-utility command -o --option option-argument command-argument-1 command-argument-2\n```\n\n在一些其他资料中，选项有时也称为标志（flags），而命令参数也被称为位置参数（positional arguments）或者操作数（operands）。\n"
  },
  {
    "path": "eslint.config.js",
    "content": "const globals = require('globals');\nconst esLintjs = require('@eslint/js');\nconst jest = require('eslint-plugin-jest');\nconst tseslint = require('typescript-eslint');\nconst prettier = require('eslint-config-prettier');\n\n// Only run tseslint on the files that we have included for TypeScript.\nconst tsconfigTsFiles = ['**/*.{ts,mts}']; // match \"include\" in tsconfig.ts.json;\nconst tsconfigJsFiles = ['*.{js,mjs}', 'lib/**/*.{js,mjs}']; // match \"include\" in tsconfig.js.json\n\n// Using tseslint.config adds some type safety and `extends` to simplify customising config array.\nmodule.exports = tseslint.config(\n  // Add recommended rules.\n  esLintjs.configs.recommended,\n  jest.configs['flat/recommended'],\n  // tseslint with different setup for js/ts\n  {\n    files: tsconfigJsFiles,\n    extends: [...tseslint.configs.recommended],\n    languageOptions: {\n      parserOptions: { project: './tsconfig.js.json' },\n    },\n    rules: {\n      '@typescript-eslint/no-var-requires': 'off', // tseslint does not autodetect commonjs context\n      '@typescript-eslint/no-require-imports': 'off', // tseslint does not autodetect commonjs context\n    },\n  },\n  {\n    files: tsconfigTsFiles,\n    extends: [...tseslint.configs.recommended],\n    languageOptions: {\n      parserOptions: { project: './tsconfig.ts.json' },\n    },\n  },\n  prettier, // Do Prettier last so it can override previous configs.\n\n  // Customise rules.\n  {\n    files: ['**/*.{js,mjs,cjs}', '**/*.{ts,mts,cts}'],\n    rules: {\n      'no-else-return': ['error', { allowElseIf: false }],\n    },\n    languageOptions: {\n      globals: {\n        ...globals.node,\n      },\n    },\n  },\n  {\n    files: ['**/*.test.{js,mjs,cjs}'],\n    rules: {\n      'no-unused-vars': 'off', // lots in tests, minimise churn for now\n    },\n  },\n  {\n    files: [...tsconfigTsFiles, ...tsconfigJsFiles],\n    rules: {\n      '@typescript-eslint/ban-ts-comment': [\n        'error',\n        {\n          'ts-expect-error': 'allow-with-description',\n          'ts-ignore': 'allow-with-description',\n          'ts-nocheck': true,\n          'ts-check': true,\n        },\n      ],\n    },\n  },\n);\n"
  },
  {
    "path": "esm.mjs",
    "content": "import commander from './index.js';\n\n// wrapper to provide named exports for ESM.\nexport const {\n  program,\n  createCommand,\n  createArgument,\n  createOption,\n  CommanderError,\n  InvalidArgumentError,\n  InvalidOptionArgumentError, // deprecated old name\n  Command,\n  Argument,\n  Option,\n  Help,\n} = commander;\n"
  },
  {
    "path": "examples/action-this.js",
    "content": "#!/usr/bin/env node\n\n// This example is used as an example in the README for the action handler.\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram\n  .command('serve')\n  .argument('<script>')\n  .option('-p, --port <number>', 'port number', 80)\n  .action(function () {\n    console.error('Run script %s on port %s', this.args[0], this.opts().port);\n  });\n\nprogram.parse();\n\n// Try the following:\n//    node action-this.js serve --port 8080 index.js\n"
  },
  {
    "path": "examples/alias.js",
    "content": "#!/usr/bin/env node\n\n// This example shows giving alternative names for a command.\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram\n  .command('exec')\n  .argument('<script>')\n  .alias('ex')\n  .action((script) => {\n    console.log(`execute: ${script}`);\n  });\n\nprogram\n  .command('print')\n  .argument('<file>')\n  // Multiple aliases is unusual but supported! You can call alias multiple times,\n  // and/or add multiple aliases at once. Only the first alias is displayed in the help.\n  .alias('p')\n  .alias('pr')\n  .aliases(['display', 'show'])\n  .action((file) => {\n    console.log(`print: ${file}`);\n  });\n\nprogram.parse();\n\n// Try the following:\n//    node alias.js --help\n//    node alias.js exec script\n//    node alias.js ex script\n//    node alias.js print file\n//    node alias.js pr file\n//    node alias.js show file\n"
  },
  {
    "path": "examples/argument.js",
    "content": "#!/usr/bin/env node\n\n// This example shows specifying the command arguments using argument() function.\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram\n  .name('connect')\n  .argument('<server>', 'connect to the specified server')\n  .argument('[user]', 'user account for connection', 'guest')\n  .description('Example program with argument descriptions')\n  .action((server, user) => {\n    console.log('server:', server);\n    console.log('user:', user);\n  });\n\nprogram.parse();\n\n// Try the following:\n//    node argument.js --help\n//    node argument.js main.remote.site\n//    node argument.js main.remote.site admin\n"
  },
  {
    "path": "examples/arguments-custom-processing.js",
    "content": "#!/usr/bin/env node\n\n// This is used as an example in the README for:\n//    Custom argument processing\n//    You may specify a function to do custom processing of argument values.\n\nconst commander = require('commander');\nconst program = new commander.Command();\n\nfunction myParseInt(value) {\n  // parseInt takes a string and a radix\n  const parsedValue = parseInt(value, 10);\n  if (isNaN(parsedValue)) {\n    throw new commander.InvalidArgumentError('Not a number.');\n  }\n  return parsedValue;\n}\n\n// The previous value passed to the custom processing is used when processing variadic values.\nfunction mySum(value, total) {\n  return total + myParseInt(value);\n}\n\nprogram\n  .command('add')\n  .argument('<first>', 'integer argument', myParseInt)\n  .argument('[second]', 'integer argument', myParseInt, 1000)\n  .action((first, second) => {\n    console.log(`${first} + ${second} = ${first + second}`);\n  });\n\nprogram\n  .command('sum')\n  .argument('<value...>', 'values to be summed', mySum, 0)\n  .action((total) => {\n    console.log(`sum is ${total}`);\n  });\n\nprogram.parse();\n\n// Try the following:\n//    node arguments-custom-processing add --help\n//    node arguments-custom-processing add 2\n//    node arguments-custom-processing add 12 56\n//    node arguments-custom-processing sum 1 2 3\n//    node arguments-custom-processing sum silly\n"
  },
  {
    "path": "examples/arguments-extra.js",
    "content": "#!/usr/bin/env node\n\n// This is used as an example in the README for extra argument features.\n\nconst commander = require('commander');\nconst program = new commander.Command();\n\nprogram\n  .addArgument(\n    new commander.Argument('<drink-size>', 'drink cup size').choices([\n      'small',\n      'medium',\n      'large',\n    ]),\n  )\n  .addArgument(\n    new commander.Argument('[timeout]', 'timeout in seconds').default(\n      60,\n      'one minute',\n    ),\n  )\n  .action((drinkSize, timeout) => {\n    console.log(`Drink size: ${drinkSize}`);\n    console.log(`Timeout (s): ${timeout}`);\n  });\n\nprogram.parse();\n\n// Try the following:\n//    node arguments-extra.js --help\n//    node arguments-extra.js huge\n//    node arguments-extra.js small\n//    node arguments-extra.js medium 30\n"
  },
  {
    "path": "examples/color-help-replacement.mjs",
    "content": "import stripAnsi from 'strip-ansi';\nimport wrapAnsi from 'wrap-ansi';\nimport {\n  default as chalkStdOut,\n  chalkStderr as chalkStdErr,\n  supportsColor as supportsColorStdout,\n  supportsColorStderr,\n} from 'chalk';\nimport { Command, Help } from 'commander';\n\n// Replace default color and wrapping support with Chalk packages as an example of\n// a deep replacement of layout and style support.\n\n// This example requires chalk and wrap-ansi and strip-ansi, and won't run\n// from a clone of Commander repo without installing them first.\n//\n// For example using npm:\n//    npm install chalk wrap-ansi strip-ansi\n\nclass MyHelp extends Help {\n  constructor() {\n    super();\n    this.chalk = chalkStdOut;\n  }\n\n  prepareContext(contextOptions) {\n    super.prepareContext(contextOptions);\n    if (contextOptions?.error) {\n      this.chalk = chalkStdErr;\n    }\n  }\n\n  displayWidth(str) {\n    return stripAnsi(str).length; // use imported package\n  }\n\n  boxWrap(str, width) {\n    return wrapAnsi(str, width, { hard: true }); // use imported package\n  }\n\n  styleTitle(str) {\n    return this.chalk.bold(str);\n  }\n  styleCommandText(str) {\n    return this.chalk.cyan(str);\n  }\n  styleCommandDescription(str) {\n    return this.chalk.magenta(str);\n  }\n  styleDescriptionText(str) {\n    return this.chalk.italic(str);\n  }\n  styleOptionText(str) {\n    return this.chalk.green(str);\n  }\n  styleArgumentText(str) {\n    return this.chalk.yellow(str);\n  }\n  styleSubcommandText(str) {\n    return this.chalk.blue(str);\n  }\n}\n\nclass MyCommand extends Command {\n  createCommand(name) {\n    return new MyCommand(name);\n  }\n  createHelp() {\n    return Object.assign(new MyHelp(), this.configureHelp());\n  }\n}\n\nconst program = new MyCommand();\n\n// Override the color detection to use Chalk's detection.\n// Chalk overrides color support based on the `FORCE_COLOR` environment variable,\n// and looks for --color and --no-color command-line options.\n// See https://github.com/chalk/chalk?tab=readme-ov-file#supportscolor\n//\n// In general we want stripColor() to be consistent with displayWidth().\nprogram.configureOutput({\n  getOutHasColors: () => supportsColorStdout,\n  getErrHasColors: () => supportsColorStderr,\n  stripColor: (str) => stripAnsi(str),\n});\n\nprogram.description('program description '.repeat(10));\nprogram\n  .option('-s', 'short description')\n  .option('--long <number>', 'long description '.repeat(10))\n  .option('--color', 'force color output') // implemented by chalk\n  .option('--no-color', 'disable color output'); // implemented by chalk\n\nprogram.addHelpText('after', (context) => {\n  const chalk = context.error ? chalkStdErr : chalkStdOut;\n  return chalk.italic('\\nThis is additional help text.');\n});\n\nprogram.command('esses').description('sssss '.repeat(33));\n\nprogram\n  .command('print')\n  .description('print files')\n  .argument('<files...>', 'files to queue for printing')\n  .option('--double-sided', 'print on both sides');\n\nprogram.parse();\n\n// Try the following (after installing the required packages):\n//    node color-help-replacement.mjs --help\n//    node color-help-replacement.mjs --no-color help\n//    FORCE_COLOR=0 node color-help-replacement.mjs help\n//    node color-help-replacement.mjs help print\n"
  },
  {
    "path": "examples/color-help.mjs",
    "content": "import { styleText } from 'node:util'; // from node v20.12.0\nimport { Command } from 'commander';\n\n// Customise colours and styles for help output.\n\nconst program = new Command();\n\nprogram.configureHelp({\n  styleTitle: (str) => styleText('bold', str),\n  styleCommandText: (str) => styleText('cyan', str),\n  styleCommandDescription: (str) => styleText('magenta', str),\n  styleDescriptionText: (str) => styleText('italic', str),\n  styleOptionText: (str) => styleText('green', str),\n  styleArgumentText: (str) => styleText('yellow', str),\n  styleSubcommandText: (str) => styleText('blue', str),\n});\n\nprogram.description('program description '.repeat(10));\nprogram\n  .option('-s', 'short description')\n  .option('--long <number>', 'long description '.repeat(10));\n\nprogram.addHelpText(\n  'after',\n  styleText('italic', '\\nThis is additional help text.'),\n);\n\nprogram.command('esses').description('sssss '.repeat(33));\n\nprogram\n  .command('print')\n  .description('print files')\n  .argument('<files...>', 'files to queue for printing')\n  .option('--double-sided', 'print on both sides');\n\nprogram.parse();\n\n// Try the following:\n//    node color-help.mjs --help\n//    NO_COLOR=1 node color-help.mjs --help\n//    node color-help.mjs help print\n"
  },
  {
    "path": "examples/configure-help.js",
    "content": "const commander = require('commander');\nconst program = new commander.Command();\n\n// This example shows a simple use of configureHelp.\n// This is used as an example in the README.\n// Any method on the Help class can be overridden\n// See: https://github.com/tj/commander.js/blob/master/lib/help.js\n\nprogram.configureHelp({\n  sortSubcommands: true,\n  subcommandTerm: (cmd) => cmd.name(), // Just show the name, instead of short usage.\n});\n\nprogram.command(\n  'zebra <herd-size>',\n  'African equines with distinctive black-and-white striped coats',\n);\nprogram.command(\n  'aardvark [colour]',\n  'medium-sized, burrowing, nocturnal mammal',\n);\nprogram\n  .command('beaver', 'large, semiaquatic rodent')\n  .option('--pond')\n  .option('--river');\n\nprogram.parse();\n\n// Try the following:\n//    node configure-help.js --help\n"
  },
  {
    "path": "examples/configure-output.js",
    "content": "const commander = require('commander');\nconst program = new commander.Command();\n\nfunction errorColor(str) {\n  // Add ANSI escape codes to display text in red.\n  return `\\x1b[31m${str}\\x1b[0m`;\n}\n\nprogram.configureOutput({\n  // Visibly override write routines as example!\n  writeOut: (str) => process.stdout.write(`[OUT] ${str}`),\n  writeErr: (str) => process.stdout.write(`[ERR] ${str}`),\n  // Output errors in red.\n  outputError: (str, write) => write(errorColor(str)),\n});\n\nprogram.version('1.2.3').option('-c, --compress').command('sub-command');\n\nprogram.parse();\n\n// Try the following:\n//    node configure-output.js --version\n//    node configure-output.js --unknown\n//    node configure-output.js --help\n//    node configure-output.js\n"
  },
  {
    "path": "examples/custom-command-class.js",
    "content": "#!/usr/bin/env node\nconst commander = require('commander');\n\n// Use a class override to customise the command and its subcommands.\n\nclass CommandWithTrace extends commander.Command {\n  createCommand(name) {\n    const cmd = new CommandWithTrace(name);\n    // Add an option to subcommands created using `.command()`\n    cmd.option('-t, --trace', 'display extra information when run command');\n    return cmd;\n  }\n}\n\nfunction inspectCommand(command) {\n  // The option value is stored as property on command because we called .storeOptionsAsProperties()\n  console.log(`Called '${command.name()}'`);\n  console.log(`args: ${command.args}`);\n  console.log('opts: %o', command.opts());\n}\n\nconst program = new CommandWithTrace('program')\n  .option('-v, ---verbose')\n  .action((options, command) => {\n    inspectCommand(command);\n  });\n\nprogram\n  .command('serve [params...]')\n  .option('-p, --port <number>', 'port number')\n  .action((params, options, command) => {\n    inspectCommand(command);\n  });\n\nprogram.command('build <target>').action((buildTarget, options, command) => {\n  inspectCommand(command);\n});\n\nprogram.parse();\n\n// Try the following:\n//    node custom-command-class.js --help\n//    node custom-command-class.js serve --help\n//    node custom-command-class.js serve -t -p 80 a b c\n//    node custom-command-class.js build --help\n//    node custom-command-class.js build --trace foo\n"
  },
  {
    "path": "examples/custom-help",
    "content": "#!/usr/bin/env node\n\n// This example shows a simple use of addHelpText.\n// This is used as an example in the README.\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram.option('-f, --foo', 'enable some foo');\n\nprogram.addHelpText(\n  'after',\n  `\n\nExample call:\n  $ custom-help --help`,\n);\n\nprogram.parse(process.argv);\n\n// Try the following:\n//    node custom-help --help\n"
  },
  {
    "path": "examples/custom-help-description",
    "content": "#!/usr/bin/env node\n\n// This example shows changing the flags and description for the help option.\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram\n  .helpOption('-c, --HELP', 'custom help message')\n  .option('-s, --sessions', 'add session support')\n  .option('-t, --template <engine>', 'specify template engine', 'jade');\n\nprogram\n  .command('child')\n  .option('--gender', 'specific gender of child')\n  .action((options) => {\n    console.log('Childsubcommand...');\n  });\n\nprogram.parse(process.argv);\n\n// Try the following:\n//    node custom-help-description -c\n//    node custom-help-description child --HELP\n"
  },
  {
    "path": "examples/custom-help-text.js",
    "content": "#!/usr/bin/env node\n\n// This example shows using addHelpText.\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram.name('awesome');\n\nprogram\n  .addHelpText('beforeAll', 'A W E S O M E\\n')\n  .addHelpText('afterAll', (context) => {\n    if (context.error) {\n      return '\\nHelp being displayed for an error';\n    }\n    return '\\nSee web site for further help';\n  });\n\nprogram\n  .command('extra')\n  .addHelpText('before', 'Note: the extra command does not do anything')\n  .addHelpText(\n    'after',\n    `\nExamples:\n  awesome extra --help\n  awesome help extra`,\n  );\n\nprogram.parse();\n\n// Try the following:\n//    node custom-help-text.js --help\n//    node custom-help-text.js extra --help\n//    node custom-help-text.js\n"
  },
  {
    "path": "examples/custom-version",
    "content": "#!/usr/bin/env node\n\n// This example shows changing the flags and description for the version option.\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram\n  .version('0.0.1', '-v, --VERSION', 'new version message')\n  .option('-s, --sessions', 'add session support')\n  .option('-t, --template <engine>', 'specify template engine', 'jade');\n\nprogram.parse(process.argv);\n\n// Try the following:\n//    node custom-version -v\n//    node custom-version --VERSION\n"
  },
  {
    "path": "examples/defaultCommand.js",
    "content": "#!/usr/bin/env node\n\nconst commander = require('commander');\nconst program = new commander.Command();\n\n// Example program using the command configuration option isDefault to specify the default command.\n\nprogram\n  .command('build')\n  .description('build web site for deployment')\n  .action(() => {\n    console.log('build');\n  });\n\nprogram\n  .command('deploy')\n  .description('deploy web site to production')\n  .action(() => {\n    console.log('deploy');\n  });\n\nprogram\n  .command('serve', { isDefault: true })\n  .description('launch web server')\n  .option('-p,--port <port_number>', 'web port')\n  .action((options) => {\n    console.log(`server on port ${options.port}`);\n  });\n\nprogram.parse(process.argv);\n\n// Try the following:\n//    node defaultCommand.js build\n//    node defaultCommand.js serve -p 8080\n//    node defaultCommand.js -p 443\n"
  },
  {
    "path": "examples/deploy",
    "content": "#!/usr/bin/env node\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram\n  .name('deploy')\n  .version('0.0.1')\n  .option('-c, --config <path>', 'set config path', './deploy.conf');\n\nprogram\n  .command('setup [env]')\n  .description('run setup commands for all envs')\n  .option('-s, --setup_mode <mode>', 'Which setup mode to use', 'normal')\n  .action((env, options) => {\n    env = env || 'all';\n    console.log('read config from %s', program.opts().config);\n    console.log('setup for %s env(s) with %s mode', env, options.setup_mode);\n  });\n\nprogram\n  .command('exec <script>')\n  .alias('ex')\n  .description('execute the given remote cmd')\n  .option('-e, --exec_mode <mode>', 'Which exec mode to use', 'fast')\n  .action((script, options) => {\n    console.log('read config from %s', program.opts().config);\n    console.log(\n      'exec \"%s\" using %s mode and config %s',\n      script,\n      options.exec_mode,\n      program.opts().config,\n    );\n  })\n  .addHelpText(\n    'after',\n    `\nExamples:\n  $ deploy exec sequential\n  $ deploy exec async`,\n  );\n\nprogram.parse(process.argv);\n"
  },
  {
    "path": "examples/description",
    "content": "#!/usr/bin/env node\n\n// This example shows adding a description which is displayed in the help.\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram\n  .version('0.0.1')\n  .description('Application simple description')\n  .option('-f, --foo', 'enable some foo')\n  .option('-b, --bar', 'enable some bar')\n  .option('-B, --baz', 'enable some baz');\n\nprogram.parse(process.argv);\n\nif (!program.args.length) program.help();\n\n// Try the following on macOS or Linux:\n//    ./description -h\n//\n// Try the following:\n//    node description -h\n"
  },
  {
    "path": "examples/global-options-added.js",
    "content": "#!/usr/bin/env node\n\n// This example shows a couple of ways to add a \"global\" option to all of the subcommands.\n// The first approach is to use a subclass and add the option as the subcommand is created.\n// The second approach is to loop over the subcommands after they have been created.\n//\n// The code in this example assumes there is just one level of subcommands.\n//\n// (A different pattern for a \"global\" option is to add it to the root command, rather\n// than to the subcommand. See global-options-nested.js.)\n\nconst { Command } = require('commander');\n\n// Common options can be added when subcommands are created by using a custom subclass.\n// If the options are unsorted in the help, these will appear first.\nclass MyRootCommand extends Command {\n  createCommand(name) {\n    const cmd = new Command(name);\n    cmd.option('-v, --verbose', 'use verbose logging');\n    return cmd;\n  }\n}\n\nconst program = new MyRootCommand();\n\nprogram\n  .command('print')\n  .option('--a4', 'Use A4 sized paper')\n  .action((options) => {\n    console.log('print options: %O', options);\n  });\n\nprogram\n  .command('serve')\n  .option('-p, --port <number>', 'port number for server')\n  .action((options) => {\n    console.log('serve options: %O', options);\n  });\n\n// Common options can be added manually after setting up program and subcommands.\n// If the options are unsorted in the help, these will appear last.\nprogram.commands.forEach((cmd) => {\n  cmd.option('-d, --debug');\n});\n\nprogram.parse();\n\n// Try the following:\n//    node global-options-added.js --help\n//    node global-options-added.js print --help\n//    node global-options-added.js serve --help\n//    node global-options-added.js serve --debug --verbose\n"
  },
  {
    "path": "examples/global-options-nested.js",
    "content": "#!/usr/bin/env node\n\n// This example shows global options on the program which affect all the subcommands.\n// See how to work with global options in the subcommand and display them in the help.\n//\n// (A different pattern for a \"global\" option is to add it to the subcommands, rather\n// than to the program. See global-options-added.js.)\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram.configureHelp({ showGlobalOptions: true }).option('-g, --global');\n\nprogram\n  .command('sub')\n  .option('-l, --local')\n  .action((options, cmd) => {\n    console.log({\n      opts: cmd.opts(),\n      optsWithGlobals: cmd.optsWithGlobals(),\n    });\n  });\n\nprogram.parse();\n\n// Try the following:\n//    node global-options-nested.js --global sub --local\n//    node global-options-nested.js sub --help\n"
  },
  {
    "path": "examples/help-centered.mjs",
    "content": "import { Command, Help } from 'commander';\n\n// Right-justify the terms in the help output.\n// Setup a subclass so we can do simple tweak of formatItem.\n\nclass MyHelp extends Help {\n  formatItem(term, termWidth, description, helper) {\n    // Pre-pad the term at start instead of end.\n    const paddedTerm = term.padStart(\n      termWidth + term.length - helper.displayWidth(term),\n    );\n\n    return super.formatItem(paddedTerm, termWidth, description, helper);\n  }\n}\n\nclass MyCommand extends Command {\n  createCommand(name) {\n    return new MyCommand(name);\n  }\n  createHelp() {\n    return Object.assign(new MyHelp(), this.configureHelp());\n  }\n}\n\nconst program = new MyCommand();\n\nprogram.configureHelp({ MyCommand });\n\nprogram\n  .option('-s', 'short flag')\n  .option('-f, --flag', 'short and long flag')\n  .option('--long <number>', 'long flag');\n\nprogram.command('compile').alias('c').description('compile something');\n\nprogram.command('run', 'run something').command('print', 'print something');\n\nprogram.parse();\n\n// Try the following:\n//    node help-centered.mjs --help\n"
  },
  {
    "path": "examples/help-groups.js",
    "content": "const { Command, Option } = require('commander');\n\n// Show the two approaches for adding help groups, and how to customise the built-in help and version.\n\nconst program = new Command();\nconst devOptionsHeading = 'Development Options:';\nconst managementCommandsHeading = 'Management Commands:';\n\n// The high-level approach is use .optionsGroup() and .commandsGroup() before adding the options/commands.\nconst docker1 = program\n  .command('docker1')\n  .description('help groups created using .optionsGroup() and .commandsGroup()')\n  .addOption(new Option('-h, --hostname <name>', 'container host name'))\n  .addOption(new Option('-p, --port <number>', 'container port number'))\n  .optionsGroup(devOptionsHeading)\n  .option('-d, --debug', 'add extra trace information')\n  .option('-w, --watch', 'run and relaunch service on file changes');\n\ndocker1\n  .command('run')\n  .description('create and run a new container from an image');\ndocker1.command('exec').description('execute a command in a running container');\n\ndocker1.commandsGroup(managementCommandsHeading);\ndocker1.command('images').description('manage images');\ndocker1.command('volumes').description('manage volumes');\n\n// The low-level approach is using .helpGroup() on the Option or Command.\nconst docker2 = program\n  .command('docker2')\n  .description('help groups created using .helpGroup()')\n  .addOption(new Option('-h, --hostname <name>', 'container host name'))\n  .addOption(new Option('-p, --port <number>', 'container port number'))\n  .addOption(\n    new Option('-d, --debug', 'add extra trace information').helpGroup(\n      devOptionsHeading,\n    ),\n  )\n  .addOption(\n    new Option(\n      '-w, --watch',\n      'run and relaunch service on file changes',\n    ).helpGroup(devOptionsHeading),\n  );\n\ndocker2\n  .command('run')\n  .description('create and run a new container from an image');\ndocker2.command('exec').description('execute a command in a running container');\n\ndocker2\n  .command('images')\n  .description('manage images')\n  .helpGroup(managementCommandsHeading);\ndocker2\n  .command('volumes')\n  .description('manage volumes')\n  .helpGroup(managementCommandsHeading);\n\n// Customise group for built-ins by configuring them with default group set.\nprogram\n  .command('built-in')\n  .description('help groups for help and version')\n  .optionsGroup('Built-in Options:')\n  .version('v2.3.4')\n  .helpOption('-h, --help') // or .helpOption(true) to use default flags\n  .commandsGroup('Built-in Commands:')\n  .helpCommand('help [command]'); // or .helpCommand(true) to use default name\n\nprogram.parse();\n\n// Try the following:\n//    node help-groups.js help docker1\n//    node help-groups.js help docker2\n//    node help-groups.js help built-in\n"
  },
  {
    "path": "examples/help-subcommands-usage.js",
    "content": "const commander = require('commander');\n\n// By default the subcommand list includes a fairly simple usage. If you have added a custom usage\n// to the subcommands you may wish to configure the help to show these instead.\n//\n// See also ./configure-help.js which shows configuring the subcommand list to have no usage at all\n// and just the subcommand name.\n\nconst program = new commander.Command().configureHelp({\n  subcommandTerm: (cmd) => cmd.name() + ' ' + cmd.usage(),\n});\n\nprogram\n  .command('make <FILENAME>')\n  .usage('-root ROOTDIR [-abc] <FILENAME>')\n  .requiredOption('--root <ROOTDIR>')\n  .option('-a')\n  .option('-b')\n  .option('-c')\n  .summary('example command with custom usage')\n  .description(\n    'this full description is  displayed in the full help and not in the list of subcommands',\n  );\n\nprogram\n  .command('serve <SERVICE>')\n  .option('--port <PORTNUMBER>')\n  .description('example command with default simple usage');\n\nprogram.parse();\n\n// Try the following:\n//    node help-subcommands-usage help\n"
  },
  {
    "path": "examples/hook.js",
    "content": "#!/usr/bin/env node\n\nconst { Command, Option } = require('commander');\nconst program = new Command();\n\n// This example shows using some hooks for life cycle events.\n\nconst timeLabel = 'command duration';\nprogram\n  .option('--profile', 'show how long command takes')\n  .hook('preAction', (thisCommand) => {\n    if (thisCommand.opts().profile) {\n      console.time(timeLabel);\n    }\n  })\n  .hook('postAction', (thisCommand) => {\n    if (thisCommand.opts().profile) {\n      console.timeEnd(timeLabel);\n    }\n  });\n\nprogram\n  .option('--trace', 'display trace statements for commands')\n  .hook('preAction', (thisCommand, actionCommand) => {\n    if (thisCommand.opts().trace) {\n      console.log('>>>>');\n      console.log(\n        `About to call action handler for subcommand: ${actionCommand.name()}`,\n      );\n      console.log('arguments: %O', actionCommand.args);\n      console.log('options: %o', actionCommand.opts());\n      console.log('<<<<');\n    }\n  });\n\nprogram\n  .option('--env <filename>', 'specify environment file')\n  .hook('preSubcommand', (thisCommand, subcommand) => {\n    if (thisCommand.opts().env) {\n      // One use case for this hook is modifying environment variables before\n      // parsing the subcommand, say by reading .env file.\n      console.log(`Reading ${thisCommand.opts().env}...`);\n      process.env.PORT = 80;\n      console.log(`About to call subcommand: ${subcommand.name()}`);\n    }\n  });\n\nprogram\n  .command('start')\n  .argument('[script]', 'script name', 'server.js')\n  .option('-d, --delay <seconds>', 'how long to delay before starting')\n  .addOption(\n    new Option('-p, --port <number>', 'port number').default(8080).env('PORT'),\n  )\n  .action(async (script, options) => {\n    if (options.delay) {\n      await new Promise((resolve) =>\n        setTimeout(resolve, parseInt(options.delay) * 1000),\n      );\n    }\n    console.log(`Starting ${script} on port ${options.port}`);\n  });\n\n// Some of the hooks or actions are async, so call parseAsync rather than parse.\nprogram.parseAsync().then(() => {});\n\n// Try the following:\n//    node hook.js start\n//    node hook.js --trace start --port 9000 test.js\n//    node hook.js --profile start --delay 5\n//    node hook.js --env=production.env start\n"
  },
  {
    "path": "examples/man-style-help.mjs",
    "content": "import { Command } from 'commander';\n\n// Layout the help like a man page, with the description starting on the next line.\n\nfunction formatItem(term, termWidth, description, helper) {\n  const termIndent = 2;\n  const descIndent = 6;\n  const helpWidth = this.helpWidth || 80;\n\n  // No need to pad term as on its own line.\n  const lines = [' '.repeat(termIndent) + term];\n\n  if (description) {\n    const boxText = helper.boxWrap(description, helpWidth - 6);\n    const descIndentText = ' '.repeat(descIndent);\n    lines.push(\n      descIndentText + boxText.split('\\n').join('\\n' + descIndentText),\n    );\n  }\n\n  lines.push('');\n  return lines.join('\\n');\n}\n\nconst program = new Command();\n\nprogram.configureHelp({ formatItem });\n\nprogram\n  .option('-s', 'short flag')\n  .option('-f, --flag', 'short and long flag')\n  .option('--long <number>', 'l '.repeat(100));\n\nprogram\n  .command('sub1', 'sssss '.repeat(33))\n  .command('sub2', 'subcommand 2 description');\n\nprogram.parse();\n\n// Try the following:\n//    node man-style-help.mjs --help\n"
  },
  {
    "path": "examples/nestedCommands.js",
    "content": "#!/usr/bin/env node\n\nconst commander = require('commander');\nconst program = new commander.Command();\n\n// Commander supports nested subcommands.\n// .command() can add a subcommand with an action handler or an executable.\n// .addCommand() adds a prepared command with an action handler.\n\n// Add nested commands using `.command()`.\nconst brew = program.command('brew');\nbrew.command('tea').action(() => {\n  console.log('brew tea');\n});\nbrew.command('coffee').action(() => {\n  console.log('brew coffee');\n});\n\n// Add nested commands using `.addCommand().\n// The command could be created separately in another module.\nfunction makeHeatCommand() {\n  const heat = new commander.Command('heat');\n  heat.command('jug').action(() => {\n    console.log('heat jug');\n  });\n  heat.command('pot').action(() => {\n    console.log('heat pot');\n  });\n  return heat;\n}\nprogram.addCommand(makeHeatCommand());\n\nprogram.parse(process.argv);\n\n// Try the following:\n//    node nestedCommands.js brew tea\n//    node nestedCommands.js heat jug\n"
  },
  {
    "path": "examples/options-boolean-or-value.js",
    "content": "#!/usr/bin/env node\n\n// This is used as an example in the README for:\n//    Other option types, flag|value\n//    You can specify an option which functions as a flag but may also take a value (declared using square brackets).\n\nconst commander = require('commander');\nconst program = new commander.Command();\n\nprogram.option('-c, --cheese [type]', 'Add cheese with optional type');\n\nprogram.parse(process.argv);\n\nconst options = program.opts();\nif (options.cheese === undefined) console.log('no cheese');\nelse if (options.cheese === true) console.log('add cheese');\nelse console.log(`add cheese type ${options.cheese}`);\n\n// Try the following:\n//    node options-boolean-or-value\n//    node options-boolean-or-value --cheese\n//    node options-boolean-or-value --cheese mozzarella\n"
  },
  {
    "path": "examples/options-common.js",
    "content": "#!/usr/bin/env node\n\n// This is used as an example in the README for:\n//    Common option types, boolean and value\n\nconst commander = require('commander');\nconst program = new commander.Command();\n\nprogram\n  .option('-d, --debug', 'output extra debugging')\n  .option('-s, --small', 'small pizza size')\n  .option('-p, --pizza-type <type>', 'flavour of pizza');\n\nprogram.parse(process.argv);\n\nconst options = program.opts();\nif (options.debug) console.log(options);\nconsole.log('pizza details:');\nif (options.small) console.log('- small pizza size');\nif (options.pizzaType) console.log(`- ${options.pizzaType}`);\n\n// Try the following:\n//    node options-common.js -p\n//    node options-common.js -d -s -p vegetarian\n//    node options-common.js --pizza-type=cheese\n"
  },
  {
    "path": "examples/options-conflicts.js",
    "content": "#!/usr/bin/env node\nconst { Command, Option } = require('commander');\nconst program = new Command();\n\n// You can use .conflicts() with a single string, which is the camel-case name of the conflicting option.\nprogram\n  .command('pay')\n  .addOption(new Option('--cash').conflicts('creditCard'))\n  .addOption(new Option('--credit-card'))\n  .action((options) => {\n    if (options.cash) {\n      console.log('Paying by cash');\n    } else if (options.creditCard) {\n      console.log('Paying by credit card');\n    } else {\n      console.log('Payment method unknown');\n    }\n  });\n\n// The default value for an option does not cause a conflict.\n// A value specified using an environment variable is checked for conflicts.\nprogram\n  .command('source')\n  .addOption(\n    new Option('-p, --port <number>', 'port number for server')\n      .default(80)\n      .env('PORT'),\n  )\n  .addOption(\n    new Option(\n      '--interactive',\n      'prompt for user input instead of listening to a port',\n    ).conflicts('port'),\n  )\n  .action((options) => {\n    if (options.interactive) {\n      console.log('What do you want to do today?');\n    } else {\n      console.log(`Running server on port: ${options.port}`);\n    }\n  });\n\n// You can use .conflicts() with an array of option names.\n// A negated option is not separate from the positive option for conflicts (they have same option name).\nprogram\n  .command('paint')\n  .addOption(\n    new Option('--summer', 'use a mixture of summer colors').conflicts([\n      'autumn',\n      'colour',\n    ]),\n  )\n  .addOption(\n    new Option('--autumn', 'use a mixture of autumn colors').conflicts([\n      'summer',\n      'colour',\n    ]),\n  )\n  .addOption(new Option('--colour <shade>', 'use a single solid colour'))\n  .addOption(new Option('--no-colour', 'leave surface natural'))\n  .action((options) => {\n    let colour = 'not specified';\n    if (options.colour === false) {\n      colour = 'natural';\n    } else if (options.colour) {\n      colour = options.colour;\n    } else if (options.summer) {\n      colour = 'summer';\n    } else if (options.autumn) {\n      colour = 'autumn';\n    }\n    console.log(`Painting colour is ${colour}`);\n  });\n\nprogram.parse();\n\n// Try the following:\n//    node options-conflicts.js pay --cash --credit-card\n//\n//    node options-conflicts.js source\n//    node options-conflicts.js source --interactive\n//    node options-conflicts.js source --port 8080 --interactive\n//    PORT=8080 node options-conflicts.js source --interactive\n//\n//    node options-conflicts.js paint --colour=red --summer\n//    node options-conflicts.js paint --no-colour --autumn\n"
  },
  {
    "path": "examples/options-custom-processing.js",
    "content": "#!/usr/bin/env node\n\n// This is used as an example in the README for:\n//    Custom option processing\n//    You may specify a function to do custom processing of option values.\n\nconst commander = require('commander');\nconst program = new commander.Command();\n\nfunction myParseInt(value) {\n  // parseInt takes a string and a radix\n  const parsedValue = parseInt(value, 10);\n  if (isNaN(parsedValue)) {\n    throw new commander.InvalidArgumentError('Not a number.');\n  }\n  return parsedValue;\n}\n\nfunction increaseVerbosity(dummyValue, previous) {\n  return previous + 1;\n}\n\nfunction collect(value, previous) {\n  return previous.concat([value]);\n}\n\nfunction commaSeparatedList(value) {\n  return value.split(',');\n}\n\nprogram\n  .option('-f, --float <number>', 'float argument', parseFloat)\n  .option('-i, --integer <number>', 'integer argument', myParseInt)\n  .option(\n    '-v, --verbose',\n    'verbosity that can be increased',\n    increaseVerbosity,\n    0,\n  )\n  .option('-c, --collect <value>', 'repeatable value', collect, [])\n  .option('-l, --list <items>', 'comma separated list', commaSeparatedList);\n\nprogram.parse();\n\nconst options = program.opts();\nif (options.float !== undefined) console.log(`float: ${options.float}`);\nif (options.integer !== undefined) console.log(`integer: ${options.integer}`);\nif (options.verbose > 0) console.log(`verbosity: ${options.verbose}`);\nif (options.collect.length > 0) console.log(options.collect);\nif (options.list !== undefined) console.log(options.list);\n\n// Try the following:\n//    node options-custom-processing -f 1e2\n//    node options-custom-processing --integer 2\n//    node options-custom-processing -v -v -v\n//    node options-custom-processing -c a -c b -c c\n//    node options-custom-processing --list x,y,z\n"
  },
  {
    "path": "examples/options-defaults.js",
    "content": "#!/usr/bin/env node\n\n// This is used as an example in the README for:\n//    Default option value\n\nconst commander = require('commander');\nconst program = new commander.Command();\n\nprogram.option(\n  '-c, --cheese <type>',\n  'Add the specified type of cheese',\n  'blue',\n);\n\nprogram.parse();\n\nconsole.log(`cheese: ${program.opts().cheese}`);\n\n// Try the following:\n//    node options-defaults.js\n//    node options-defaults.js --cheese stilton\n"
  },
  {
    "path": "examples/options-env.js",
    "content": "#!/usr/bin/env node\nconst { Command, Option } = require('commander');\nconst program = new Command();\n\nprogram.addOption(\n  new Option('-p, --port <number>', 'specify port number')\n    .default(80)\n    .env('PORT'),\n);\nprogram.addOption(\n  new Option('-c, --colour', 'turn on colour output').env('COLOUR'),\n);\nprogram.addOption(\n  new Option('-C, --no-colour', 'turn off colour output').env('NO_COLOUR'),\n);\nprogram.addOption(\n  new Option('-s, --size <type>', 'specify size of drink')\n    .choices(['small', 'medium', 'large'])\n    .env('SIZE'),\n);\n\nprogram.parse();\nconsole.log(program.opts());\n\n// Try the following:\n//    node options-env.js --help\n//\n//    node options-env.js\n//    PORT=9001 node options-env.js\n//    PORT=9001 node options-env.js --port 123\n//\n//    COLOUR= node options-env.js\n//    COLOUR= node options-env.js --no-colour\n//    NO_COLOUR= node options-env.js\n//    NO_COLOUR= node options-env.js --colour\n//\n//    SIZE=small node options-env.js\n//    SIZE=enormous node options-env.js\n//    SIZE=enormous node options-env.js --size=large\n"
  },
  {
    "path": "examples/options-extra.js",
    "content": "#!/usr/bin/env node\n\n// This is used as an example in the README for extra option features.\n// See also options-env.js for more extensive env examples,\n// and options-conflicts.js for more details about .conflicts().\n\nconst { Command, Option } = require('commander');\nconst program = new Command();\n\nprogram\n  .addOption(new Option('-s, --secret').hideHelp())\n  .addOption(\n    new Option('-t, --timeout <delay>', 'timeout in seconds').default(\n      60,\n      'one minute',\n    ),\n  )\n  .addOption(\n    new Option('-d, --drink <size>', 'drink cup size').choices([\n      'small',\n      'medium',\n      'large',\n    ]),\n  )\n  .addOption(new Option('-p, --port <number>', 'port number').env('PORT'))\n  .addOption(\n    new Option('--donate [amount]', 'optional donation in dollars')\n      .preset('20')\n      .argParser(parseFloat),\n  )\n  .addOption(\n    new Option('--disable-server', 'disables the server').conflicts('port'),\n  )\n  .addOption(\n    new Option('--free-drink', 'small drink included free ').implies({\n      drink: 'small',\n    }),\n  );\n\nprogram.parse();\n\nconsole.log('Options: ', program.opts());\n\n// Try the following:\n//    node options-extra.js --help\n//    node options-extra.js --drink huge\n//    node options-extra.js --free-drink\n//    PORT=80 node options-extra.js\n//    node options-extra.js --donate\n//    node options-extra.js --donate 30.50\n//    node options-extra.js --disable-server --port 8000\n"
  },
  {
    "path": "examples/options-implies.js",
    "content": "#!/usr/bin/env node\nconst { Command, Option } = require('commander');\nconst program = new Command();\n\nprogram\n  .addOption(new Option('--quiet').implies({ logLevel: 'off' }))\n  .addOption(\n    new Option('--log-level <level>')\n      .choices(['info', 'warning', 'error', 'off'])\n      .default('info'),\n  )\n  .addOption(\n    new Option(\n      '-c, --cheese <type>',\n      'Add the specified type of cheese',\n    ).implies({ dairy: true }),\n  )\n  .addOption(\n    new Option('--no-cheese', 'You do not want any cheese').implies({\n      dairy: false,\n    }),\n  )\n  .addOption(new Option('--dairy', 'May contain dairy'));\n\nprogram.parse();\nconsole.log(program.opts());\n\n// Try the following:\n//    node options-implies.js\n//    node options-implies.js --quiet\n//    node options-implies.js --log-level=warning --quiet\n//    node options-implies.js --cheese=cheddar\n//    node options-implies.js --no-cheese\n"
  },
  {
    "path": "examples/options-negatable.js",
    "content": "#!/usr/bin/env node\n\n// This is used as an example in the README for:\n//    Other option types, negatable boolean\n//    You can specify a boolean option long name with a leading `no-` to make it true by default and able to be negated.\n\nconst commander = require('commander');\nconst program = new commander.Command();\n\nprogram\n  .option('--no-sauce', 'Remove sauce')\n  .option('--cheese <flavour>', 'cheese flavour', 'mozzarella')\n  .option('--no-cheese', 'plain with no cheese');\n\nprogram.parse();\n\nconst options = program.opts();\nconst sauceStr = options.sauce ? 'sauce' : 'no sauce';\nconst cheeseStr =\n  options.cheese === false ? 'no cheese' : `${options.cheese} cheese`;\nconsole.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`);\n\n// Try the following:\n//    node options-negatable.js\n//    node options-negatable.js --sauce\n//    node options-negatable.js --cheese=blue\n//    node options-negatable.js --no-sauce --no-cheese\n"
  },
  {
    "path": "examples/options-required.js",
    "content": "#!/usr/bin/env node\n\n// This is used as an example in the README for:\n//    Required option\n//    You may specify a required (mandatory) option using `.requiredOption`.\n//    The option must be specified on the command line, or by having a default value.\n\nconst commander = require('commander');\nconst program = new commander.Command();\n\nprogram.requiredOption('-c, --cheese <type>', 'pizza must have cheese');\n\nprogram.parse();\n\nconsole.log(`Cheese type: ${program.opts().cheese}`);\n\n// Try the following:\n//    node options-required.js\n//    node options-required.js --cheese blue\n"
  },
  {
    "path": "examples/options-variadic.js",
    "content": "#!/usr/bin/env node\n\n// This is used as an example in the README for variadic options.\n\nconst commander = require('commander');\nconst program = new commander.Command();\n\nprogram\n  .option('-n, --number <value...>', 'specify numbers')\n  .option('-l, --letter [value...]', 'specify letters');\n\nprogram.parse();\n\nconsole.log('Options: ', program.opts());\nconsole.log('Remaining arguments: ', program.args);\n\n// Try the following:\n//    node options-variadic.js -n 1 2 3 --letter a b c\n//    node options-variadic.js --letter=A -n80 operand\n//    node options-variadic.js --letter -n 1 -n 2 3 -- operand\n"
  },
  {
    "path": "examples/pass-through-options.js",
    "content": "#!/usr/bin/env node\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram\n  .argument('<utility>')\n  .argument('[args...]')\n  .passThroughOptions()\n  .option('-d, --dry-run')\n  .action((utility, args, options) => {\n    const action = options.dryRun ? 'Would run' : 'Running';\n    console.log(`${action}: ${utility} ${args.join(' ')}`);\n  });\n\nprogram.parse();\n\n// Try the following:\n//    node pass-through-options.js git status\n//    node pass-through-options.js git --version\n//    node pass-through-options.js --dry-run git checkout -b new-branch\n//    node pass-through-options.js git push --dry-run\n"
  },
  {
    "path": "examples/pizza",
    "content": "#!/usr/bin/env node\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram\n  .description('An application for pizza ordering')\n  .option('-p, --peppers', 'Add peppers')\n  .option('-c, --cheese <type>', 'Add the specified type of cheese', 'marble')\n  .option('-C, --no-cheese', 'You do not want any cheese');\n\nprogram.parse();\n\nconst options = program.opts();\nconsole.log('you ordered a pizza with:');\nif (options.peppers) console.log('  - peppers');\nconst cheese = !options.cheese ? 'no' : options.cheese;\nconsole.log('  - %s cheese', cheese);\n\n// Try the following on macOS or Linux:\n//    ./pizza --help\n//\n// Try the following:\n//    ./pizza --help\n//    node pizza --peppers --cheese=blue\n//    node pizza --no-cheese\n"
  },
  {
    "path": "examples/pm",
    "content": "#!/usr/bin/env node\n\nconst { Command } = require('commander');\nconst program = new Command();\n\n// Example of subcommands which are implemented as stand-alone executable files.\n//\n// When `.command()` is invoked with a description argument,\n// this tells Commander that you're going to use a stand-alone executable for the subcommand.\n//\n// Only `install` and `list` are implemented, see pm-install and pm-list.js\n\nprogram\n  .name('pm')\n  .version('0.0.1')\n  .description('Fake package manager')\n  .command('install [package-names...]', 'install one or more packages')\n  .alias('i')\n  .command('search [query]', 'search with optional query')\n  .alias('s')\n  .command('update', 'update installed packages', {\n    executableFile: 'myUpdateSubCommand',\n  })\n  .command('list', 'list packages installed', { isDefault: true });\n\nprogram.parse(process.argv);\n\n// Try the following on macOS or Linux:\n//    ./examples/pm\n//\n// Try the following:\n//    node pm\n//    node pm help install\n//    node pm install -h\n//    node pm install foo bar baz\n//    node pm install foo bar baz --force\n"
  },
  {
    "path": "examples/pm-install",
    "content": "#!/usr/bin/env node\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram.option('-f, --force', 'force installation');\nprogram.argument('[package-names...]');\n\nprogram.parse(process.argv);\n\nconst pkgs = program.args;\n\nif (!pkgs.length) {\n  console.error('packages required');\n  process.exit(1);\n}\n\nconsole.log();\nif (program.opts().force) console.log('  force: install');\npkgs.forEach(function (pkg) {\n  console.log('  install : %s', pkg);\n});\nconsole.log();\n"
  },
  {
    "path": "examples/pm-list.js",
    "content": "#!/usr/bin/env node\n\nconsole.log('list');\n"
  },
  {
    "path": "examples/positional-options.js",
    "content": "#!/usr/bin/env node\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram.enablePositionalOptions().option('-p, --progress');\n\nprogram\n  .command('upload <file>')\n  .option('-p, --port <number>', 'port number', 80)\n  .action((file, options) => {\n    if (program.opts().progress) console.log('Starting upload...');\n    console.log(`Uploading ${file} to port ${options.port}`);\n    if (program.opts().progress) console.log('Finished upload');\n  });\n\nprogram.parse();\n\n// Try the following:\n//    node positional-options.js upload test.js\n//    node positional-options.js -p upload test.js\n//    node positional-options.js upload -p 8080 test.js\n//    node positional-options.js -p upload -p 8080 test.js\n"
  },
  {
    "path": "examples/split.js",
    "content": "const { program } = require('commander');\n\n// This is used as an example in the README for the Quick Start.\n\nprogram.option('--first').option('-s, --separator <char>').argument('<string>');\n\nprogram.parse();\n\nconst options = program.opts();\nconst limit = options.first ? 1 : undefined;\nconsole.log(program.args[0].split(options.separator, limit));\n\n// Try the following:\n//    node split -s / --fits a/b/c\n//    node split -s / --first a/b/c\n//    node split --separator=, a,b,c\n"
  },
  {
    "path": "examples/string-util.js",
    "content": "const { Command } = require('commander');\nconst program = new Command();\n\n// This is used as an example in the README for the Quick Start.\n\nprogram\n  .name('string-util')\n  .description('CLI to some JavaScript string utilities')\n  .version('0.8.0');\n\nprogram\n  .command('split')\n  .description('Split a string into substrings and display as an array.')\n  .argument('<string>', 'string to split')\n  .option('--first', 'display just the first substring')\n  .option('-s, --separator <char>', 'separator character', ',')\n  .action((str, options) => {\n    const limit = options.first ? 1 : undefined;\n    console.log(str.split(options.separator, limit));\n  });\n\nprogram\n  .command('join')\n  .description('Join the command-arguments into a single string')\n  .argument('<strings...>', 'one or more strings')\n  .option('-s, --separator <char>', 'separator character', ',')\n  .action((strings, options) => {\n    console.log(strings.join(options.separator));\n  });\n\nprogram.parse();\n\n// Try the following:\n//    node string-util\n//    node string-util help split\n//    node string-util split --separator=/ a/b/c\n//    node string-util split --first a,b,c\n//    node string-util join a b c d\n"
  },
  {
    "path": "examples/thank.js",
    "content": "#!/usr/bin/env node\n\n// This example is used as an example in the README for the action handler.\n\nconst { Command } = require('commander');\nconst program = new Command();\n\nprogram\n  .argument('<name>')\n  .option('-t, --title <honorific>', 'title to use before name')\n  .option('-d, --debug', 'display some debugging')\n  .action((name, options, command) => {\n    if (options.debug) {\n      console.error('Called %s with options %o', command.name(), options);\n    }\n    const title = options.title ? `${options.title} ` : '';\n    console.log(`Thank-you ${title}${name}`);\n  });\n\nprogram.parse();\n\n// Try the following:\n//    node thank.js John\n//    node thank.js Doe --title Mr\n//    node thank.js --debug Doe --title Mr\n"
  },
  {
    "path": "index.js",
    "content": "const { Argument } = require('./lib/argument.js');\nconst { Command } = require('./lib/command.js');\nconst { CommanderError, InvalidArgumentError } = require('./lib/error.js');\nconst { Help } = require('./lib/help.js');\nconst { Option } = require('./lib/option.js');\n\nexports.program = new Command();\n\nexports.createCommand = (name) => new Command(name);\nexports.createOption = (flags, description) => new Option(flags, description);\nexports.createArgument = (name, description) => new Argument(name, description);\n\n/**\n * Expose classes\n */\n\nexports.Command = Command;\nexports.Option = Option;\nexports.Argument = Argument;\nexports.Help = Help;\n\nexports.CommanderError = CommanderError;\nexports.InvalidArgumentError = InvalidArgumentError;\nexports.InvalidOptionArgumentError = InvalidArgumentError; // Deprecated\n"
  },
  {
    "path": "jest.config.js",
    "content": "const config = {\n  testEnvironment: 'node',\n  collectCoverage: true,\n  transform: {\n    '^.+\\\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.ts.json' }],\n  },\n  testPathIgnorePatterns: ['/node_modules/'],\n};\n\nmodule.exports = config;\n"
  },
  {
    "path": "lib/argument.js",
    "content": "const { InvalidArgumentError } = require('./error.js');\n\nclass Argument {\n  /**\n   * Initialize a new command argument with the given name and description.\n   * The default is that the argument is required, and you can explicitly\n   * indicate this with <> around the name. Put [] around the name for an optional argument.\n   *\n   * @param {string} name\n   * @param {string} [description]\n   */\n\n  constructor(name, description) {\n    this.description = description || '';\n    this.variadic = false;\n    this.parseArg = undefined;\n    this.defaultValue = undefined;\n    this.defaultValueDescription = undefined;\n    this.argChoices = undefined;\n\n    switch (name[0]) {\n      case '<': // e.g. <required>\n        this.required = true;\n        this._name = name.slice(1, -1);\n        break;\n      case '[': // e.g. [optional]\n        this.required = false;\n        this._name = name.slice(1, -1);\n        break;\n      default:\n        this.required = true;\n        this._name = name;\n        break;\n    }\n\n    if (this._name.endsWith('...')) {\n      this.variadic = true;\n      this._name = this._name.slice(0, -3);\n    }\n  }\n\n  /**\n   * Return argument name.\n   *\n   * @return {string}\n   */\n\n  name() {\n    return this._name;\n  }\n\n  /**\n   * @package\n   */\n\n  _collectValue(value, previous) {\n    if (previous === this.defaultValue || !Array.isArray(previous)) {\n      return [value];\n    }\n\n    previous.push(value);\n    return previous;\n  }\n\n  /**\n   * Set the default value, and optionally supply the description to be displayed in the help.\n   *\n   * @param {*} value\n   * @param {string} [description]\n   * @return {Argument}\n   */\n\n  default(value, description) {\n    this.defaultValue = value;\n    this.defaultValueDescription = description;\n    return this;\n  }\n\n  /**\n   * Set the custom handler for processing CLI command arguments into argument values.\n   *\n   * @param {Function} [fn]\n   * @return {Argument}\n   */\n\n  argParser(fn) {\n    this.parseArg = fn;\n    return this;\n  }\n\n  /**\n   * Only allow argument value to be one of choices.\n   *\n   * @param {string[]} values\n   * @return {Argument}\n   */\n\n  choices(values) {\n    this.argChoices = values.slice();\n    this.parseArg = (arg, previous) => {\n      if (!this.argChoices.includes(arg)) {\n        throw new InvalidArgumentError(\n          `Allowed choices are ${this.argChoices.join(', ')}.`,\n        );\n      }\n      if (this.variadic) {\n        return this._collectValue(arg, previous);\n      }\n      return arg;\n    };\n    return this;\n  }\n\n  /**\n   * Make argument required.\n   *\n   * @returns {Argument}\n   */\n  argRequired() {\n    this.required = true;\n    return this;\n  }\n\n  /**\n   * Make argument optional.\n   *\n   * @returns {Argument}\n   */\n  argOptional() {\n    this.required = false;\n    return this;\n  }\n}\n\n/**\n * Takes an argument and returns its human readable equivalent for help usage.\n *\n * @param {Argument} arg\n * @return {string}\n * @private\n */\n\nfunction humanReadableArgName(arg) {\n  const nameOutput = arg.name() + (arg.variadic === true ? '...' : '');\n\n  return arg.required ? '<' + nameOutput + '>' : '[' + nameOutput + ']';\n}\n\nexports.Argument = Argument;\nexports.humanReadableArgName = humanReadableArgName;\n"
  },
  {
    "path": "lib/command.js",
    "content": "const EventEmitter = require('node:events').EventEmitter;\nconst childProcess = require('node:child_process');\nconst path = require('node:path');\nconst fs = require('node:fs');\nconst process = require('node:process');\n\nconst { Argument, humanReadableArgName } = require('./argument.js');\nconst { CommanderError } = require('./error.js');\nconst { Help, stripColor } = require('./help.js');\nconst { Option, DualOptions } = require('./option.js');\nconst { suggestSimilar } = require('./suggestSimilar');\n\nclass Command extends EventEmitter {\n  /**\n   * Initialize a new `Command`.\n   *\n   * @param {string} [name]\n   */\n\n  constructor(name) {\n    super();\n    /** @type {Command[]} */\n    this.commands = [];\n    /** @type {Option[]} */\n    this.options = [];\n    this.parent = null;\n    this._allowUnknownOption = false;\n    this._allowExcessArguments = false;\n    /** @type {Argument[]} */\n    this.registeredArguments = [];\n    this._args = this.registeredArguments; // deprecated old name\n    /** @type {string[]} */\n    this.args = []; // cli args with options removed\n    this.rawArgs = [];\n    this.processedArgs = []; // like .args but after custom processing and collecting variadic\n    this._scriptPath = null;\n    this._name = name || '';\n    this._optionValues = {};\n    this._optionValueSources = {}; // default, env, cli etc\n    this._storeOptionsAsProperties = false;\n    this._actionHandler = null;\n    this._executableHandler = false;\n    this._executableFile = null; // custom name for executable\n    this._executableDir = null; // custom search directory for subcommands\n    this._defaultCommandName = null;\n    this._exitCallback = null;\n    this._aliases = [];\n    this._combineFlagAndOptionalValue = true;\n    this._description = '';\n    this._summary = '';\n    this._argsDescription = undefined; // legacy\n    this._enablePositionalOptions = false;\n    this._passThroughOptions = false;\n    this._lifeCycleHooks = {}; // a hash of arrays\n    /** @type {(boolean | string)} */\n    this._showHelpAfterError = false;\n    this._showSuggestionAfterError = true;\n    this._savedState = null; // used in save/restoreStateBeforeParse\n\n    // see configureOutput() for docs\n    this._outputConfiguration = {\n      writeOut: (str) => process.stdout.write(str),\n      writeErr: (str) => process.stderr.write(str),\n      outputError: (str, write) => write(str),\n      getOutHelpWidth: () =>\n        process.stdout.isTTY ? process.stdout.columns : undefined,\n      getErrHelpWidth: () =>\n        process.stderr.isTTY ? process.stderr.columns : undefined,\n      getOutHasColors: () =>\n        useColor() ?? (process.stdout.isTTY && process.stdout.hasColors?.()),\n      getErrHasColors: () =>\n        useColor() ?? (process.stderr.isTTY && process.stderr.hasColors?.()),\n      stripColor: (str) => stripColor(str),\n    };\n\n    this._hidden = false;\n    /** @type {(Option | null | undefined)} */\n    this._helpOption = undefined; // Lazy created on demand. May be null if help option is disabled.\n    this._addImplicitHelpCommand = undefined; // undecided whether true or false yet, not inherited\n    /** @type {Command} */\n    this._helpCommand = undefined; // lazy initialised, inherited\n    this._helpConfiguration = {};\n    /** @type {string | undefined} */\n    this._helpGroupHeading = undefined; // soft initialised when added to parent\n    /** @type {string | undefined} */\n    this._defaultCommandGroup = undefined;\n    /** @type {string | undefined} */\n    this._defaultOptionGroup = undefined;\n  }\n\n  /**\n   * Copy settings that are useful to have in common across root command and subcommands.\n   *\n   * (Used internally when adding a command using `.command()` so subcommands inherit parent settings.)\n   *\n   * @param {Command} sourceCommand\n   * @return {Command} `this` command for chaining\n   */\n  copyInheritedSettings(sourceCommand) {\n    this._outputConfiguration = sourceCommand._outputConfiguration;\n    this._helpOption = sourceCommand._helpOption;\n    this._helpCommand = sourceCommand._helpCommand;\n    this._helpConfiguration = sourceCommand._helpConfiguration;\n    this._exitCallback = sourceCommand._exitCallback;\n    this._storeOptionsAsProperties = sourceCommand._storeOptionsAsProperties;\n    this._combineFlagAndOptionalValue =\n      sourceCommand._combineFlagAndOptionalValue;\n    this._allowExcessArguments = sourceCommand._allowExcessArguments;\n    this._enablePositionalOptions = sourceCommand._enablePositionalOptions;\n    this._showHelpAfterError = sourceCommand._showHelpAfterError;\n    this._showSuggestionAfterError = sourceCommand._showSuggestionAfterError;\n\n    return this;\n  }\n\n  /**\n   * @returns {Command[]}\n   * @private\n   */\n\n  _getCommandAndAncestors() {\n    const result = [];\n    // eslint-disable-next-line @typescript-eslint/no-this-alias\n    for (let command = this; command; command = command.parent) {\n      result.push(command);\n    }\n    return result;\n  }\n\n  /**\n   * Define a command.\n   *\n   * There are two styles of command: pay attention to where to put the description.\n   *\n   * @example\n   * // Command implemented using action handler (description is supplied separately to `.command`)\n   * program\n   *   .command('clone <source> [destination]')\n   *   .description('clone a repository into a newly created directory')\n   *   .action((source, destination) => {\n   *     console.log('clone command called');\n   *   });\n   *\n   * // Command implemented using separate executable file (description is second parameter to `.command`)\n   * program\n   *   .command('start <service>', 'start named service')\n   *   .command('stop [service]', 'stop named service, or all if no name supplied');\n   *\n   * @param {string} nameAndArgs - command name and arguments, args are `<required>` or `[optional]` and last may also be `variadic...`\n   * @param {(object | string)} [actionOptsOrExecDesc] - configuration options (for action), or description (for executable)\n   * @param {object} [execOpts] - configuration options (for executable)\n   * @return {Command} returns new command for action handler, or `this` for executable command\n   */\n\n  command(nameAndArgs, actionOptsOrExecDesc, execOpts) {\n    let desc = actionOptsOrExecDesc;\n    let opts = execOpts;\n    if (typeof desc === 'object' && desc !== null) {\n      opts = desc;\n      desc = null;\n    }\n    opts = opts || {};\n    const [, name, args] = nameAndArgs.match(/([^ ]+) *(.*)/);\n\n    const cmd = this.createCommand(name);\n    if (desc) {\n      cmd.description(desc);\n      cmd._executableHandler = true;\n    }\n    if (opts.isDefault) this._defaultCommandName = cmd._name;\n    cmd._hidden = !!(opts.noHelp || opts.hidden); // noHelp is deprecated old name for hidden\n    cmd._executableFile = opts.executableFile || null; // Custom name for executable file, set missing to null to match constructor\n    if (args) cmd.arguments(args);\n    this._registerCommand(cmd);\n    cmd.parent = this;\n    cmd.copyInheritedSettings(this);\n\n    if (desc) return this;\n    return cmd;\n  }\n\n  /**\n   * Factory routine to create a new unattached command.\n   *\n   * See .command() for creating an attached subcommand, which uses this routine to\n   * create the command. You can override createCommand to customise subcommands.\n   *\n   * @param {string} [name]\n   * @return {Command} new command\n   */\n\n  createCommand(name) {\n    return new Command(name);\n  }\n\n  /**\n   * You can customise the help with a subclass of Help by overriding createHelp,\n   * or by overriding Help properties using configureHelp().\n   *\n   * @return {Help}\n   */\n\n  createHelp() {\n    return Object.assign(new Help(), this.configureHelp());\n  }\n\n  /**\n   * You can customise the help by overriding Help properties using configureHelp(),\n   * or with a subclass of Help by overriding createHelp().\n   *\n   * @param {object} [configuration] - configuration options\n   * @return {(Command | object)} `this` command for chaining, or stored configuration\n   */\n\n  configureHelp(configuration) {\n    if (configuration === undefined) return this._helpConfiguration;\n\n    this._helpConfiguration = configuration;\n    return this;\n  }\n\n  /**\n   * The default output goes to stdout and stderr. You can customise this for special\n   * applications. You can also customise the display of errors by overriding outputError.\n   *\n   * The configuration properties are all functions:\n   *\n   *     // change how output being written, defaults to stdout and stderr\n   *     writeOut(str)\n   *     writeErr(str)\n   *     // change how output being written for errors, defaults to writeErr\n   *     outputError(str, write) // used for displaying errors and not used for displaying help\n   *     // specify width for wrapping help\n   *     getOutHelpWidth()\n   *     getErrHelpWidth()\n   *     // color support, currently only used with Help\n   *     getOutHasColors()\n   *     getErrHasColors()\n   *     stripColor() // used to remove ANSI escape codes if output does not have colors\n   *\n   * @param {object} [configuration] - configuration options\n   * @return {(Command | object)} `this` command for chaining, or stored configuration\n   */\n\n  configureOutput(configuration) {\n    if (configuration === undefined) return this._outputConfiguration;\n\n    this._outputConfiguration = {\n      ...this._outputConfiguration,\n      ...configuration,\n    };\n    return this;\n  }\n\n  /**\n   * Display the help or a custom message after an error occurs.\n   *\n   * @param {(boolean|string)} [displayHelp]\n   * @return {Command} `this` command for chaining\n   */\n  showHelpAfterError(displayHelp = true) {\n    if (typeof displayHelp !== 'string') displayHelp = !!displayHelp;\n    this._showHelpAfterError = displayHelp;\n    return this;\n  }\n\n  /**\n   * Display suggestion of similar commands for unknown commands, or options for unknown options.\n   *\n   * @param {boolean} [displaySuggestion]\n   * @return {Command} `this` command for chaining\n   */\n  showSuggestionAfterError(displaySuggestion = true) {\n    this._showSuggestionAfterError = !!displaySuggestion;\n    return this;\n  }\n\n  /**\n   * Add a prepared subcommand.\n   *\n   * See .command() for creating an attached subcommand which inherits settings from its parent.\n   *\n   * @param {Command} cmd - new subcommand\n   * @param {object} [opts] - configuration options\n   * @return {Command} `this` command for chaining\n   */\n\n  addCommand(cmd, opts) {\n    if (!cmd._name) {\n      throw new Error(`Command passed to .addCommand() must have a name\n- specify the name in Command constructor or using .name()`);\n    }\n\n    opts = opts || {};\n    if (opts.isDefault) this._defaultCommandName = cmd._name;\n    if (opts.noHelp || opts.hidden) cmd._hidden = true; // modifying passed command due to existing implementation\n\n    this._registerCommand(cmd);\n    cmd.parent = this;\n    cmd._checkForBrokenPassThrough();\n\n    return this;\n  }\n\n  /**\n   * Factory routine to create a new unattached argument.\n   *\n   * See .argument() for creating an attached argument, which uses this routine to\n   * create the argument. You can override createArgument to return a custom argument.\n   *\n   * @param {string} name\n   * @param {string} [description]\n   * @return {Argument} new argument\n   */\n\n  createArgument(name, description) {\n    return new Argument(name, description);\n  }\n\n  /**\n   * Define argument syntax for command.\n   *\n   * The default is that the argument is required, and you can explicitly\n   * indicate this with <> around the name. Put [] around the name for an optional argument.\n   *\n   * @example\n   * program.argument('<input-file>');\n   * program.argument('[output-file]');\n   *\n   * @param {string} name\n   * @param {string} [description]\n   * @param {(Function|*)} [parseArg] - custom argument processing function or default value\n   * @param {*} [defaultValue]\n   * @return {Command} `this` command for chaining\n   */\n  argument(name, description, parseArg, defaultValue) {\n    const argument = this.createArgument(name, description);\n    if (typeof parseArg === 'function') {\n      argument.default(defaultValue).argParser(parseArg);\n    } else {\n      argument.default(parseArg);\n    }\n    this.addArgument(argument);\n    return this;\n  }\n\n  /**\n   * Define argument syntax for command, adding multiple at once (without descriptions).\n   *\n   * See also .argument().\n   *\n   * @example\n   * program.arguments('<cmd> [env]');\n   *\n   * @param {string} names\n   * @return {Command} `this` command for chaining\n   */\n\n  arguments(names) {\n    names\n      .trim()\n      .split(/ +/)\n      .forEach((detail) => {\n        this.argument(detail);\n      });\n    return this;\n  }\n\n  /**\n   * Define argument syntax for command, adding a prepared argument.\n   *\n   * @param {Argument} argument\n   * @return {Command} `this` command for chaining\n   */\n  addArgument(argument) {\n    const previousArgument = this.registeredArguments.slice(-1)[0];\n    if (previousArgument?.variadic) {\n      throw new Error(\n        `only the last argument can be variadic '${previousArgument.name()}'`,\n      );\n    }\n    if (\n      argument.required &&\n      argument.defaultValue !== undefined &&\n      argument.parseArg === undefined\n    ) {\n      throw new Error(\n        `a default value for a required argument is never used: '${argument.name()}'`,\n      );\n    }\n    this.registeredArguments.push(argument);\n    return this;\n  }\n\n  /**\n   * Customise or override default help command. By default a help command is automatically added if your command has subcommands.\n   *\n   * @example\n   *    program.helpCommand('help [cmd]');\n   *    program.helpCommand('help [cmd]', 'show help');\n   *    program.helpCommand(false); // suppress default help command\n   *    program.helpCommand(true); // add help command even if no subcommands\n   *\n   * @param {string|boolean} enableOrNameAndArgs - enable with custom name and/or arguments, or boolean to override whether added\n   * @param {string} [description] - custom description\n   * @return {Command} `this` command for chaining\n   */\n\n  helpCommand(enableOrNameAndArgs, description) {\n    if (typeof enableOrNameAndArgs === 'boolean') {\n      this._addImplicitHelpCommand = enableOrNameAndArgs;\n      if (enableOrNameAndArgs && this._defaultCommandGroup) {\n        // make the command to store the group\n        this._initCommandGroup(this._getHelpCommand());\n      }\n      return this;\n    }\n\n    const nameAndArgs = enableOrNameAndArgs ?? 'help [command]';\n    const [, helpName, helpArgs] = nameAndArgs.match(/([^ ]+) *(.*)/);\n    const helpDescription = description ?? 'display help for command';\n\n    const helpCommand = this.createCommand(helpName);\n    helpCommand.helpOption(false);\n    if (helpArgs) helpCommand.arguments(helpArgs);\n    if (helpDescription) helpCommand.description(helpDescription);\n\n    this._addImplicitHelpCommand = true;\n    this._helpCommand = helpCommand;\n    // init group unless lazy create\n    if (enableOrNameAndArgs || description) this._initCommandGroup(helpCommand);\n\n    return this;\n  }\n\n  /**\n   * Add prepared custom help command.\n   *\n   * @param {(Command|string|boolean)} helpCommand - custom help command, or deprecated enableOrNameAndArgs as for `.helpCommand()`\n   * @param {string} [deprecatedDescription] - deprecated custom description used with custom name only\n   * @return {Command} `this` command for chaining\n   */\n  addHelpCommand(helpCommand, deprecatedDescription) {\n    // If not passed an object, call through to helpCommand for backwards compatibility,\n    // as addHelpCommand was originally used like helpCommand is now.\n    if (typeof helpCommand !== 'object') {\n      this.helpCommand(helpCommand, deprecatedDescription);\n      return this;\n    }\n\n    this._addImplicitHelpCommand = true;\n    this._helpCommand = helpCommand;\n    this._initCommandGroup(helpCommand);\n    return this;\n  }\n\n  /**\n   * Lazy create help command.\n   *\n   * @return {(Command|null)}\n   * @package\n   */\n  _getHelpCommand() {\n    const hasImplicitHelpCommand =\n      this._addImplicitHelpCommand ??\n      (this.commands.length &&\n        !this._actionHandler &&\n        !this._findCommand('help'));\n\n    if (hasImplicitHelpCommand) {\n      if (this._helpCommand === undefined) {\n        this.helpCommand(undefined, undefined); // use default name and description\n      }\n      return this._helpCommand;\n    }\n    return null;\n  }\n\n  /**\n   * Add hook for life cycle event.\n   *\n   * @param {string} event\n   * @param {Function} listener\n   * @return {Command} `this` command for chaining\n   */\n\n  hook(event, listener) {\n    const allowedValues = ['preSubcommand', 'preAction', 'postAction'];\n    if (!allowedValues.includes(event)) {\n      throw new Error(`Unexpected value for event passed to hook : '${event}'.\nExpecting one of '${allowedValues.join(\"', '\")}'`);\n    }\n    if (this._lifeCycleHooks[event]) {\n      this._lifeCycleHooks[event].push(listener);\n    } else {\n      this._lifeCycleHooks[event] = [listener];\n    }\n    return this;\n  }\n\n  /**\n   * Register callback to use as replacement for calling process.exit.\n   *\n   * @param {Function} [fn] optional callback which will be passed a CommanderError, defaults to throwing\n   * @return {Command} `this` command for chaining\n   */\n\n  exitOverride(fn) {\n    if (fn) {\n      this._exitCallback = fn;\n    } else {\n      this._exitCallback = (err) => {\n        if (err.code !== 'commander.executeSubCommandAsync') {\n          throw err;\n        } else {\n          // Async callback from spawn events, not useful to throw.\n        }\n      };\n    }\n    return this;\n  }\n\n  /**\n   * Call process.exit, and _exitCallback if defined.\n   *\n   * @param {number} exitCode exit code for using with process.exit\n   * @param {string} code an id string representing the error\n   * @param {string} message human-readable description of the error\n   * @return never\n   * @private\n   */\n\n  _exit(exitCode, code, message) {\n    if (this._exitCallback) {\n      this._exitCallback(new CommanderError(exitCode, code, message));\n      // Expecting this line is not reached.\n    }\n    process.exit(exitCode);\n  }\n\n  /**\n   * Register callback `fn` for the command.\n   *\n   * @example\n   * program\n   *   .command('serve')\n   *   .description('start service')\n   *   .action(function() {\n   *      // do work here\n   *   });\n   *\n   * @param {Function} fn\n   * @return {Command} `this` command for chaining\n   */\n\n  action(fn) {\n    const listener = (args) => {\n      // The .action callback takes an extra parameter which is the command or options.\n      const expectedArgsCount = this.registeredArguments.length;\n      const actionArgs = args.slice(0, expectedArgsCount);\n      if (this._storeOptionsAsProperties) {\n        actionArgs[expectedArgsCount] = this; // backwards compatible \"options\"\n      } else {\n        actionArgs[expectedArgsCount] = this.opts();\n      }\n      actionArgs.push(this);\n\n      return fn.apply(this, actionArgs);\n    };\n    this._actionHandler = listener;\n    return this;\n  }\n\n  /**\n   * Factory routine to create a new unattached option.\n   *\n   * See .option() for creating an attached option, which uses this routine to\n   * create the option. You can override createOption to return a custom option.\n   *\n   * @param {string} flags\n   * @param {string} [description]\n   * @return {Option} new option\n   */\n\n  createOption(flags, description) {\n    return new Option(flags, description);\n  }\n\n  /**\n   * Wrap parseArgs to catch 'commander.invalidArgument'.\n   *\n   * @param {(Option | Argument)} target\n   * @param {string} value\n   * @param {*} previous\n   * @param {string} invalidArgumentMessage\n   * @private\n   */\n\n  _callParseArg(target, value, previous, invalidArgumentMessage) {\n    try {\n      return target.parseArg(value, previous);\n    } catch (err) {\n      if (err.code === 'commander.invalidArgument') {\n        const message = `${invalidArgumentMessage} ${err.message}`;\n        this.error(message, { exitCode: err.exitCode, code: err.code });\n      }\n      throw err;\n    }\n  }\n\n  /**\n   * Check for option flag conflicts.\n   * Register option if no conflicts found, or throw on conflict.\n   *\n   * @param {Option} option\n   * @private\n   */\n\n  _registerOption(option) {\n    const matchingOption =\n      (option.short && this._findOption(option.short)) ||\n      (option.long && this._findOption(option.long));\n    if (matchingOption) {\n      const matchingFlag =\n        option.long && this._findOption(option.long)\n          ? option.long\n          : option.short;\n      throw new Error(`Cannot add option '${option.flags}'${this._name && ` to command '${this._name}'`} due to conflicting flag '${matchingFlag}'\n-  already used by option '${matchingOption.flags}'`);\n    }\n\n    this._initOptionGroup(option);\n    this.options.push(option);\n  }\n\n  /**\n   * Check for command name and alias conflicts with existing commands.\n   * Register command if no conflicts found, or throw on conflict.\n   *\n   * @param {Command} command\n   * @private\n   */\n\n  _registerCommand(command) {\n    const knownBy = (cmd) => {\n      return [cmd.name()].concat(cmd.aliases());\n    };\n\n    const alreadyUsed = knownBy(command).find((name) =>\n      this._findCommand(name),\n    );\n    if (alreadyUsed) {\n      const existingCmd = knownBy(this._findCommand(alreadyUsed)).join('|');\n      const newCmd = knownBy(command).join('|');\n      throw new Error(\n        `cannot add command '${newCmd}' as already have command '${existingCmd}'`,\n      );\n    }\n\n    this._initCommandGroup(command);\n    this.commands.push(command);\n  }\n\n  /**\n   * Add an option.\n   *\n   * @param {Option} option\n   * @return {Command} `this` command for chaining\n   */\n  addOption(option) {\n    this._registerOption(option);\n\n    const oname = option.name();\n    const name = option.attributeName();\n\n    // store default value\n    if (option.negate) {\n      // --no-foo is special and defaults foo to true, unless a --foo option is already defined\n      const positiveLongFlag = option.long.replace(/^--no-/, '--');\n      if (!this._findOption(positiveLongFlag)) {\n        this.setOptionValueWithSource(\n          name,\n          option.defaultValue === undefined ? true : option.defaultValue,\n          'default',\n        );\n      }\n    } else if (option.defaultValue !== undefined) {\n      this.setOptionValueWithSource(name, option.defaultValue, 'default');\n    }\n\n    // handler for cli and env supplied values\n    const handleOptionValue = (val, invalidValueMessage, valueSource) => {\n      // val is null for optional option used without an optional-argument.\n      // val is undefined for boolean and negated option.\n      if (val == null && option.presetArg !== undefined) {\n        val = option.presetArg;\n      }\n\n      // custom processing\n      const oldValue = this.getOptionValue(name);\n      if (val !== null && option.parseArg) {\n        val = this._callParseArg(option, val, oldValue, invalidValueMessage);\n      } else if (val !== null && option.variadic) {\n        val = option._collectValue(val, oldValue);\n      }\n\n      // Fill-in appropriate missing values. Long winded but easy to follow.\n      if (val == null) {\n        if (option.negate) {\n          val = false;\n        } else if (option.isBoolean() || option.optional) {\n          val = true;\n        } else {\n          val = ''; // not normal, parseArg might have failed or be a mock function for testing\n        }\n      }\n      this.setOptionValueWithSource(name, val, valueSource);\n    };\n\n    this.on('option:' + oname, (val) => {\n      const invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`;\n      handleOptionValue(val, invalidValueMessage, 'cli');\n    });\n\n    if (option.envVar) {\n      this.on('optionEnv:' + oname, (val) => {\n        const invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`;\n        handleOptionValue(val, invalidValueMessage, 'env');\n      });\n    }\n\n    return this;\n  }\n\n  /**\n   * Internal implementation shared by .option() and .requiredOption()\n   *\n   * @return {Command} `this` command for chaining\n   * @private\n   */\n  _optionEx(config, flags, description, fn, defaultValue) {\n    if (typeof flags === 'object' && flags instanceof Option) {\n      throw new Error(\n        'To add an Option object use addOption() instead of option() or requiredOption()',\n      );\n    }\n    const option = this.createOption(flags, description);\n    option.makeOptionMandatory(!!config.mandatory);\n    if (typeof fn === 'function') {\n      option.default(defaultValue).argParser(fn);\n    } else if (fn instanceof RegExp) {\n      // deprecated\n      const regex = fn;\n      fn = (val, def) => {\n        const m = regex.exec(val);\n        return m ? m[0] : def;\n      };\n      option.default(defaultValue).argParser(fn);\n    } else {\n      option.default(fn);\n    }\n\n    return this.addOption(option);\n  }\n\n  /**\n   * Define option with `flags`, `description`, and optional argument parsing function or `defaultValue` or both.\n   *\n   * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space. A required\n   * option-argument is indicated by `<>` and an optional option-argument by `[]`.\n   *\n   * See the README for more details, and see also addOption() and requiredOption().\n   *\n   * @example\n   * program\n   *     .option('-p, --pepper', 'add pepper')\n   *     .option('--pt, --pizza-type <TYPE>', 'type of pizza') // required option-argument\n   *     .option('-c, --cheese [CHEESE]', 'add extra cheese', 'mozzarella') // optional option-argument with default\n   *     .option('-t, --tip <VALUE>', 'add tip to purchase cost', parseFloat) // custom parse function\n   *\n   * @param {string} flags\n   * @param {string} [description]\n   * @param {(Function|*)} [parseArg] - custom option processing function or default value\n   * @param {*} [defaultValue]\n   * @return {Command} `this` command for chaining\n   */\n\n  option(flags, description, parseArg, defaultValue) {\n    return this._optionEx({}, flags, description, parseArg, defaultValue);\n  }\n\n  /**\n   * Add a required option which must have a value after parsing. This usually means\n   * the option must be specified on the command line. (Otherwise the same as .option().)\n   *\n   * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space.\n   *\n   * @param {string} flags\n   * @param {string} [description]\n   * @param {(Function|*)} [parseArg] - custom option processing function or default value\n   * @param {*} [defaultValue]\n   * @return {Command} `this` command for chaining\n   */\n\n  requiredOption(flags, description, parseArg, defaultValue) {\n    return this._optionEx(\n      { mandatory: true },\n      flags,\n      description,\n      parseArg,\n      defaultValue,\n    );\n  }\n\n  /**\n   * Alter parsing of short flags with optional values.\n   *\n   * @example\n   * // for `.option('-f,--flag [value]'):\n   * program.combineFlagAndOptionalValue(true);  // `-f80` is treated like `--flag=80`, this is the default behaviour\n   * program.combineFlagAndOptionalValue(false) // `-fb` is treated like `-f -b`\n   *\n   * @param {boolean} [combine] - if `true` or omitted, an optional value can be specified directly after the flag.\n   * @return {Command} `this` command for chaining\n   */\n  combineFlagAndOptionalValue(combine = true) {\n    this._combineFlagAndOptionalValue = !!combine;\n    return this;\n  }\n\n  /**\n   * Allow unknown options on the command line.\n   *\n   * @param {boolean} [allowUnknown] - if `true` or omitted, no error will be thrown for unknown options.\n   * @return {Command} `this` command for chaining\n   */\n  allowUnknownOption(allowUnknown = true) {\n    this._allowUnknownOption = !!allowUnknown;\n    return this;\n  }\n\n  /**\n   * Allow excess command-arguments on the command line. Pass false to make excess arguments an error.\n   *\n   * @param {boolean} [allowExcess] - if `true` or omitted, no error will be thrown for excess arguments.\n   * @return {Command} `this` command for chaining\n   */\n  allowExcessArguments(allowExcess = true) {\n    this._allowExcessArguments = !!allowExcess;\n    return this;\n  }\n\n  /**\n   * Enable positional options. Positional means global options are specified before subcommands which lets\n   * subcommands reuse the same option names, and also enables subcommands to turn on passThroughOptions.\n   * The default behaviour is non-positional and global options may appear anywhere on the command line.\n   *\n   * @param {boolean} [positional]\n   * @return {Command} `this` command for chaining\n   */\n  enablePositionalOptions(positional = true) {\n    this._enablePositionalOptions = !!positional;\n    return this;\n  }\n\n  /**\n   * Pass through options that come after command-arguments rather than treat them as command-options,\n   * so actual command-options come before command-arguments. Turning this on for a subcommand requires\n   * positional options to have been enabled on the program (parent commands).\n   * The default behaviour is non-positional and options may appear before or after command-arguments.\n   *\n   * @param {boolean} [passThrough] for unknown options.\n   * @return {Command} `this` command for chaining\n   */\n  passThroughOptions(passThrough = true) {\n    this._passThroughOptions = !!passThrough;\n    this._checkForBrokenPassThrough();\n    return this;\n  }\n\n  /**\n   * @private\n   */\n\n  _checkForBrokenPassThrough() {\n    if (\n      this.parent &&\n      this._passThroughOptions &&\n      !this.parent._enablePositionalOptions\n    ) {\n      throw new Error(\n        `passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`,\n      );\n    }\n  }\n\n  /**\n   * Whether to store option values as properties on command object,\n   * or store separately (specify false). In both cases the option values can be accessed using .opts().\n   *\n   * @param {boolean} [storeAsProperties=true]\n   * @return {Command} `this` command for chaining\n   */\n\n  storeOptionsAsProperties(storeAsProperties = true) {\n    if (this.options.length) {\n      throw new Error('call .storeOptionsAsProperties() before adding options');\n    }\n    if (Object.keys(this._optionValues).length) {\n      throw new Error(\n        'call .storeOptionsAsProperties() before setting option values',\n      );\n    }\n    this._storeOptionsAsProperties = !!storeAsProperties;\n    return this;\n  }\n\n  /**\n   * Retrieve option value.\n   *\n   * @param {string} key\n   * @return {object} value\n   */\n\n  getOptionValue(key) {\n    if (this._storeOptionsAsProperties) {\n      return this[key];\n    }\n    return this._optionValues[key];\n  }\n\n  /**\n   * Store option value.\n   *\n   * @param {string} key\n   * @param {object} value\n   * @return {Command} `this` command for chaining\n   */\n\n  setOptionValue(key, value) {\n    return this.setOptionValueWithSource(key, value, undefined);\n  }\n\n  /**\n   * Store option value and where the value came from.\n   *\n   * @param {string} key\n   * @param {object} value\n   * @param {string} source - expected values are default/config/env/cli/implied\n   * @return {Command} `this` command for chaining\n   */\n\n  setOptionValueWithSource(key, value, source) {\n    if (this._storeOptionsAsProperties) {\n      this[key] = value;\n    } else {\n      this._optionValues[key] = value;\n    }\n    this._optionValueSources[key] = source;\n    return this;\n  }\n\n  /**\n   * Get source of option value.\n   * Expected values are default | config | env | cli | implied\n   *\n   * @param {string} key\n   * @return {string}\n   */\n\n  getOptionValueSource(key) {\n    return this._optionValueSources[key];\n  }\n\n  /**\n   * Get source of option value. See also .optsWithGlobals().\n   * Expected values are default | config | env | cli | implied\n   *\n   * @param {string} key\n   * @return {string}\n   */\n\n  getOptionValueSourceWithGlobals(key) {\n    // global overwrites local, like optsWithGlobals\n    let source;\n    this._getCommandAndAncestors().forEach((cmd) => {\n      if (cmd.getOptionValueSource(key) !== undefined) {\n        source = cmd.getOptionValueSource(key);\n      }\n    });\n    return source;\n  }\n\n  /**\n   * Get user arguments from implied or explicit arguments.\n   * Side-effects: set _scriptPath if args included script. Used for default program name, and subcommand searches.\n   *\n   * @private\n   */\n\n  _prepareUserArgs(argv, parseOptions) {\n    if (argv !== undefined && !Array.isArray(argv)) {\n      throw new Error('first parameter to parse must be array or undefined');\n    }\n    parseOptions = parseOptions || {};\n\n    // auto-detect argument conventions if nothing supplied\n    if (argv === undefined && parseOptions.from === undefined) {\n      if (process.versions?.electron) {\n        parseOptions.from = 'electron';\n      }\n      // check node specific options for scenarios where user CLI args follow executable without scriptname\n      const execArgv = process.execArgv ?? [];\n      if (\n        execArgv.includes('-e') ||\n        execArgv.includes('--eval') ||\n        execArgv.includes('-p') ||\n        execArgv.includes('--print')\n      ) {\n        parseOptions.from = 'eval'; // internal usage, not documented\n      }\n    }\n\n    // default to using process.argv\n    if (argv === undefined) {\n      argv = process.argv;\n    }\n    this.rawArgs = argv.slice();\n\n    // extract the user args and scriptPath\n    let userArgs;\n    switch (parseOptions.from) {\n      case undefined:\n      case 'node':\n        this._scriptPath = argv[1];\n        userArgs = argv.slice(2);\n        break;\n      case 'electron':\n        // @ts-ignore: because defaultApp is an unknown property\n        if (process.defaultApp) {\n          this._scriptPath = argv[1];\n          userArgs = argv.slice(2);\n        } else {\n          userArgs = argv.slice(1);\n        }\n        break;\n      case 'user':\n        userArgs = argv.slice(0);\n        break;\n      case 'eval':\n        userArgs = argv.slice(1);\n        break;\n      default:\n        throw new Error(\n          `unexpected parse option { from: '${parseOptions.from}' }`,\n        );\n    }\n\n    // Find default name for program from arguments.\n    if (!this._name && this._scriptPath)\n      this.nameFromFilename(this._scriptPath);\n    this._name = this._name || 'program';\n\n    return userArgs;\n  }\n\n  /**\n   * Parse `argv`, setting options and invoking commands when defined.\n   *\n   * Use parseAsync instead of parse if any of your action handlers are async.\n   *\n   * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!\n   *\n   * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:\n   * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that\n   * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged\n   * - `'user'`: just user arguments\n   *\n   * @example\n   * program.parse(); // parse process.argv and auto-detect electron and special node flags\n   * program.parse(process.argv); // assume argv[0] is app and argv[1] is script\n   * program.parse(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]\n   *\n   * @param {string[]} [argv] - optional, defaults to process.argv\n   * @param {object} [parseOptions] - optionally specify style of options with from: node/user/electron\n   * @param {string} [parseOptions.from] - where the args are from: 'node', 'user', 'electron'\n   * @return {Command} `this` command for chaining\n   */\n\n  parse(argv, parseOptions) {\n    this._prepareForParse();\n    const userArgs = this._prepareUserArgs(argv, parseOptions);\n    this._parseCommand([], userArgs);\n\n    return this;\n  }\n\n  /**\n   * Parse `argv`, setting options and invoking commands when defined.\n   *\n   * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!\n   *\n   * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:\n   * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that\n   * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged\n   * - `'user'`: just user arguments\n   *\n   * @example\n   * await program.parseAsync(); // parse process.argv and auto-detect electron and special node flags\n   * await program.parseAsync(process.argv); // assume argv[0] is app and argv[1] is script\n   * await program.parseAsync(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]\n   *\n   * @param {string[]} [argv]\n   * @param {object} [parseOptions]\n   * @param {string} parseOptions.from - where the args are from: 'node', 'user', 'electron'\n   * @return {Promise}\n   */\n\n  async parseAsync(argv, parseOptions) {\n    this._prepareForParse();\n    const userArgs = this._prepareUserArgs(argv, parseOptions);\n    await this._parseCommand([], userArgs);\n\n    return this;\n  }\n\n  _prepareForParse() {\n    if (this._savedState === null) {\n      this.saveStateBeforeParse();\n    } else {\n      this.restoreStateBeforeParse();\n    }\n  }\n\n  /**\n   * Called the first time parse is called to save state and allow a restore before subsequent calls to parse.\n   * Not usually called directly, but available for subclasses to save their custom state.\n   *\n   * This is called in a lazy way. Only commands used in parsing chain will have state saved.\n   */\n  saveStateBeforeParse() {\n    this._savedState = {\n      // name is stable if supplied by author, but may be unspecified for root command and deduced during parsing\n      _name: this._name,\n      // option values before parse have default values (including false for negated options)\n      // shallow clones\n      _optionValues: { ...this._optionValues },\n      _optionValueSources: { ...this._optionValueSources },\n    };\n  }\n\n  /**\n   * Restore state before parse for calls after the first.\n   * Not usually called directly, but available for subclasses to save their custom state.\n   *\n   * This is called in a lazy way. Only commands used in parsing chain will have state restored.\n   */\n  restoreStateBeforeParse() {\n    if (this._storeOptionsAsProperties)\n      throw new Error(`Can not call parse again when storeOptionsAsProperties is true.\n- either make a new Command for each call to parse, or stop storing options as properties`);\n\n    // clear state from _prepareUserArgs\n    this._name = this._savedState._name;\n    this._scriptPath = null;\n    this.rawArgs = [];\n    // clear state from setOptionValueWithSource\n    this._optionValues = { ...this._savedState._optionValues };\n    this._optionValueSources = { ...this._savedState._optionValueSources };\n    // clear state from _parseCommand\n    this.args = [];\n    // clear state from _processArguments\n    this.processedArgs = [];\n  }\n\n  /**\n   * Throw if expected executable is missing. Add lots of help for author.\n   *\n   * @param {string} executableFile\n   * @param {string} executableDir\n   * @param {string} subcommandName\n   */\n  _checkForMissingExecutable(executableFile, executableDir, subcommandName) {\n    if (fs.existsSync(executableFile)) return;\n\n    const executableDirMessage = executableDir\n      ? `searched for local subcommand relative to directory '${executableDir}'`\n      : 'no directory for search for local subcommand, use .executableDir() to supply a custom directory';\n    const executableMissing = `'${executableFile}' does not exist\n - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead\n - if the default executable name is not suitable, use the executableFile option to supply a custom name or path\n - ${executableDirMessage}`;\n    throw new Error(executableMissing);\n  }\n\n  /**\n   * Execute a sub-command executable.\n   *\n   * @private\n   */\n\n  _executeSubCommand(subcommand, args) {\n    args = args.slice();\n    let launchWithNode = false; // Use node for source targets so do not need to get permissions correct, and on Windows.\n    const sourceExt = ['.js', '.ts', '.tsx', '.mjs', '.cjs'];\n\n    function findFile(baseDir, baseName) {\n      // Look for specified file\n      const localBin = path.resolve(baseDir, baseName);\n      if (fs.existsSync(localBin)) return localBin;\n\n      // Stop looking if candidate already has an expected extension.\n      if (sourceExt.includes(path.extname(baseName))) return undefined;\n\n      // Try all the extensions.\n      const foundExt = sourceExt.find((ext) =>\n        fs.existsSync(`${localBin}${ext}`),\n      );\n      if (foundExt) return `${localBin}${foundExt}`;\n\n      return undefined;\n    }\n\n    // Not checking for help first. Unlikely to have mandatory and executable, and can't robustly test for help flags in external command.\n    this._checkForMissingMandatoryOptions();\n    this._checkForConflictingOptions();\n\n    // executableFile and executableDir might be full path, or just a name\n    let executableFile =\n      subcommand._executableFile || `${this._name}-${subcommand._name}`;\n    let executableDir = this._executableDir || '';\n    if (this._scriptPath) {\n      let resolvedScriptPath; // resolve possible symlink for installed npm binary\n      try {\n        resolvedScriptPath = fs.realpathSync(this._scriptPath);\n      } catch {\n        resolvedScriptPath = this._scriptPath;\n      }\n      executableDir = path.resolve(\n        path.dirname(resolvedScriptPath),\n        executableDir,\n      );\n    }\n\n    // Look for a local file in preference to a command in PATH.\n    if (executableDir) {\n      let localFile = findFile(executableDir, executableFile);\n\n      // Legacy search using prefix of script name instead of command name\n      if (!localFile && !subcommand._executableFile && this._scriptPath) {\n        const legacyName = path.basename(\n          this._scriptPath,\n          path.extname(this._scriptPath),\n        );\n        if (legacyName !== this._name) {\n          localFile = findFile(\n            executableDir,\n            `${legacyName}-${subcommand._name}`,\n          );\n        }\n      }\n      executableFile = localFile || executableFile;\n    }\n\n    launchWithNode = sourceExt.includes(path.extname(executableFile));\n\n    let proc;\n    if (process.platform !== 'win32') {\n      if (launchWithNode) {\n        args.unshift(executableFile);\n        // add executable arguments to spawn\n        args = incrementNodeInspectorPort(process.execArgv).concat(args);\n\n        proc = childProcess.spawn(process.argv[0], args, { stdio: 'inherit' });\n      } else {\n        proc = childProcess.spawn(executableFile, args, { stdio: 'inherit' });\n      }\n    } else {\n      this._checkForMissingExecutable(\n        executableFile,\n        executableDir,\n        subcommand._name,\n      );\n      args.unshift(executableFile);\n      // add executable arguments to spawn\n      args = incrementNodeInspectorPort(process.execArgv).concat(args);\n      proc = childProcess.spawn(process.execPath, args, { stdio: 'inherit' });\n    }\n\n    if (!proc.killed) {\n      // testing mainly to avoid leak warnings during unit tests with mocked spawn\n      const signals = ['SIGUSR1', 'SIGUSR2', 'SIGTERM', 'SIGINT', 'SIGHUP'];\n      signals.forEach((signal) => {\n        process.on(signal, () => {\n          if (proc.killed === false && proc.exitCode === null) {\n            // @ts-ignore because signals not typed to known strings\n            proc.kill(signal);\n          }\n        });\n      });\n    }\n\n    // By default terminate process when spawned process terminates.\n    const exitCallback = this._exitCallback;\n    proc.on('close', (code) => {\n      code = code ?? 1; // code is null if spawned process terminated due to a signal\n      if (!exitCallback) {\n        process.exit(code);\n      } else {\n        exitCallback(\n          new CommanderError(\n            code,\n            'commander.executeSubCommandAsync',\n            '(close)',\n          ),\n        );\n      }\n    });\n    proc.on('error', (err) => {\n      // @ts-ignore: because err.code is an unknown property\n      if (err.code === 'ENOENT') {\n        this._checkForMissingExecutable(\n          executableFile,\n          executableDir,\n          subcommand._name,\n        );\n        // @ts-ignore: because err.code is an unknown property\n      } else if (err.code === 'EACCES') {\n        throw new Error(`'${executableFile}' not executable`);\n      }\n      if (!exitCallback) {\n        process.exit(1);\n      } else {\n        const wrappedError = new CommanderError(\n          1,\n          'commander.executeSubCommandAsync',\n          '(error)',\n        );\n        wrappedError.nestedError = err;\n        exitCallback(wrappedError);\n      }\n    });\n\n    // Store the reference to the child process\n    this.runningCommand = proc;\n  }\n\n  /**\n   * @private\n   */\n\n  _dispatchSubcommand(commandName, operands, unknown) {\n    const subCommand = this._findCommand(commandName);\n    if (!subCommand) this.help({ error: true });\n\n    subCommand._prepareForParse();\n    let promiseChain;\n    promiseChain = this._chainOrCallSubCommandHook(\n      promiseChain,\n      subCommand,\n      'preSubcommand',\n    );\n    promiseChain = this._chainOrCall(promiseChain, () => {\n      if (subCommand._executableHandler) {\n        this._executeSubCommand(subCommand, operands.concat(unknown));\n      } else {\n        return subCommand._parseCommand(operands, unknown);\n      }\n    });\n    return promiseChain;\n  }\n\n  /**\n   * Invoke help directly if possible, or dispatch if necessary.\n   * e.g. help foo\n   *\n   * @private\n   */\n\n  _dispatchHelpCommand(subcommandName) {\n    if (!subcommandName) {\n      this.help();\n    }\n    const subCommand = this._findCommand(subcommandName);\n    if (subCommand && !subCommand._executableHandler) {\n      subCommand.help();\n    }\n\n    // Fallback to parsing the help flag to invoke the help.\n    return this._dispatchSubcommand(\n      subcommandName,\n      [],\n      [this._getHelpOption()?.long ?? this._getHelpOption()?.short ?? '--help'],\n    );\n  }\n\n  /**\n   * Check this.args against expected this.registeredArguments.\n   *\n   * @private\n   */\n\n  _checkNumberOfArguments() {\n    // too few\n    this.registeredArguments.forEach((arg, i) => {\n      if (arg.required && this.args[i] == null) {\n        this.missingArgument(arg.name());\n      }\n    });\n    // too many\n    if (\n      this.registeredArguments.length > 0 &&\n      this.registeredArguments[this.registeredArguments.length - 1].variadic\n    ) {\n      return;\n    }\n    if (this.args.length > this.registeredArguments.length) {\n      this._excessArguments(this.args);\n    }\n  }\n\n  /**\n   * Process this.args using this.registeredArguments and save as this.processedArgs!\n   *\n   * @private\n   */\n\n  _processArguments() {\n    const myParseArg = (argument, value, previous) => {\n      // Extra processing for nice error message on parsing failure.\n      let parsedValue = value;\n      if (value !== null && argument.parseArg) {\n        const invalidValueMessage = `error: command-argument value '${value}' is invalid for argument '${argument.name()}'.`;\n        parsedValue = this._callParseArg(\n          argument,\n          value,\n          previous,\n          invalidValueMessage,\n        );\n      }\n      return parsedValue;\n    };\n\n    this._checkNumberOfArguments();\n\n    const processedArgs = [];\n    this.registeredArguments.forEach((declaredArg, index) => {\n      let value = declaredArg.defaultValue;\n      if (declaredArg.variadic) {\n        // Collect together remaining arguments for passing together as an array.\n        if (index < this.args.length) {\n          value = this.args.slice(index);\n          if (declaredArg.parseArg) {\n            value = value.reduce((processed, v) => {\n              return myParseArg(declaredArg, v, processed);\n            }, declaredArg.defaultValue);\n          }\n        } else if (value === undefined) {\n          value = [];\n        }\n      } else if (index < this.args.length) {\n        value = this.args[index];\n        if (declaredArg.parseArg) {\n          value = myParseArg(declaredArg, value, declaredArg.defaultValue);\n        }\n      }\n      processedArgs[index] = value;\n    });\n    this.processedArgs = processedArgs;\n  }\n\n  /**\n   * Once we have a promise we chain, but call synchronously until then.\n   *\n   * @param {(Promise|undefined)} promise\n   * @param {Function} fn\n   * @return {(Promise|undefined)}\n   * @private\n   */\n\n  _chainOrCall(promise, fn) {\n    // thenable\n    if (promise?.then && typeof promise.then === 'function') {\n      // already have a promise, chain callback\n      return promise.then(() => fn());\n    }\n    // callback might return a promise\n    return fn();\n  }\n\n  /**\n   *\n   * @param {(Promise|undefined)} promise\n   * @param {string} event\n   * @return {(Promise|undefined)}\n   * @private\n   */\n\n  _chainOrCallHooks(promise, event) {\n    let result = promise;\n    const hooks = [];\n    this._getCommandAndAncestors()\n      .reverse()\n      .filter((cmd) => cmd._lifeCycleHooks[event] !== undefined)\n      .forEach((hookedCommand) => {\n        hookedCommand._lifeCycleHooks[event].forEach((callback) => {\n          hooks.push({ hookedCommand, callback });\n        });\n      });\n    if (event === 'postAction') {\n      hooks.reverse();\n    }\n\n    hooks.forEach((hookDetail) => {\n      result = this._chainOrCall(result, () => {\n        return hookDetail.callback(hookDetail.hookedCommand, this);\n      });\n    });\n    return result;\n  }\n\n  /**\n   *\n   * @param {(Promise|undefined)} promise\n   * @param {Command} subCommand\n   * @param {string} event\n   * @return {(Promise|undefined)}\n   * @private\n   */\n\n  _chainOrCallSubCommandHook(promise, subCommand, event) {\n    let result = promise;\n    if (this._lifeCycleHooks[event] !== undefined) {\n      this._lifeCycleHooks[event].forEach((hook) => {\n        result = this._chainOrCall(result, () => {\n          return hook(this, subCommand);\n        });\n      });\n    }\n    return result;\n  }\n\n  /**\n   * Process arguments in context of this command.\n   * Returns action result, in case it is a promise.\n   *\n   * @private\n   */\n\n  _parseCommand(operands, unknown) {\n    const parsed = this.parseOptions(unknown);\n    this._parseOptionsEnv(); // after cli, so parseArg not called on both cli and env\n    this._parseOptionsImplied();\n    operands = operands.concat(parsed.operands);\n    unknown = parsed.unknown;\n    this.args = operands.concat(unknown);\n\n    if (operands && this._findCommand(operands[0])) {\n      return this._dispatchSubcommand(operands[0], operands.slice(1), unknown);\n    }\n    if (\n      this._getHelpCommand() &&\n      operands[0] === this._getHelpCommand().name()\n    ) {\n      return this._dispatchHelpCommand(operands[1]);\n    }\n    if (this._defaultCommandName) {\n      this._outputHelpIfRequested(unknown); // Run the help for default command from parent rather than passing to default command\n      return this._dispatchSubcommand(\n        this._defaultCommandName,\n        operands,\n        unknown,\n      );\n    }\n    if (\n      this.commands.length &&\n      this.args.length === 0 &&\n      !this._actionHandler &&\n      !this._defaultCommandName\n    ) {\n      // probably missing subcommand and no handler, user needs help (and exit)\n      this.help({ error: true });\n    }\n\n    this._outputHelpIfRequested(parsed.unknown);\n    this._checkForMissingMandatoryOptions();\n    this._checkForConflictingOptions();\n\n    // We do not always call this check to avoid masking a \"better\" error, like unknown command.\n    const checkForUnknownOptions = () => {\n      if (parsed.unknown.length > 0) {\n        this.unknownOption(parsed.unknown[0]);\n      }\n    };\n\n    const commandEvent = `command:${this.name()}`;\n    if (this._actionHandler) {\n      checkForUnknownOptions();\n      this._processArguments();\n\n      let promiseChain;\n      promiseChain = this._chainOrCallHooks(promiseChain, 'preAction');\n      promiseChain = this._chainOrCall(promiseChain, () =>\n        this._actionHandler(this.processedArgs),\n      );\n      if (this.parent) {\n        promiseChain = this._chainOrCall(promiseChain, () => {\n          this.parent.emit(commandEvent, operands, unknown); // legacy\n        });\n      }\n      promiseChain = this._chainOrCallHooks(promiseChain, 'postAction');\n      return promiseChain;\n    }\n    if (this.parent?.listenerCount(commandEvent)) {\n      checkForUnknownOptions();\n      this._processArguments();\n      this.parent.emit(commandEvent, operands, unknown); // legacy\n    } else if (operands.length) {\n      if (this._findCommand('*')) {\n        // legacy default command\n        return this._dispatchSubcommand('*', operands, unknown);\n      }\n      if (this.listenerCount('command:*')) {\n        // skip option check, emit event for possible misspelling suggestion\n        this.emit('command:*', operands, unknown);\n      } else if (this.commands.length) {\n        this.unknownCommand();\n      } else {\n        checkForUnknownOptions();\n        this._processArguments();\n      }\n    } else if (this.commands.length) {\n      checkForUnknownOptions();\n      // This command has subcommands and nothing hooked up at this level, so display help (and exit).\n      this.help({ error: true });\n    } else {\n      checkForUnknownOptions();\n      this._processArguments();\n      // fall through for caller to handle after calling .parse()\n    }\n  }\n\n  /**\n   * Find matching command.\n   *\n   * @private\n   * @return {Command | undefined}\n   */\n  _findCommand(name) {\n    if (!name) return undefined;\n    return this.commands.find(\n      (cmd) => cmd._name === name || cmd._aliases.includes(name),\n    );\n  }\n\n  /**\n   * Return an option matching `arg` if any.\n   *\n   * @param {string} arg\n   * @return {Option}\n   * @package\n   */\n\n  _findOption(arg) {\n    return this.options.find((option) => option.is(arg));\n  }\n\n  /**\n   * Display an error message if a mandatory option does not have a value.\n   * Called after checking for help flags in leaf subcommand.\n   *\n   * @private\n   */\n\n  _checkForMissingMandatoryOptions() {\n    // Walk up hierarchy so can call in subcommand after checking for displaying help.\n    this._getCommandAndAncestors().forEach((cmd) => {\n      cmd.options.forEach((anOption) => {\n        if (\n          anOption.mandatory &&\n          cmd.getOptionValue(anOption.attributeName()) === undefined\n        ) {\n          cmd.missingMandatoryOptionValue(anOption);\n        }\n      });\n    });\n  }\n\n  /**\n   * Display an error message if conflicting options are used together in this.\n   *\n   * @private\n   */\n  _checkForConflictingLocalOptions() {\n    const definedNonDefaultOptions = this.options.filter((option) => {\n      const optionKey = option.attributeName();\n      if (this.getOptionValue(optionKey) === undefined) {\n        return false;\n      }\n      return this.getOptionValueSource(optionKey) !== 'default';\n    });\n\n    const optionsWithConflicting = definedNonDefaultOptions.filter(\n      (option) => option.conflictsWith.length > 0,\n    );\n\n    optionsWithConflicting.forEach((option) => {\n      const conflictingAndDefined = definedNonDefaultOptions.find((defined) =>\n        option.conflictsWith.includes(defined.attributeName()),\n      );\n      if (conflictingAndDefined) {\n        this._conflictingOption(option, conflictingAndDefined);\n      }\n    });\n  }\n\n  /**\n   * Display an error message if conflicting options are used together.\n   * Called after checking for help flags in leaf subcommand.\n   *\n   * @private\n   */\n  _checkForConflictingOptions() {\n    // Walk up hierarchy so can call in subcommand after checking for displaying help.\n    this._getCommandAndAncestors().forEach((cmd) => {\n      cmd._checkForConflictingLocalOptions();\n    });\n  }\n\n  /**\n   * Parse options from `argv` removing known options,\n   * and return argv split into operands and unknown arguments.\n   *\n   * Side effects: modifies command by storing options. Does not reset state if called again.\n   *\n   * Examples:\n   *\n   *     argv => operands, unknown\n   *     --known kkk op => [op], []\n   *     op --known kkk => [op], []\n   *     sub --unknown uuu op => [sub], [--unknown uuu op]\n   *     sub -- --unknown uuu op => [sub --unknown uuu op], []\n   *\n   * @param {string[]} args\n   * @return {{operands: string[], unknown: string[]}}\n   */\n\n  parseOptions(args) {\n    const operands = []; // operands, not options or values\n    const unknown = []; // first unknown option and remaining unknown args\n    let dest = operands;\n\n    function maybeOption(arg) {\n      return arg.length > 1 && arg[0] === '-';\n    }\n\n    const negativeNumberArg = (arg) => {\n      // return false if not a negative number\n      if (!/^-(\\d+|\\d*\\.\\d+)(e[+-]?\\d+)?$/.test(arg)) return false;\n      // negative number is ok unless digit used as an option in command hierarchy\n      return !this._getCommandAndAncestors().some((cmd) =>\n        cmd.options\n          .map((opt) => opt.short)\n          .some((short) => /^-\\d$/.test(short)),\n      );\n    };\n\n    // parse options\n    let activeVariadicOption = null;\n    let activeGroup = null; // working through group of short options, like -abc\n    let i = 0;\n    while (i < args.length || activeGroup) {\n      const arg = activeGroup ?? args[i++];\n      activeGroup = null;\n\n      // literal\n      if (arg === '--') {\n        if (dest === unknown) dest.push(arg);\n        dest.push(...args.slice(i));\n        break;\n      }\n\n      if (\n        activeVariadicOption &&\n        (!maybeOption(arg) || negativeNumberArg(arg))\n      ) {\n        this.emit(`option:${activeVariadicOption.name()}`, arg);\n        continue;\n      }\n      activeVariadicOption = null;\n\n      if (maybeOption(arg)) {\n        const option = this._findOption(arg);\n        // recognised option, call listener to assign value with possible custom processing\n        if (option) {\n          if (option.required) {\n            const value = args[i++];\n            if (value === undefined) this.optionMissingArgument(option);\n            this.emit(`option:${option.name()}`, value);\n          } else if (option.optional) {\n            let value = null;\n            // historical behaviour is optional value is following arg unless an option\n            if (\n              i < args.length &&\n              (!maybeOption(args[i]) || negativeNumberArg(args[i]))\n            ) {\n              value = args[i++];\n            }\n            this.emit(`option:${option.name()}`, value);\n          } else {\n            // boolean flag\n            this.emit(`option:${option.name()}`);\n          }\n          activeVariadicOption = option.variadic ? option : null;\n          continue;\n        }\n      }\n\n      // Look for combo options following single dash, eat first one if known.\n      if (arg.length > 2 && arg[0] === '-' && arg[1] !== '-') {\n        const option = this._findOption(`-${arg[1]}`);\n        if (option) {\n          if (\n            option.required ||\n            (option.optional && this._combineFlagAndOptionalValue)\n          ) {\n            // option with value following in same argument\n            this.emit(`option:${option.name()}`, arg.slice(2));\n          } else {\n            // boolean option\n            this.emit(`option:${option.name()}`);\n            // remove the processed option and keep processing group\n            activeGroup = `-${arg.slice(2)}`;\n          }\n          continue;\n        }\n      }\n\n      // Look for known long flag with value, like --foo=bar\n      if (/^--[^=]+=/.test(arg)) {\n        const index = arg.indexOf('=');\n        const option = this._findOption(arg.slice(0, index));\n        if (option && (option.required || option.optional)) {\n          this.emit(`option:${option.name()}`, arg.slice(index + 1));\n          continue;\n        }\n      }\n\n      // Not a recognised option by this command.\n      // Might be a command-argument, or subcommand option, or unknown option, or help command or option.\n\n      // An unknown option means further arguments also classified as unknown so can be reprocessed by subcommands.\n      // A negative number in a leaf command is not an unknown option.\n      if (\n        dest === operands &&\n        maybeOption(arg) &&\n        !(this.commands.length === 0 && negativeNumberArg(arg))\n      ) {\n        dest = unknown;\n      }\n\n      // If using positionalOptions, stop processing our options at subcommand.\n      if (\n        (this._enablePositionalOptions || this._passThroughOptions) &&\n        operands.length === 0 &&\n        unknown.length === 0\n      ) {\n        if (this._findCommand(arg)) {\n          operands.push(arg);\n          unknown.push(...args.slice(i));\n          break;\n        } else if (\n          this._getHelpCommand() &&\n          arg === this._getHelpCommand().name()\n        ) {\n          operands.push(arg, ...args.slice(i));\n          break;\n        } else if (this._defaultCommandName) {\n          unknown.push(arg, ...args.slice(i));\n          break;\n        }\n      }\n\n      // If using passThroughOptions, stop processing options at first command-argument.\n      if (this._passThroughOptions) {\n        dest.push(arg, ...args.slice(i));\n        break;\n      }\n\n      // add arg\n      dest.push(arg);\n    }\n\n    return { operands, unknown };\n  }\n\n  /**\n   * Return an object containing local option values as key-value pairs.\n   *\n   * @return {object}\n   */\n  opts() {\n    if (this._storeOptionsAsProperties) {\n      // Preserve original behaviour so backwards compatible when still using properties\n      const result = {};\n      const len = this.options.length;\n\n      for (let i = 0; i < len; i++) {\n        const key = this.options[i].attributeName();\n        result[key] =\n          key === this._versionOptionName ? this._version : this[key];\n      }\n      return result;\n    }\n\n    return this._optionValues;\n  }\n\n  /**\n   * Return an object containing merged local and global option values as key-value pairs.\n   *\n   * @return {object}\n   */\n  optsWithGlobals() {\n    // globals overwrite locals\n    return this._getCommandAndAncestors().reduce(\n      (combinedOptions, cmd) => Object.assign(combinedOptions, cmd.opts()),\n      {},\n    );\n  }\n\n  /**\n   * Display error message and exit (or call exitOverride).\n   *\n   * @param {string} message\n   * @param {object} [errorOptions]\n   * @param {string} [errorOptions.code] - an id string representing the error\n   * @param {number} [errorOptions.exitCode] - used with process.exit\n   */\n  error(message, errorOptions) {\n    // output handling\n    this._outputConfiguration.outputError(\n      `${message}\\n`,\n      this._outputConfiguration.writeErr,\n    );\n    if (typeof this._showHelpAfterError === 'string') {\n      this._outputConfiguration.writeErr(`${this._showHelpAfterError}\\n`);\n    } else if (this._showHelpAfterError) {\n      this._outputConfiguration.writeErr('\\n');\n      this.outputHelp({ error: true });\n    }\n\n    // exit handling\n    const config = errorOptions || {};\n    const exitCode = config.exitCode || 1;\n    const code = config.code || 'commander.error';\n    this._exit(exitCode, code, message);\n  }\n\n  /**\n   * Apply any option related environment variables, if option does\n   * not have a value from cli or client code.\n   *\n   * @private\n   */\n  _parseOptionsEnv() {\n    this.options.forEach((option) => {\n      if (option.envVar && option.envVar in process.env) {\n        const optionKey = option.attributeName();\n        // Priority check. Do not overwrite cli or options from unknown source (client-code).\n        if (\n          this.getOptionValue(optionKey) === undefined ||\n          ['default', 'config', 'env'].includes(\n            this.getOptionValueSource(optionKey),\n          )\n        ) {\n          if (option.required || option.optional) {\n            // option can take a value\n            // keep very simple, optional always takes value\n            this.emit(`optionEnv:${option.name()}`, process.env[option.envVar]);\n          } else {\n            // boolean\n            // keep very simple, only care that envVar defined and not the value\n            this.emit(`optionEnv:${option.name()}`);\n          }\n        }\n      }\n    });\n  }\n\n  /**\n   * Apply any implied option values, if option is undefined or default value.\n   *\n   * @private\n   */\n  _parseOptionsImplied() {\n    const dualHelper = new DualOptions(this.options);\n    const hasCustomOptionValue = (optionKey) => {\n      return (\n        this.getOptionValue(optionKey) !== undefined &&\n        !['default', 'implied'].includes(this.getOptionValueSource(optionKey))\n      );\n    };\n    this.options\n      .filter(\n        (option) =>\n          option.implied !== undefined &&\n          hasCustomOptionValue(option.attributeName()) &&\n          dualHelper.valueFromOption(\n            this.getOptionValue(option.attributeName()),\n            option,\n          ),\n      )\n      .forEach((option) => {\n        Object.keys(option.implied)\n          .filter((impliedKey) => !hasCustomOptionValue(impliedKey))\n          .forEach((impliedKey) => {\n            this.setOptionValueWithSource(\n              impliedKey,\n              option.implied[impliedKey],\n              'implied',\n            );\n          });\n      });\n  }\n\n  /**\n   * Argument `name` is missing.\n   *\n   * @param {string} name\n   * @private\n   */\n\n  missingArgument(name) {\n    const message = `error: missing required argument '${name}'`;\n    this.error(message, { code: 'commander.missingArgument' });\n  }\n\n  /**\n   * `Option` is missing an argument.\n   *\n   * @param {Option} option\n   * @private\n   */\n\n  optionMissingArgument(option) {\n    const message = `error: option '${option.flags}' argument missing`;\n    this.error(message, { code: 'commander.optionMissingArgument' });\n  }\n\n  /**\n   * `Option` does not have a value, and is a mandatory option.\n   *\n   * @param {Option} option\n   * @private\n   */\n\n  missingMandatoryOptionValue(option) {\n    const message = `error: required option '${option.flags}' not specified`;\n    this.error(message, { code: 'commander.missingMandatoryOptionValue' });\n  }\n\n  /**\n   * `Option` conflicts with another option.\n   *\n   * @param {Option} option\n   * @param {Option} conflictingOption\n   * @private\n   */\n  _conflictingOption(option, conflictingOption) {\n    // The calling code does not know whether a negated option is the source of the\n    // value, so do some work to take an educated guess.\n    const findBestOptionFromValue = (option) => {\n      const optionKey = option.attributeName();\n      const optionValue = this.getOptionValue(optionKey);\n      const negativeOption = this.options.find(\n        (target) => target.negate && optionKey === target.attributeName(),\n      );\n      const positiveOption = this.options.find(\n        (target) => !target.negate && optionKey === target.attributeName(),\n      );\n      if (\n        negativeOption &&\n        ((negativeOption.presetArg === undefined && optionValue === false) ||\n          (negativeOption.presetArg !== undefined &&\n            optionValue === negativeOption.presetArg))\n      ) {\n        return negativeOption;\n      }\n      return positiveOption || option;\n    };\n\n    const getErrorMessage = (option) => {\n      const bestOption = findBestOptionFromValue(option);\n      const optionKey = bestOption.attributeName();\n      const source = this.getOptionValueSource(optionKey);\n      if (source === 'env') {\n        return `environment variable '${bestOption.envVar}'`;\n      }\n      return `option '${bestOption.flags}'`;\n    };\n\n    const message = `error: ${getErrorMessage(option)} cannot be used with ${getErrorMessage(conflictingOption)}`;\n    this.error(message, { code: 'commander.conflictingOption' });\n  }\n\n  /**\n   * Unknown option `flag`.\n   *\n   * @param {string} flag\n   * @private\n   */\n\n  unknownOption(flag) {\n    if (this._allowUnknownOption) return;\n    let suggestion = '';\n\n    if (flag.startsWith('--') && this._showSuggestionAfterError) {\n      // Looping to pick up the global options too\n      let candidateFlags = [];\n      // eslint-disable-next-line @typescript-eslint/no-this-alias\n      let command = this;\n      do {\n        const moreFlags = command\n          .createHelp()\n          .visibleOptions(command)\n          .filter((option) => option.long)\n          .map((option) => option.long);\n        candidateFlags = candidateFlags.concat(moreFlags);\n        command = command.parent;\n      } while (command && !command._enablePositionalOptions);\n      suggestion = suggestSimilar(flag, candidateFlags);\n    }\n\n    const message = `error: unknown option '${flag}'${suggestion}`;\n    this.error(message, { code: 'commander.unknownOption' });\n  }\n\n  /**\n   * Excess arguments, more than expected.\n   *\n   * @param {string[]} receivedArgs\n   * @private\n   */\n\n  _excessArguments(receivedArgs) {\n    if (this._allowExcessArguments) return;\n\n    const expected = this.registeredArguments.length;\n    const s = expected === 1 ? '' : 's';\n    const forSubcommand = this.parent ? ` for '${this.name()}'` : '';\n    const message = `error: too many arguments${forSubcommand}. Expected ${expected} argument${s} but got ${receivedArgs.length}.`;\n    this.error(message, { code: 'commander.excessArguments' });\n  }\n\n  /**\n   * Unknown command.\n   *\n   * @private\n   */\n\n  unknownCommand() {\n    const unknownName = this.args[0];\n    let suggestion = '';\n\n    if (this._showSuggestionAfterError) {\n      const candidateNames = [];\n      this.createHelp()\n        .visibleCommands(this)\n        .forEach((command) => {\n          candidateNames.push(command.name());\n          // just visible alias\n          if (command.alias()) candidateNames.push(command.alias());\n        });\n      suggestion = suggestSimilar(unknownName, candidateNames);\n    }\n\n    const message = `error: unknown command '${unknownName}'${suggestion}`;\n    this.error(message, { code: 'commander.unknownCommand' });\n  }\n\n  /**\n   * Get or set the program version.\n   *\n   * This method auto-registers the \"-V, --version\" option which will print the version number.\n   *\n   * You can optionally supply the flags and description to override the defaults.\n   *\n   * @param {string} [str]\n   * @param {string} [flags]\n   * @param {string} [description]\n   * @return {(this | string | undefined)} `this` command for chaining, or version string if no arguments\n   */\n\n  version(str, flags, description) {\n    if (str === undefined) return this._version;\n    this._version = str;\n    flags = flags || '-V, --version';\n    description = description || 'output the version number';\n    const versionOption = this.createOption(flags, description);\n    this._versionOptionName = versionOption.attributeName();\n    this._registerOption(versionOption);\n\n    this.on('option:' + versionOption.name(), () => {\n      this._outputConfiguration.writeOut(`${str}\\n`);\n      this._exit(0, 'commander.version', str);\n    });\n    return this;\n  }\n\n  /**\n   * Set the description.\n   *\n   * @param {string} [str]\n   * @param {object} [argsDescription]\n   * @return {(string|Command)}\n   */\n  description(str, argsDescription) {\n    if (str === undefined && argsDescription === undefined)\n      return this._description;\n    this._description = str;\n    if (argsDescription) {\n      this._argsDescription = argsDescription;\n    }\n    return this;\n  }\n\n  /**\n   * Set the summary. Used when listed as subcommand of parent.\n   *\n   * @param {string} [str]\n   * @return {(string|Command)}\n   */\n  summary(str) {\n    if (str === undefined) return this._summary;\n    this._summary = str;\n    return this;\n  }\n\n  /**\n   * Set an alias for the command.\n   *\n   * You may call more than once to add multiple aliases. Only the first alias is shown in the auto-generated help.\n   *\n   * @param {string} [alias]\n   * @return {(string|Command)}\n   */\n\n  alias(alias) {\n    if (alias === undefined) return this._aliases[0]; // just return first, for backwards compatibility\n\n    /** @type {Command} */\n    // eslint-disable-next-line @typescript-eslint/no-this-alias\n    let command = this;\n    if (\n      this.commands.length !== 0 &&\n      this.commands[this.commands.length - 1]._executableHandler\n    ) {\n      // assume adding alias for last added executable subcommand, rather than this\n      command = this.commands[this.commands.length - 1];\n    }\n\n    if (alias === command._name)\n      throw new Error(\"Command alias can't be the same as its name\");\n    const matchingCommand = this.parent?._findCommand(alias);\n    if (matchingCommand) {\n      // c.f. _registerCommand\n      const existingCmd = [matchingCommand.name()]\n        .concat(matchingCommand.aliases())\n        .join('|');\n      throw new Error(\n        `cannot add alias '${alias}' to command '${this.name()}' as already have command '${existingCmd}'`,\n      );\n    }\n\n    command._aliases.push(alias);\n    return this;\n  }\n\n  /**\n   * Set aliases for the command.\n   *\n   * Only the first alias is shown in the auto-generated help.\n   *\n   * @param {string[]} [aliases]\n   * @return {(string[]|Command)}\n   */\n\n  aliases(aliases) {\n    // Getter for the array of aliases is the main reason for having aliases() in addition to alias().\n    if (aliases === undefined) return this._aliases;\n\n    aliases.forEach((alias) => this.alias(alias));\n    return this;\n  }\n\n  /**\n   * Set / get the command usage `str`.\n   *\n   * @param {string} [str]\n   * @return {(string|Command)}\n   */\n\n  usage(str) {\n    if (str === undefined) {\n      if (this._usage) return this._usage;\n\n      const args = this.registeredArguments.map((arg) => {\n        return humanReadableArgName(arg);\n      });\n      return []\n        .concat(\n          this.options.length || this._helpOption !== null ? '[options]' : [],\n          this.commands.length ? '[command]' : [],\n          this.registeredArguments.length ? args : [],\n        )\n        .join(' ');\n    }\n\n    this._usage = str;\n    return this;\n  }\n\n  /**\n   * Get or set the name of the command.\n   *\n   * @param {string} [str]\n   * @return {(string|Command)}\n   */\n\n  name(str) {\n    if (str === undefined) return this._name;\n    this._name = str;\n    return this;\n  }\n\n  /**\n   * Set/get the help group heading for this subcommand in parent command's help.\n   *\n   * @param {string} [heading]\n   * @return {Command | string}\n   */\n\n  helpGroup(heading) {\n    if (heading === undefined) return this._helpGroupHeading ?? '';\n    this._helpGroupHeading = heading;\n    return this;\n  }\n\n  /**\n   * Set/get the default help group heading for subcommands added to this command.\n   * (This does not override a group set directly on the subcommand using .helpGroup().)\n   *\n   * @example\n   * program.commandsGroup('Development Commands:);\n   * program.command('watch')...\n   * program.command('lint')...\n   * ...\n   *\n   * @param {string} [heading]\n   * @returns {Command | string}\n   */\n  commandsGroup(heading) {\n    if (heading === undefined) return this._defaultCommandGroup ?? '';\n    this._defaultCommandGroup = heading;\n    return this;\n  }\n\n  /**\n   * Set/get the default help group heading for options added to this command.\n   * (This does not override a group set directly on the option using .helpGroup().)\n   *\n   * @example\n   * program\n   *   .optionsGroup('Development Options:')\n   *   .option('-d, --debug', 'output extra debugging')\n   *   .option('-p, --profile', 'output profiling information')\n   *\n   * @param {string} [heading]\n   * @returns {Command | string}\n   */\n  optionsGroup(heading) {\n    if (heading === undefined) return this._defaultOptionGroup ?? '';\n    this._defaultOptionGroup = heading;\n    return this;\n  }\n\n  /**\n   * @param {Option} option\n   * @private\n   */\n  _initOptionGroup(option) {\n    if (this._defaultOptionGroup && !option.helpGroupHeading)\n      option.helpGroup(this._defaultOptionGroup);\n  }\n\n  /**\n   * @param {Command} cmd\n   * @private\n   */\n  _initCommandGroup(cmd) {\n    if (this._defaultCommandGroup && !cmd.helpGroup())\n      cmd.helpGroup(this._defaultCommandGroup);\n  }\n\n  /**\n   * Set the name of the command from script filename, such as process.argv[1],\n   * or require.main.filename, or __filename.\n   *\n   * (Used internally and public although not documented in README.)\n   *\n   * @example\n   * program.nameFromFilename(require.main.filename);\n   *\n   * @param {string} filename\n   * @return {Command}\n   */\n\n  nameFromFilename(filename) {\n    this._name = path.basename(filename, path.extname(filename));\n\n    return this;\n  }\n\n  /**\n   * Get or set the directory for searching for executable subcommands of this command.\n   *\n   * @example\n   * program.executableDir(__dirname);\n   * // or\n   * program.executableDir('subcommands');\n   *\n   * @param {string} [path]\n   * @return {(string|null|Command)}\n   */\n\n  executableDir(path) {\n    if (path === undefined) return this._executableDir;\n    this._executableDir = path;\n    return this;\n  }\n\n  /**\n   * Return program help documentation.\n   *\n   * @param {{ error: boolean }} [contextOptions] - pass {error:true} to wrap for stderr instead of stdout\n   * @return {string}\n   */\n\n  helpInformation(contextOptions) {\n    const helper = this.createHelp();\n    const context = this._getOutputContext(contextOptions);\n    helper.prepareContext({\n      error: context.error,\n      helpWidth: context.helpWidth,\n      outputHasColors: context.hasColors,\n    });\n    const text = helper.formatHelp(this, helper);\n    if (context.hasColors) return text;\n    return this._outputConfiguration.stripColor(text);\n  }\n\n  /**\n   * @typedef HelpContext\n   * @type {object}\n   * @property {boolean} error\n   * @property {number} helpWidth\n   * @property {boolean} hasColors\n   * @property {function} write - includes stripColor if needed\n   *\n   * @returns {HelpContext}\n   * @private\n   */\n\n  _getOutputContext(contextOptions) {\n    contextOptions = contextOptions || {};\n    const error = !!contextOptions.error;\n    let baseWrite;\n    let hasColors;\n    let helpWidth;\n    if (error) {\n      baseWrite = (str) => this._outputConfiguration.writeErr(str);\n      hasColors = this._outputConfiguration.getErrHasColors();\n      helpWidth = this._outputConfiguration.getErrHelpWidth();\n    } else {\n      baseWrite = (str) => this._outputConfiguration.writeOut(str);\n      hasColors = this._outputConfiguration.getOutHasColors();\n      helpWidth = this._outputConfiguration.getOutHelpWidth();\n    }\n    const write = (str) => {\n      if (!hasColors) str = this._outputConfiguration.stripColor(str);\n      return baseWrite(str);\n    };\n    return { error, write, hasColors, helpWidth };\n  }\n\n  /**\n   * Output help information for this command.\n   *\n   * Outputs built-in help, and custom text added using `.addHelpText()`.\n   *\n   * @param {{ error: boolean } | Function} [contextOptions] - pass {error:true} to write to stderr instead of stdout\n   */\n\n  outputHelp(contextOptions) {\n    let deprecatedCallback;\n    if (typeof contextOptions === 'function') {\n      deprecatedCallback = contextOptions;\n      contextOptions = undefined;\n    }\n\n    const outputContext = this._getOutputContext(contextOptions);\n    /** @type {HelpTextEventContext} */\n    const eventContext = {\n      error: outputContext.error,\n      write: outputContext.write,\n      command: this,\n    };\n\n    this._getCommandAndAncestors()\n      .reverse()\n      .forEach((command) => command.emit('beforeAllHelp', eventContext));\n    this.emit('beforeHelp', eventContext);\n\n    let helpInformation = this.helpInformation({ error: outputContext.error });\n    if (deprecatedCallback) {\n      helpInformation = deprecatedCallback(helpInformation);\n      if (\n        typeof helpInformation !== 'string' &&\n        !Buffer.isBuffer(helpInformation)\n      ) {\n        throw new Error('outputHelp callback must return a string or a Buffer');\n      }\n    }\n    outputContext.write(helpInformation);\n\n    if (this._getHelpOption()?.long) {\n      this.emit(this._getHelpOption().long); // deprecated\n    }\n    this.emit('afterHelp', eventContext);\n    this._getCommandAndAncestors().forEach((command) =>\n      command.emit('afterAllHelp', eventContext),\n    );\n  }\n\n  /**\n   * You can pass in flags and a description to customise the built-in help option.\n   * Pass in false to disable the built-in help option.\n   *\n   * @example\n   * program.helpOption('-?, --help' 'show help'); // customise\n   * program.helpOption(false); // disable\n   *\n   * @param {(string | boolean)} flags\n   * @param {string} [description]\n   * @return {Command} `this` command for chaining\n   */\n\n  helpOption(flags, description) {\n    // Support enabling/disabling built-in help option.\n    if (typeof flags === 'boolean') {\n      if (flags) {\n        if (this._helpOption === null) this._helpOption = undefined; // reenable\n        if (this._defaultOptionGroup) {\n          // make the option to store the group\n          this._initOptionGroup(this._getHelpOption());\n        }\n      } else {\n        this._helpOption = null; // disable\n      }\n      return this;\n    }\n\n    // Customise flags and description.\n    this._helpOption = this.createOption(\n      flags ?? '-h, --help',\n      description ?? 'display help for command',\n    );\n    // init group unless lazy create\n    if (flags || description) this._initOptionGroup(this._helpOption);\n\n    return this;\n  }\n\n  /**\n   * Lazy create help option.\n   * Returns null if has been disabled with .helpOption(false).\n   *\n   * @returns {(Option | null)} the help option\n   * @package\n   */\n  _getHelpOption() {\n    // Lazy create help option on demand.\n    if (this._helpOption === undefined) {\n      this.helpOption(undefined, undefined);\n    }\n    return this._helpOption;\n  }\n\n  /**\n   * Supply your own option to use for the built-in help option.\n   * This is an alternative to using helpOption() to customise the flags and description etc.\n   *\n   * @param {Option} option\n   * @return {Command} `this` command for chaining\n   */\n  addHelpOption(option) {\n    this._helpOption = option;\n    this._initOptionGroup(option);\n    return this;\n  }\n\n  /**\n   * Output help information and exit.\n   *\n   * Outputs built-in help, and custom text added using `.addHelpText()`.\n   *\n   * @param {{ error: boolean }} [contextOptions] - pass {error:true} to write to stderr instead of stdout\n   */\n\n  help(contextOptions) {\n    this.outputHelp(contextOptions);\n    let exitCode = Number(process.exitCode ?? 0); // process.exitCode does allow a string or an integer, but we prefer just a number\n    if (\n      exitCode === 0 &&\n      contextOptions &&\n      typeof contextOptions !== 'function' &&\n      contextOptions.error\n    ) {\n      exitCode = 1;\n    }\n    // message: do not have all displayed text available so only passing placeholder.\n    this._exit(exitCode, 'commander.help', '(outputHelp)');\n  }\n\n  /**\n   * // Do a little typing to coordinate emit and listener for the help text events.\n   * @typedef HelpTextEventContext\n   * @type {object}\n   * @property {boolean} error\n   * @property {Command} command\n   * @property {function} write\n   */\n\n  /**\n   * Add additional text to be displayed with the built-in help.\n   *\n   * Position is 'before' or 'after' to affect just this command,\n   * and 'beforeAll' or 'afterAll' to affect this command and all its subcommands.\n   *\n   * @param {string} position - before or after built-in help\n   * @param {(string | Function)} text - string to add, or a function returning a string\n   * @return {Command} `this` command for chaining\n   */\n\n  addHelpText(position, text) {\n    const allowedValues = ['beforeAll', 'before', 'after', 'afterAll'];\n    if (!allowedValues.includes(position)) {\n      throw new Error(`Unexpected value for position to addHelpText.\nExpecting one of '${allowedValues.join(\"', '\")}'`);\n    }\n\n    const helpEvent = `${position}Help`;\n    this.on(helpEvent, (/** @type {HelpTextEventContext} */ context) => {\n      let helpStr;\n      if (typeof text === 'function') {\n        helpStr = text({ error: context.error, command: context.command });\n      } else {\n        helpStr = text;\n      }\n      // Ignore falsy value when nothing to output.\n      if (helpStr) {\n        context.write(`${helpStr}\\n`);\n      }\n    });\n    return this;\n  }\n\n  /**\n   * Output help information if help flags specified\n   *\n   * @param {Array} args - array of options to search for help flags\n   * @private\n   */\n\n  _outputHelpIfRequested(args) {\n    const helpOption = this._getHelpOption();\n    const helpRequested = helpOption && args.find((arg) => helpOption.is(arg));\n    if (helpRequested) {\n      this.outputHelp();\n      // (Do not have all displayed text available so only passing placeholder.)\n      this._exit(0, 'commander.helpDisplayed', '(outputHelp)');\n    }\n  }\n}\n\n/**\n * Scan arguments and increment port number for inspect calls (to avoid conflicts when spawning new command).\n *\n * @param {string[]} args - array of arguments from node.execArgv\n * @returns {string[]}\n * @private\n */\n\nfunction incrementNodeInspectorPort(args) {\n  // Testing for these options:\n  //  --inspect[=[host:]port]\n  //  --inspect-brk[=[host:]port]\n  //  --inspect-port=[host:]port\n  return args.map((arg) => {\n    if (!arg.startsWith('--inspect')) {\n      return arg;\n    }\n    let debugOption;\n    let debugHost = '127.0.0.1';\n    let debugPort = '9229';\n    let match;\n    if ((match = arg.match(/^(--inspect(-brk)?)$/)) !== null) {\n      // e.g. --inspect\n      debugOption = match[1];\n    } else if (\n      (match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+)$/)) !== null\n    ) {\n      debugOption = match[1];\n      if (/^\\d+$/.test(match[3])) {\n        // e.g. --inspect=1234\n        debugPort = match[3];\n      } else {\n        // e.g. --inspect=localhost\n        debugHost = match[3];\n      }\n    } else if (\n      (match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+):(\\d+)$/)) !== null\n    ) {\n      // e.g. --inspect=localhost:1234\n      debugOption = match[1];\n      debugHost = match[3];\n      debugPort = match[4];\n    }\n\n    if (debugOption && debugPort !== '0') {\n      return `${debugOption}=${debugHost}:${parseInt(debugPort) + 1}`;\n    }\n    return arg;\n  });\n}\n\n/**\n * @returns {boolean | undefined}\n * @package\n */\nfunction useColor() {\n  // Test for common conventions.\n  // NB: the observed behaviour is in combination with how author adds color! For example:\n  //   - we do not test NODE_DISABLE_COLORS, but util:styletext does\n  //   - we do test NO_COLOR, but Chalk does not\n  //\n  // References:\n  // https://no-color.org\n  // https://bixense.com/clicolors/\n  // https://github.com/nodejs/node/blob/0a00217a5f67ef4a22384cfc80eb6dd9a917fdc1/lib/internal/tty.js#L109\n  // https://github.com/chalk/supports-color/blob/c214314a14bcb174b12b3014b2b0a8de375029ae/index.js#L33\n  // (https://force-color.org recent web page from 2023, does not match major javascript implementations)\n\n  if (\n    process.env.NO_COLOR ||\n    process.env.FORCE_COLOR === '0' ||\n    process.env.FORCE_COLOR === 'false'\n  )\n    return false;\n  if (process.env.FORCE_COLOR || process.env.CLICOLOR_FORCE !== undefined)\n    return true;\n  return undefined;\n}\n\nexports.Command = Command;\nexports.useColor = useColor; // exporting for tests\n"
  },
  {
    "path": "lib/error.js",
    "content": "/**\n * CommanderError class\n */\nclass CommanderError extends Error {\n  /**\n   * Constructs the CommanderError class\n   * @param {number} exitCode suggested exit code which could be used with process.exit\n   * @param {string} code an id string representing the error\n   * @param {string} message human-readable description of the error\n   */\n  constructor(exitCode, code, message) {\n    super(message);\n    // properly capture stack trace in Node.js\n    Error.captureStackTrace(this, this.constructor);\n    this.name = this.constructor.name;\n    this.code = code;\n    this.exitCode = exitCode;\n    this.nestedError = undefined;\n  }\n}\n\n/**\n * InvalidArgumentError class\n */\nclass InvalidArgumentError extends CommanderError {\n  /**\n   * Constructs the InvalidArgumentError class\n   * @param {string} [message] explanation of why argument is invalid\n   */\n  constructor(message) {\n    super(1, 'commander.invalidArgument', message);\n    // properly capture stack trace in Node.js\n    Error.captureStackTrace(this, this.constructor);\n    this.name = this.constructor.name;\n  }\n}\n\nexports.CommanderError = CommanderError;\nexports.InvalidArgumentError = InvalidArgumentError;\n"
  },
  {
    "path": "lib/help.js",
    "content": "const { humanReadableArgName } = require('./argument.js');\n\n/**\n * TypeScript import types for JSDoc, used by Visual Studio Code IntelliSense and `npm run typescript-checkJS`\n * https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#import-types\n * @typedef { import(\"./argument.js\").Argument } Argument\n * @typedef { import(\"./command.js\").Command } Command\n * @typedef { import(\"./option.js\").Option } Option\n */\n\n// Although this is a class, methods are static in style to allow override using subclass or just functions.\nclass Help {\n  constructor() {\n    this.helpWidth = undefined;\n    this.minWidthToWrap = 40;\n    this.sortSubcommands = false;\n    this.sortOptions = false;\n    this.showGlobalOptions = false;\n  }\n\n  /**\n   * prepareContext is called by Commander after applying overrides from `Command.configureHelp()`\n   * and just before calling `formatHelp()`.\n   *\n   * Commander just uses the helpWidth and the rest is provided for optional use by more complex subclasses.\n   *\n   * @param {{ error?: boolean, helpWidth?: number, outputHasColors?: boolean }} contextOptions\n   */\n  prepareContext(contextOptions) {\n    this.helpWidth = this.helpWidth ?? contextOptions.helpWidth ?? 80;\n  }\n\n  /**\n   * Get an array of the visible subcommands. Includes a placeholder for the implicit help command, if there is one.\n   *\n   * @param {Command} cmd\n   * @returns {Command[]}\n   */\n\n  visibleCommands(cmd) {\n    const visibleCommands = cmd.commands.filter((cmd) => !cmd._hidden);\n    const helpCommand = cmd._getHelpCommand();\n    if (helpCommand && !helpCommand._hidden) {\n      visibleCommands.push(helpCommand);\n    }\n    if (this.sortSubcommands) {\n      visibleCommands.sort((a, b) => {\n        // @ts-ignore: because overloaded return type\n        return a.name().localeCompare(b.name());\n      });\n    }\n    return visibleCommands;\n  }\n\n  /**\n   * Compare options for sort.\n   *\n   * @param {Option} a\n   * @param {Option} b\n   * @returns {number}\n   */\n  compareOptions(a, b) {\n    const getSortKey = (option) => {\n      // WYSIWYG for order displayed in help. Short used for comparison if present. No special handling for negated.\n      return option.short\n        ? option.short.replace(/^-/, '')\n        : option.long.replace(/^--/, '');\n    };\n    return getSortKey(a).localeCompare(getSortKey(b));\n  }\n\n  /**\n   * Get an array of the visible options. Includes a placeholder for the implicit help option, if there is one.\n   *\n   * @param {Command} cmd\n   * @returns {Option[]}\n   */\n\n  visibleOptions(cmd) {\n    const visibleOptions = cmd.options.filter((option) => !option.hidden);\n    // Built-in help option.\n    const helpOption = cmd._getHelpOption();\n    if (helpOption && !helpOption.hidden) {\n      // Automatically hide conflicting flags. Bit dubious but a historical behaviour that is convenient for single-command programs.\n      const removeShort = helpOption.short && cmd._findOption(helpOption.short);\n      const removeLong = helpOption.long && cmd._findOption(helpOption.long);\n      if (!removeShort && !removeLong) {\n        visibleOptions.push(helpOption); // no changes needed\n      } else if (helpOption.long && !removeLong) {\n        visibleOptions.push(\n          cmd.createOption(helpOption.long, helpOption.description),\n        );\n      } else if (helpOption.short && !removeShort) {\n        visibleOptions.push(\n          cmd.createOption(helpOption.short, helpOption.description),\n        );\n      }\n    }\n    if (this.sortOptions) {\n      visibleOptions.sort(this.compareOptions);\n    }\n    return visibleOptions;\n  }\n\n  /**\n   * Get an array of the visible global options. (Not including help.)\n   *\n   * @param {Command} cmd\n   * @returns {Option[]}\n   */\n\n  visibleGlobalOptions(cmd) {\n    if (!this.showGlobalOptions) return [];\n\n    const globalOptions = [];\n    for (\n      let ancestorCmd = cmd.parent;\n      ancestorCmd;\n      ancestorCmd = ancestorCmd.parent\n    ) {\n      const visibleOptions = ancestorCmd.options.filter(\n        (option) => !option.hidden,\n      );\n      globalOptions.push(...visibleOptions);\n    }\n    if (this.sortOptions) {\n      globalOptions.sort(this.compareOptions);\n    }\n    return globalOptions;\n  }\n\n  /**\n   * Get an array of the arguments if any have a description.\n   *\n   * @param {Command} cmd\n   * @returns {Argument[]}\n   */\n\n  visibleArguments(cmd) {\n    // Side effect! Apply the legacy descriptions before the arguments are displayed.\n    if (cmd._argsDescription) {\n      cmd.registeredArguments.forEach((argument) => {\n        argument.description =\n          argument.description || cmd._argsDescription[argument.name()] || '';\n      });\n    }\n\n    // If there are any arguments with a description then return all the arguments.\n    if (cmd.registeredArguments.find((argument) => argument.description)) {\n      return cmd.registeredArguments;\n    }\n    return [];\n  }\n\n  /**\n   * Get the command term to show in the list of subcommands.\n   *\n   * @param {Command} cmd\n   * @returns {string}\n   */\n\n  subcommandTerm(cmd) {\n    // Legacy. Ignores custom usage string, and nested commands.\n    const args = cmd.registeredArguments\n      .map((arg) => humanReadableArgName(arg))\n      .join(' ');\n    return (\n      cmd._name +\n      (cmd._aliases[0] ? '|' + cmd._aliases[0] : '') +\n      (cmd.options.length ? ' [options]' : '') + // simplistic check for non-help option\n      (args ? ' ' + args : '')\n    );\n  }\n\n  /**\n   * Get the option term to show in the list of options.\n   *\n   * @param {Option} option\n   * @returns {string}\n   */\n\n  optionTerm(option) {\n    return option.flags;\n  }\n\n  /**\n   * Get the argument term to show in the list of arguments.\n   *\n   * @param {Argument} argument\n   * @returns {string}\n   */\n\n  argumentTerm(argument) {\n    return argument.name();\n  }\n\n  /**\n   * Get the longest command term length.\n   *\n   * @param {Command} cmd\n   * @param {Help} helper\n   * @returns {number}\n   */\n\n  longestSubcommandTermLength(cmd, helper) {\n    return helper.visibleCommands(cmd).reduce((max, command) => {\n      return Math.max(\n        max,\n        this.displayWidth(\n          helper.styleSubcommandTerm(helper.subcommandTerm(command)),\n        ),\n      );\n    }, 0);\n  }\n\n  /**\n   * Get the longest option term length.\n   *\n   * @param {Command} cmd\n   * @param {Help} helper\n   * @returns {number}\n   */\n\n  longestOptionTermLength(cmd, helper) {\n    return helper.visibleOptions(cmd).reduce((max, option) => {\n      return Math.max(\n        max,\n        this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))),\n      );\n    }, 0);\n  }\n\n  /**\n   * Get the longest global option term length.\n   *\n   * @param {Command} cmd\n   * @param {Help} helper\n   * @returns {number}\n   */\n\n  longestGlobalOptionTermLength(cmd, helper) {\n    return helper.visibleGlobalOptions(cmd).reduce((max, option) => {\n      return Math.max(\n        max,\n        this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))),\n      );\n    }, 0);\n  }\n\n  /**\n   * Get the longest argument term length.\n   *\n   * @param {Command} cmd\n   * @param {Help} helper\n   * @returns {number}\n   */\n\n  longestArgumentTermLength(cmd, helper) {\n    return helper.visibleArguments(cmd).reduce((max, argument) => {\n      return Math.max(\n        max,\n        this.displayWidth(\n          helper.styleArgumentTerm(helper.argumentTerm(argument)),\n        ),\n      );\n    }, 0);\n  }\n\n  /**\n   * Get the command usage to be displayed at the top of the built-in help.\n   *\n   * @param {Command} cmd\n   * @returns {string}\n   */\n\n  commandUsage(cmd) {\n    // Usage\n    let cmdName = cmd._name;\n    if (cmd._aliases[0]) {\n      cmdName = cmdName + '|' + cmd._aliases[0];\n    }\n    let ancestorCmdNames = '';\n    for (\n      let ancestorCmd = cmd.parent;\n      ancestorCmd;\n      ancestorCmd = ancestorCmd.parent\n    ) {\n      ancestorCmdNames = ancestorCmd.name() + ' ' + ancestorCmdNames;\n    }\n    return ancestorCmdNames + cmdName + ' ' + cmd.usage();\n  }\n\n  /**\n   * Get the description for the command.\n   *\n   * @param {Command} cmd\n   * @returns {string}\n   */\n\n  commandDescription(cmd) {\n    // @ts-ignore: because overloaded return type\n    return cmd.description();\n  }\n\n  /**\n   * Get the subcommand summary to show in the list of subcommands.\n   * (Fallback to description for backwards compatibility.)\n   *\n   * @param {Command} cmd\n   * @returns {string}\n   */\n\n  subcommandDescription(cmd) {\n    // @ts-ignore: because overloaded return type\n    return cmd.summary() || cmd.description();\n  }\n\n  /**\n   * Get the option description to show in the list of options.\n   *\n   * @param {Option} option\n   * @return {string}\n   */\n\n  optionDescription(option) {\n    const extraInfo = [];\n\n    if (option.argChoices) {\n      extraInfo.push(\n        // use stringify to match the display of the default value\n        `choices: ${option.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`,\n      );\n    }\n    if (option.defaultValue !== undefined) {\n      // default for boolean and negated more for programmer than end user,\n      // but show true/false for boolean option as may be for hand-rolled env or config processing.\n      const showDefault =\n        option.required ||\n        option.optional ||\n        (option.isBoolean() && typeof option.defaultValue === 'boolean');\n      if (showDefault) {\n        extraInfo.push(\n          `default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`,\n        );\n      }\n    }\n    // preset for boolean and negated are more for programmer than end user\n    if (option.presetArg !== undefined && option.optional) {\n      extraInfo.push(`preset: ${JSON.stringify(option.presetArg)}`);\n    }\n    if (option.envVar !== undefined) {\n      extraInfo.push(`env: ${option.envVar}`);\n    }\n    if (extraInfo.length > 0) {\n      const extraDescription = `(${extraInfo.join(', ')})`;\n      if (option.description) {\n        return `${option.description} ${extraDescription}`;\n      }\n      return extraDescription;\n    }\n\n    return option.description;\n  }\n\n  /**\n   * Get the argument description to show in the list of arguments.\n   *\n   * @param {Argument} argument\n   * @return {string}\n   */\n\n  argumentDescription(argument) {\n    const extraInfo = [];\n    if (argument.argChoices) {\n      extraInfo.push(\n        // use stringify to match the display of the default value\n        `choices: ${argument.argChoices.map((choice) => JSON.stringify(choice)).join(', ')}`,\n      );\n    }\n    if (argument.defaultValue !== undefined) {\n      extraInfo.push(\n        `default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`,\n      );\n    }\n    if (extraInfo.length > 0) {\n      const extraDescription = `(${extraInfo.join(', ')})`;\n      if (argument.description) {\n        return `${argument.description} ${extraDescription}`;\n      }\n      return extraDescription;\n    }\n    return argument.description;\n  }\n\n  /**\n   * Format a list of items, given a heading and an array of formatted items.\n   *\n   * @param {string} heading\n   * @param {string[]} items\n   * @param {Help} helper\n   * @returns string[]\n   */\n  formatItemList(heading, items, helper) {\n    if (items.length === 0) return [];\n\n    return [helper.styleTitle(heading), ...items, ''];\n  }\n\n  /**\n   * Group items by their help group heading.\n   *\n   * @param {Command[] | Option[]} unsortedItems\n   * @param {Command[] | Option[]} visibleItems\n   * @param {Function} getGroup\n   * @returns {Map<string, Command[] | Option[]>}\n   */\n  groupItems(unsortedItems, visibleItems, getGroup) {\n    const result = new Map();\n    // Add groups in order of appearance in unsortedItems.\n    unsortedItems.forEach((item) => {\n      const group = getGroup(item);\n      if (!result.has(group)) result.set(group, []);\n    });\n    // Add items in order of appearance in visibleItems.\n    visibleItems.forEach((item) => {\n      const group = getGroup(item);\n      if (!result.has(group)) {\n        result.set(group, []);\n      }\n      result.get(group).push(item);\n    });\n    return result;\n  }\n\n  /**\n   * Generate the built-in help text.\n   *\n   * @param {Command} cmd\n   * @param {Help} helper\n   * @returns {string}\n   */\n\n  formatHelp(cmd, helper) {\n    const termWidth = helper.padWidth(cmd, helper);\n    const helpWidth = helper.helpWidth ?? 80; // in case prepareContext() was not called\n\n    function callFormatItem(term, description) {\n      return helper.formatItem(term, termWidth, description, helper);\n    }\n\n    // Usage\n    let output = [\n      `${helper.styleTitle('Usage:')} ${helper.styleUsage(helper.commandUsage(cmd))}`,\n      '',\n    ];\n\n    // Description\n    const commandDescription = helper.commandDescription(cmd);\n    if (commandDescription.length > 0) {\n      output = output.concat([\n        helper.boxWrap(\n          helper.styleCommandDescription(commandDescription),\n          helpWidth,\n        ),\n        '',\n      ]);\n    }\n\n    // Arguments\n    const argumentList = helper.visibleArguments(cmd).map((argument) => {\n      return callFormatItem(\n        helper.styleArgumentTerm(helper.argumentTerm(argument)),\n        helper.styleArgumentDescription(helper.argumentDescription(argument)),\n      );\n    });\n    output = output.concat(\n      this.formatItemList('Arguments:', argumentList, helper),\n    );\n\n    // Options\n    const optionGroups = this.groupItems(\n      cmd.options,\n      helper.visibleOptions(cmd),\n      (option) => option.helpGroupHeading ?? 'Options:',\n    );\n    optionGroups.forEach((options, group) => {\n      const optionList = options.map((option) => {\n        return callFormatItem(\n          helper.styleOptionTerm(helper.optionTerm(option)),\n          helper.styleOptionDescription(helper.optionDescription(option)),\n        );\n      });\n      output = output.concat(this.formatItemList(group, optionList, helper));\n    });\n\n    if (helper.showGlobalOptions) {\n      const globalOptionList = helper\n        .visibleGlobalOptions(cmd)\n        .map((option) => {\n          return callFormatItem(\n            helper.styleOptionTerm(helper.optionTerm(option)),\n            helper.styleOptionDescription(helper.optionDescription(option)),\n          );\n        });\n      output = output.concat(\n        this.formatItemList('Global Options:', globalOptionList, helper),\n      );\n    }\n\n    // Commands\n    const commandGroups = this.groupItems(\n      cmd.commands,\n      helper.visibleCommands(cmd),\n      (sub) => sub.helpGroup() || 'Commands:',\n    );\n    commandGroups.forEach((commands, group) => {\n      const commandList = commands.map((sub) => {\n        return callFormatItem(\n          helper.styleSubcommandTerm(helper.subcommandTerm(sub)),\n          helper.styleSubcommandDescription(helper.subcommandDescription(sub)),\n        );\n      });\n      output = output.concat(this.formatItemList(group, commandList, helper));\n    });\n\n    return output.join('\\n');\n  }\n\n  /**\n   * Return display width of string, ignoring ANSI escape sequences. Used in padding and wrapping calculations.\n   *\n   * @param {string} str\n   * @returns {number}\n   */\n  displayWidth(str) {\n    return stripColor(str).length;\n  }\n\n  /**\n   * Style the title for displaying in the help. Called with 'Usage:', 'Options:', etc.\n   *\n   * @param {string} str\n   * @returns {string}\n   */\n  styleTitle(str) {\n    return str;\n  }\n\n  styleUsage(str) {\n    // Usage has lots of parts the user might like to color separately! Assume default usage string which is formed like:\n    //    command subcommand [options] [command] <foo> [bar]\n    return str\n      .split(' ')\n      .map((word) => {\n        if (word === '[options]') return this.styleOptionText(word);\n        if (word === '[command]') return this.styleSubcommandText(word);\n        if (word[0] === '[' || word[0] === '<')\n          return this.styleArgumentText(word);\n        return this.styleCommandText(word); // Restrict to initial words?\n      })\n      .join(' ');\n  }\n  styleCommandDescription(str) {\n    return this.styleDescriptionText(str);\n  }\n  styleOptionDescription(str) {\n    return this.styleDescriptionText(str);\n  }\n  styleSubcommandDescription(str) {\n    return this.styleDescriptionText(str);\n  }\n  styleArgumentDescription(str) {\n    return this.styleDescriptionText(str);\n  }\n  styleDescriptionText(str) {\n    return str;\n  }\n  styleOptionTerm(str) {\n    return this.styleOptionText(str);\n  }\n  styleSubcommandTerm(str) {\n    // This is very like usage with lots of parts! Assume default string which is formed like:\n    //    subcommand [options] <foo> [bar]\n    return str\n      .split(' ')\n      .map((word) => {\n        if (word === '[options]') return this.styleOptionText(word);\n        if (word[0] === '[' || word[0] === '<')\n          return this.styleArgumentText(word);\n        return this.styleSubcommandText(word); // Restrict to initial words?\n      })\n      .join(' ');\n  }\n  styleArgumentTerm(str) {\n    return this.styleArgumentText(str);\n  }\n  styleOptionText(str) {\n    return str;\n  }\n  styleArgumentText(str) {\n    return str;\n  }\n  styleSubcommandText(str) {\n    return str;\n  }\n  styleCommandText(str) {\n    return str;\n  }\n\n  /**\n   * Calculate the pad width from the maximum term length.\n   *\n   * @param {Command} cmd\n   * @param {Help} helper\n   * @returns {number}\n   */\n\n  padWidth(cmd, helper) {\n    return Math.max(\n      helper.longestOptionTermLength(cmd, helper),\n      helper.longestGlobalOptionTermLength(cmd, helper),\n      helper.longestSubcommandTermLength(cmd, helper),\n      helper.longestArgumentTermLength(cmd, helper),\n    );\n  }\n\n  /**\n   * Detect manually wrapped and indented strings by checking for line break followed by whitespace.\n   *\n   * @param {string} str\n   * @returns {boolean}\n   */\n  preformatted(str) {\n    return /\\n[^\\S\\r\\n]/.test(str);\n  }\n\n  /**\n   * Format the \"item\", which consists of a term and description. Pad the term and wrap the description, indenting the following lines.\n   *\n   * So \"TTT\", 5, \"DDD DDDD DD DDD\" might be formatted for this.helpWidth=17 like so:\n   *   TTT  DDD DDDD\n   *        DD DDD\n   *\n   * @param {string} term\n   * @param {number} termWidth\n   * @param {string} description\n   * @param {Help} helper\n   * @returns {string}\n   */\n  formatItem(term, termWidth, description, helper) {\n    const itemIndent = 2;\n    const itemIndentStr = ' '.repeat(itemIndent);\n    if (!description) return itemIndentStr + term;\n\n    // Pad the term out to a consistent width, so descriptions are aligned.\n    const paddedTerm = term.padEnd(\n      termWidth + term.length - helper.displayWidth(term),\n    );\n\n    // Format the description.\n    const spacerWidth = 2; // between term and description\n    const helpWidth = this.helpWidth ?? 80; // in case prepareContext() was not called\n    const remainingWidth = helpWidth - termWidth - spacerWidth - itemIndent;\n    let formattedDescription;\n    if (\n      remainingWidth < this.minWidthToWrap ||\n      helper.preformatted(description)\n    ) {\n      formattedDescription = description;\n    } else {\n      const wrappedDescription = helper.boxWrap(description, remainingWidth);\n      formattedDescription = wrappedDescription.replace(\n        /\\n/g,\n        '\\n' + ' '.repeat(termWidth + spacerWidth),\n      );\n    }\n\n    // Construct and overall indent.\n    return (\n      itemIndentStr +\n      paddedTerm +\n      ' '.repeat(spacerWidth) +\n      formattedDescription.replace(/\\n/g, `\\n${itemIndentStr}`)\n    );\n  }\n\n  /**\n   * Wrap a string at whitespace, preserving existing line breaks.\n   * Wrapping is skipped if the width is less than `minWidthToWrap`.\n   *\n   * @param {string} str\n   * @param {number} width\n   * @returns {string}\n   */\n  boxWrap(str, width) {\n    if (width < this.minWidthToWrap) return str;\n\n    const rawLines = str.split(/\\r\\n|\\n/);\n    // split up text by whitespace\n    const chunkPattern = /[\\s]*[^\\s]+/g;\n    const wrappedLines = [];\n    rawLines.forEach((line) => {\n      const chunks = line.match(chunkPattern);\n      if (chunks === null) {\n        wrappedLines.push('');\n        return;\n      }\n\n      let sumChunks = [chunks.shift()];\n      let sumWidth = this.displayWidth(sumChunks[0]);\n      chunks.forEach((chunk) => {\n        const visibleWidth = this.displayWidth(chunk);\n        // Accumulate chunks while they fit into width.\n        if (sumWidth + visibleWidth <= width) {\n          sumChunks.push(chunk);\n          sumWidth += visibleWidth;\n          return;\n        }\n        wrappedLines.push(sumChunks.join(''));\n\n        const nextChunk = chunk.trimStart(); // trim space at line break\n        sumChunks = [nextChunk];\n        sumWidth = this.displayWidth(nextChunk);\n      });\n      wrappedLines.push(sumChunks.join(''));\n    });\n\n    return wrappedLines.join('\\n');\n  }\n}\n\n/**\n * Strip style ANSI escape sequences from the string. In particular, SGR (Select Graphic Rendition) codes.\n *\n * @param {string} str\n * @returns {string}\n * @package\n */\n\nfunction stripColor(str) {\n  // eslint-disable-next-line no-control-regex\n  const sgrPattern = /\\x1b\\[\\d*(;\\d*)*m/g;\n  return str.replace(sgrPattern, '');\n}\n\nexports.Help = Help;\nexports.stripColor = stripColor;\n"
  },
  {
    "path": "lib/option.js",
    "content": "const { InvalidArgumentError } = require('./error.js');\n\nclass Option {\n  /**\n   * Initialize a new `Option` with the given `flags` and `description`.\n   *\n   * @param {string} flags\n   * @param {string} [description]\n   */\n\n  constructor(flags, description) {\n    this.flags = flags;\n    this.description = description || '';\n\n    this.required = flags.includes('<'); // A value must be supplied when the option is specified.\n    this.optional = flags.includes('['); // A value is optional when the option is specified.\n    // variadic test ignores <value,...> et al which might be used to describe custom splitting of single argument\n    this.variadic = /\\w\\.\\.\\.[>\\]]$/.test(flags); // The option can take multiple values.\n    this.mandatory = false; // The option must have a value after parsing, which usually means it must be specified on command line.\n    const optionFlags = splitOptionFlags(flags);\n    this.short = optionFlags.shortFlag; // May be a short flag, undefined, or even a long flag (if option has two long flags).\n    this.long = optionFlags.longFlag;\n    this.negate = false;\n    if (this.long) {\n      this.negate = this.long.startsWith('--no-');\n    }\n    this.defaultValue = undefined;\n    this.defaultValueDescription = undefined;\n    this.presetArg = undefined;\n    this.envVar = undefined;\n    this.parseArg = undefined;\n    this.hidden = false;\n    this.argChoices = undefined;\n    this.conflictsWith = [];\n    this.implied = undefined;\n    this.helpGroupHeading = undefined; // soft initialised when option added to command\n  }\n\n  /**\n   * Set the default value, and optionally supply the description to be displayed in the help.\n   *\n   * @param {*} value\n   * @param {string} [description]\n   * @return {Option}\n   */\n\n  default(value, description) {\n    this.defaultValue = value;\n    this.defaultValueDescription = description;\n    return this;\n  }\n\n  /**\n   * Preset to use when option used without option-argument, especially optional but also boolean and negated.\n   * The custom processing (parseArg) is called.\n   *\n   * @example\n   * new Option('--color').default('GREYSCALE').preset('RGB');\n   * new Option('--donate [amount]').preset('20').argParser(parseFloat);\n   *\n   * @param {*} arg\n   * @return {Option}\n   */\n\n  preset(arg) {\n    this.presetArg = arg;\n    return this;\n  }\n\n  /**\n   * Add option name(s) that conflict with this option.\n   * An error will be displayed if conflicting options are found during parsing.\n   *\n   * @example\n   * new Option('--rgb').conflicts('cmyk');\n   * new Option('--js').conflicts(['ts', 'jsx']);\n   *\n   * @param {(string | string[])} names\n   * @return {Option}\n   */\n\n  conflicts(names) {\n    this.conflictsWith = this.conflictsWith.concat(names);\n    return this;\n  }\n\n  /**\n   * Specify implied option values for when this option is set and the implied options are not.\n   *\n   * The custom processing (parseArg) is not called on the implied values.\n   *\n   * @example\n   * program\n   *   .addOption(new Option('--log', 'write logging information to file'))\n   *   .addOption(new Option('--trace', 'log extra details').implies({ log: 'trace.txt' }));\n   *\n   * @param {object} impliedOptionValues\n   * @return {Option}\n   */\n  implies(impliedOptionValues) {\n    let newImplied = impliedOptionValues;\n    if (typeof impliedOptionValues === 'string') {\n      // string is not documented, but easy mistake and we can do what user probably intended.\n      newImplied = { [impliedOptionValues]: true };\n    }\n    this.implied = Object.assign(this.implied || {}, newImplied);\n    return this;\n  }\n\n  /**\n   * Set environment variable to check for option value.\n   *\n   * An environment variable is only used if when processed the current option value is\n   * undefined, or the source of the current value is 'default' or 'config' or 'env'.\n   *\n   * @param {string} name\n   * @return {Option}\n   */\n\n  env(name) {\n    this.envVar = name;\n    return this;\n  }\n\n  /**\n   * Set the custom handler for processing CLI option arguments into option values.\n   *\n   * @param {Function} [fn]\n   * @return {Option}\n   */\n\n  argParser(fn) {\n    this.parseArg = fn;\n    return this;\n  }\n\n  /**\n   * Whether the option is mandatory and must have a value after parsing.\n   *\n   * @param {boolean} [mandatory=true]\n   * @return {Option}\n   */\n\n  makeOptionMandatory(mandatory = true) {\n    this.mandatory = !!mandatory;\n    return this;\n  }\n\n  /**\n   * Hide option in help.\n   *\n   * @param {boolean} [hide=true]\n   * @return {Option}\n   */\n\n  hideHelp(hide = true) {\n    this.hidden = !!hide;\n    return this;\n  }\n\n  /**\n   * @package\n   */\n\n  _collectValue(value, previous) {\n    if (previous === this.defaultValue || !Array.isArray(previous)) {\n      return [value];\n    }\n\n    previous.push(value);\n    return previous;\n  }\n\n  /**\n   * Only allow option value to be one of choices.\n   *\n   * @param {string[]} values\n   * @return {Option}\n   */\n\n  choices(values) {\n    this.argChoices = values.slice();\n    this.parseArg = (arg, previous) => {\n      if (!this.argChoices.includes(arg)) {\n        throw new InvalidArgumentError(\n          `Allowed choices are ${this.argChoices.join(', ')}.`,\n        );\n      }\n      if (this.variadic) {\n        return this._collectValue(arg, previous);\n      }\n      return arg;\n    };\n    return this;\n  }\n\n  /**\n   * Return option name.\n   *\n   * @return {string}\n   */\n\n  name() {\n    if (this.long) {\n      return this.long.replace(/^--/, '');\n    }\n    return this.short.replace(/^-/, '');\n  }\n\n  /**\n   * Return option name, in a camelcase format that can be used\n   * as an object attribute key.\n   *\n   * @return {string}\n   */\n\n  attributeName() {\n    if (this.negate) {\n      return camelcase(this.name().replace(/^no-/, ''));\n    }\n    return camelcase(this.name());\n  }\n\n  /**\n   * Set the help group heading.\n   *\n   * @param {string} heading\n   * @return {Option}\n   */\n  helpGroup(heading) {\n    this.helpGroupHeading = heading;\n    return this;\n  }\n\n  /**\n   * Check if `arg` matches the short or long flag.\n   *\n   * @param {string} arg\n   * @return {boolean}\n   * @package\n   */\n\n  is(arg) {\n    return this.short === arg || this.long === arg;\n  }\n\n  /**\n   * Return whether a boolean option.\n   *\n   * Options are one of boolean, negated, required argument, or optional argument.\n   *\n   * @return {boolean}\n   * @package\n   */\n\n  isBoolean() {\n    return !this.required && !this.optional && !this.negate;\n  }\n}\n\n/**\n * This class is to make it easier to work with dual options, without changing the existing\n * implementation. We support separate dual options for separate positive and negative options,\n * like `--build` and `--no-build`, which share a single option value. This works nicely for some\n * use cases, but is tricky for others where we want separate behaviours despite\n * the single shared option value.\n */\nclass DualOptions {\n  /**\n   * @param {Option[]} options\n   */\n  constructor(options) {\n    this.positiveOptions = new Map();\n    this.negativeOptions = new Map();\n    this.dualOptions = new Set();\n    options.forEach((option) => {\n      if (option.negate) {\n        this.negativeOptions.set(option.attributeName(), option);\n      } else {\n        this.positiveOptions.set(option.attributeName(), option);\n      }\n    });\n    this.negativeOptions.forEach((value, key) => {\n      if (this.positiveOptions.has(key)) {\n        this.dualOptions.add(key);\n      }\n    });\n  }\n\n  /**\n   * Did the value come from the option, and not from possible matching dual option?\n   *\n   * @param {*} value\n   * @param {Option} option\n   * @returns {boolean}\n   */\n  valueFromOption(value, option) {\n    const optionKey = option.attributeName();\n    if (!this.dualOptions.has(optionKey)) return true;\n\n    // Use the value to deduce if (probably) came from the option.\n    const preset = this.negativeOptions.get(optionKey).presetArg;\n    const negativeValue = preset !== undefined ? preset : false;\n    return option.negate === (negativeValue === value);\n  }\n}\n\n/**\n * Convert string from kebab-case to camelCase.\n *\n * @param {string} str\n * @return {string}\n * @private\n */\n\nfunction camelcase(str) {\n  return str.split('-').reduce((str, word) => {\n    return str + word[0].toUpperCase() + word.slice(1);\n  });\n}\n\n/**\n * Split the short and long flag out of something like '-m,--mixed <value>'\n *\n * @private\n */\n\nfunction splitOptionFlags(flags) {\n  let shortFlag;\n  let longFlag;\n  // short flag, single dash and single character\n  const shortFlagExp = /^-[^-]$/;\n  // long flag, double dash and at least one character\n  const longFlagExp = /^--[^-]/;\n\n  const flagParts = flags.split(/[ |,]+/).concat('guard');\n  // Normal is short and/or long.\n  if (shortFlagExp.test(flagParts[0])) shortFlag = flagParts.shift();\n  if (longFlagExp.test(flagParts[0])) longFlag = flagParts.shift();\n  // Long then short. Rarely used but fine.\n  if (!shortFlag && shortFlagExp.test(flagParts[0]))\n    shortFlag = flagParts.shift();\n  // Allow two long flags, like '--ws, --workspace'\n  // This is the supported way to have a shortish option flag.\n  if (!shortFlag && longFlagExp.test(flagParts[0])) {\n    shortFlag = longFlag;\n    longFlag = flagParts.shift();\n  }\n\n  // Check for unprocessed flag. Fail noisily rather than silently ignore.\n  if (flagParts[0].startsWith('-')) {\n    const unsupportedFlag = flagParts[0];\n    const baseError = `option creation failed due to '${unsupportedFlag}' in option flags '${flags}'`;\n    if (/^-[^-][^-]/.test(unsupportedFlag))\n      throw new Error(\n        `${baseError}\n- a short flag is a single dash and a single character\n  - either use a single dash and a single character (for a short flag)\n  - or use a double dash for a long option (and can have two, like '--ws, --workspace')`,\n      );\n    if (shortFlagExp.test(unsupportedFlag))\n      throw new Error(`${baseError}\n- too many short flags`);\n    if (longFlagExp.test(unsupportedFlag))\n      throw new Error(`${baseError}\n- too many long flags`);\n\n    throw new Error(`${baseError}\n- unrecognised flag format`);\n  }\n  if (shortFlag === undefined && longFlag === undefined)\n    throw new Error(\n      `option creation failed due to no flags found in '${flags}'.`,\n    );\n\n  return { shortFlag, longFlag };\n}\n\nexports.Option = Option;\nexports.DualOptions = DualOptions;\n"
  },
  {
    "path": "lib/suggestSimilar.js",
    "content": "const maxDistance = 3;\n\nfunction editDistance(a, b) {\n  // https://en.wikipedia.org/wiki/Damerau–Levenshtein_distance\n  // Calculating optimal string alignment distance, no substring is edited more than once.\n  // (Simple implementation.)\n\n  // Quick early exit, return worst case.\n  if (Math.abs(a.length - b.length) > maxDistance)\n    return Math.max(a.length, b.length);\n\n  // distance between prefix substrings of a and b\n  const d = [];\n\n  // pure deletions turn a into empty string\n  for (let i = 0; i <= a.length; i++) {\n    d[i] = [i];\n  }\n  // pure insertions turn empty string into b\n  for (let j = 0; j <= b.length; j++) {\n    d[0][j] = j;\n  }\n\n  // fill matrix\n  for (let j = 1; j <= b.length; j++) {\n    for (let i = 1; i <= a.length; i++) {\n      let cost = 1;\n      if (a[i - 1] === b[j - 1]) {\n        cost = 0;\n      } else {\n        cost = 1;\n      }\n      d[i][j] = Math.min(\n        d[i - 1][j] + 1, // deletion\n        d[i][j - 1] + 1, // insertion\n        d[i - 1][j - 1] + cost, // substitution\n      );\n      // transposition\n      if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {\n        d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + 1);\n      }\n    }\n  }\n\n  return d[a.length][b.length];\n}\n\n/**\n * Find close matches, restricted to same number of edits.\n *\n * @param {string} word\n * @param {string[]} candidates\n * @returns {string}\n */\n\nfunction suggestSimilar(word, candidates) {\n  if (!candidates || candidates.length === 0) return '';\n  // remove possible duplicates\n  candidates = Array.from(new Set(candidates));\n\n  const searchingOptions = word.startsWith('--');\n  if (searchingOptions) {\n    word = word.slice(2);\n    candidates = candidates.map((candidate) => candidate.slice(2));\n  }\n\n  let similar = [];\n  let bestDistance = maxDistance;\n  const minSimilarity = 0.4;\n  candidates.forEach((candidate) => {\n    if (candidate.length <= 1) return; // no one character guesses\n\n    const distance = editDistance(word, candidate);\n    const length = Math.max(word.length, candidate.length);\n    const similarity = (length - distance) / length;\n    if (similarity > minSimilarity) {\n      if (distance < bestDistance) {\n        // better edit distance, throw away previous worse matches\n        bestDistance = distance;\n        similar = [candidate];\n      } else if (distance === bestDistance) {\n        similar.push(candidate);\n      }\n    }\n  });\n\n  similar.sort((a, b) => a.localeCompare(b));\n  if (searchingOptions) {\n    similar = similar.map((candidate) => `--${candidate}`);\n  }\n\n  if (similar.length > 1) {\n    return `\\n(Did you mean one of ${similar.join(', ')}?)`;\n  }\n  if (similar.length === 1) {\n    return `\\n(Did you mean ${similar[0]}?)`;\n  }\n  return '';\n}\n\nexports.suggestSimilar = suggestSimilar;\n"
  },
  {
    "path": "package-support.json",
    "content": "{\n  \"versions\": [\n    {\n      \"version\": \"*\",\n      \"target\": {\n        \"node\": \"supported\"\n      },\n      \"response\": {\n        \"type\": \"time-permitting\"\n      },\n      \"backing\": {\n        \"donations\": [\n          \"https://github.com/sponsors/abetomo\",\n          \"https://github.com/sponsors/shadowspawn\"\n        ]\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"commander\",\n  \"version\": \"14.0.3\",\n  \"description\": \"the complete solution for node.js command-line programs\",\n  \"keywords\": [\n    \"commander\",\n    \"command\",\n    \"option\",\n    \"parser\",\n    \"cli\",\n    \"argument\",\n    \"args\",\n    \"argv\"\n  ],\n  \"author\": \"TJ Holowaychuk <tj@vision-media.ca>\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/tj/commander.js.git\"\n  },\n  \"scripts\": {\n    \"check\": \"npm run check:type && npm run check:lint && npm run check:format\",\n    \"check:format\": \"prettier --check .\",\n    \"check:lint\": \"eslint .\",\n    \"check:type\": \"npm run check:type:js && npm run check:type:ts\",\n    \"check:type:ts\": \"tsd && tsc -p tsconfig.ts.json\",\n    \"check:type:js\": \"tsc -p tsconfig.js.json\",\n    \"fix\": \"npm run fix:lint && npm run fix:format\",\n    \"fix:format\": \"prettier --write .\",\n    \"fix:lint\": \"eslint --fix .\",\n    \"test\": \"jest && npm run check:type:ts\",\n    \"test-all\": \"jest && npm run test-esm && npm run check\",\n    \"test-esm\": \"node ./tests/esm-imports-test.mjs\"\n  },\n  \"files\": [\n    \"index.js\",\n    \"lib/*.js\",\n    \"esm.mjs\",\n    \"typings/index.d.ts\",\n    \"typings/esm.d.mts\",\n    \"package-support.json\"\n  ],\n  \"type\": \"commonjs\",\n  \"main\": \"./index.js\",\n  \"exports\": {\n    \".\": {\n      \"require\": {\n        \"types\": \"./typings/index.d.ts\",\n        \"default\": \"./index.js\"\n      },\n      \"import\": {\n        \"types\": \"./typings/esm.d.mts\",\n        \"default\": \"./esm.mjs\"\n      },\n      \"default\": \"./index.js\"\n    },\n    \"./esm.mjs\": {\n      \"types\": \"./typings/esm.d.mts\",\n      \"import\": \"./esm.mjs\"\n    }\n  },\n  \"devDependencies\": {\n    \"@eslint/js\": \"^9.4.0\",\n    \"@types/jest\": \"^30.0.0\",\n    \"@types/node\": \"^22.7.4\",\n    \"eslint\": \"^9.17.0\",\n    \"eslint-config-prettier\": \"^10.0.1\",\n    \"eslint-plugin-jest\": \"^29.0.1\",\n    \"globals\": \"^16.0.0\",\n    \"jest\": \"^30.0.3\",\n    \"prettier\": \"^3.2.5\",\n    \"ts-jest\": \"^29.0.3\",\n    \"tsd\": \"^0.33.0\",\n    \"typescript\": \"^5.0.4\",\n    \"typescript-eslint\": \"^8.12.2\"\n  },\n  \"types\": \"typings/index.d.ts\",\n  \"engines\": {\n    \"node\": \">=20\"\n  },\n  \"support\": true\n}\n"
  },
  {
    "path": "tests/args.literal.test.js",
    "content": "const commander = require('../');\n\n// Utility Conventions: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_02\n//\n// 12.2 Utility Syntax Guidelines, Guideline 10:\n// The first -- argument that is not an option-argument should be accepted as a delimiter indicating the end of options. Any following arguments should be treated as operands, even if they begin with the '-' character.\n\ntest('when arguments includes -- then stop processing options', () => {\n  const program = new commander.Command();\n  program\n    .option('-f, --foo', 'add some foo')\n    .option('-b, --bar', 'add some bar')\n    .argument('[args...]');\n  program.parse(['node', 'test', '--foo', '--', '--bar', 'baz']);\n  // More than one assert, ported from legacy test\n  const opts = program.opts();\n  expect(opts.foo).toBe(true);\n  expect(opts.bar).toBeUndefined();\n  expect(program.args).toEqual(['--bar', 'baz']);\n});\n\ntest('when arguments include -- then more literals are passed-through as args', () => {\n  const program = new commander.Command();\n  program\n    .option('-f, --foo', 'add some foo')\n    .option('-b, --bar', 'add some bar')\n    .argument('[args...]');\n  program.parse(['node', 'test', '--', 'cmd', '--', '--arg']);\n  expect(program.args).toEqual(['cmd', '--', '--arg']);\n});\n"
  },
  {
    "path": "tests/args.variadic.test.js",
    "content": "const commander = require('../');\n\n// Testing variadic arguments. Testing all the action arguments, but could test just variadicArg.\n\ndescribe('variadic argument', () => {\n  test('when no extra arguments specified for program then variadic arg is empty array', () => {\n    const actionMock = jest.fn();\n    const program = new commander.Command();\n    program.arguments('<id> [variadicArg...]').action(actionMock);\n\n    program.parse(['node', 'test', 'id']);\n\n    expect(actionMock).toHaveBeenCalledWith('id', [], program.opts(), program);\n  });\n\n  test('when extra arguments specified for program then variadic arg is array of values', () => {\n    const actionMock = jest.fn();\n    const program = new commander.Command();\n    program.arguments('<id> [variadicArg...]').action(actionMock);\n    const extraArguments = ['a', 'b', 'c'];\n\n    program.parse(['node', 'test', 'id', ...extraArguments]);\n\n    expect(actionMock).toHaveBeenCalledWith(\n      'id',\n      extraArguments,\n      program.opts(),\n      program,\n    );\n  });\n\n  test('when no extra arguments specified for command then variadic arg is empty array', () => {\n    const actionMock = jest.fn();\n    const program = new commander.Command();\n    const cmd = program.command('sub [variadicArg...]').action(actionMock);\n\n    program.parse(['node', 'test', 'sub']);\n\n    expect(actionMock).toHaveBeenCalledWith([], cmd.opts(), cmd);\n  });\n\n  test('when extra arguments specified for command then variadic arg is array of values', () => {\n    const actionMock = jest.fn();\n    const program = new commander.Command();\n    const cmd = program.command('sub [variadicArg...]').action(actionMock);\n    const extraArguments = ['a', 'b', 'c'];\n\n    program.parse(['node', 'test', 'sub', ...extraArguments]);\n\n    expect(actionMock).toHaveBeenCalledWith(extraArguments, cmd.opts(), cmd);\n  });\n\n  test('when program variadic argument not last then error', () => {\n    const program = new commander.Command();\n\n    expect(() => {\n      program.arguments('<variadicArg...> [optionalArg]');\n    }).toThrow(\"only the last argument can be variadic 'variadicArg'\");\n  });\n\n  test('when command variadic argument not last then error', () => {\n    const program = new commander.Command();\n\n    expect(() => {\n      program.command('sub <variadicArg...> [optionalArg]');\n    }).toThrow(\"only the last argument can be variadic 'variadicArg'\");\n  });\n\n  test('when variadic argument then usage shows variadic', () => {\n    const program = new commander.Command();\n    program.name('foo').arguments('[args...]');\n\n    expect(program.usage()).toBe('[options] [args...]');\n  });\n});\n"
  },
  {
    "path": "tests/argument.chain.test.js",
    "content": "const { Argument } = require('../');\n\ndescribe('Argument methods that should return this for chaining', () => {\n  test('when call .default() then returns this', () => {\n    const argument = new Argument('<value>');\n    const result = argument.default(3);\n    expect(result).toBe(argument);\n  });\n\n  test('when call .argParser() then returns this', () => {\n    const argument = new Argument('<value>');\n    const result = argument.argParser(() => {});\n    expect(result).toBe(argument);\n  });\n\n  test('when call .choices() then returns this', () => {\n    const argument = new Argument('<value>');\n    const result = argument.choices(['a']);\n    expect(result).toBe(argument);\n  });\n\n  test('when call .argRequired() then returns this', () => {\n    const argument = new Argument('<value>');\n    const result = argument.argRequired();\n    expect(result).toBe(argument);\n  });\n\n  test('when call .argOptional() then returns this', () => {\n    const argument = new Argument('<value>');\n    const result = argument.argOptional();\n    expect(result).toBe(argument);\n  });\n});\n"
  },
  {
    "path": "tests/argument.choices.test.js",
    "content": "const commander = require('../');\n\ntest('when command argument in choices then argument set', () => {\n  const program = new commander.Command();\n  let shade;\n  program\n    .exitOverride()\n    .addArgument(new commander.Argument('<shade>').choices(['red', 'blue']))\n    .action((shadeParam) => {\n      shade = shadeParam;\n    });\n  program.parse(['red'], { from: 'user' });\n  expect(shade).toBe('red');\n});\n\ntest('when command argument is not in choices then error', () => {\n  // Lightweight check, more detailed testing of behaviour in command.exitOverride.test.js\n  const program = new commander.Command();\n  program\n    .exitOverride()\n    .configureOutput({\n      writeErr: () => {},\n    })\n    .addArgument(new commander.Argument('<shade>').choices(['red', 'blue']));\n  expect(() => {\n    program.parse(['orange'], { from: 'user' });\n  }).toThrow();\n});\n\ndescribe('choices parameter is treated as readonly, per TypeScript declaration', () => {\n  test('when choices called then parameter does not change', () => {\n    // Unlikely this could break, but check the API we are declaring in TypeScript.\n    const original = ['red', 'blue', 'green'];\n    const param = original.slice();\n    new commander.Argument('<shade>').choices(param);\n    expect(param).toEqual(original);\n  });\n\n  test('when choices called and argChoices later changed then parameter does not change', () => {\n    const original = ['red', 'blue', 'green'];\n    const param = original.slice();\n    const argument = new commander.Argument('<shade>').choices(param);\n    argument.argChoices.push('purple');\n    expect(param).toEqual(original);\n  });\n\n  test('when choices called and parameter changed the choices does not change', () => {\n    const program = new commander.Command();\n    const param = ['red', 'blue'];\n    program\n      .exitOverride()\n      .configureOutput({\n        writeErr: () => {},\n      })\n      .addArgument(new commander.Argument('<shade>').choices(param));\n    param.push('orange');\n    expect(() => {\n      program.parse(['orange'], { from: 'user' });\n    }).toThrow();\n  });\n});\n"
  },
  {
    "path": "tests/argument.custom-processing.test.js",
    "content": "const commander = require('../');\n\n// Testing default value and custom processing behaviours.\n// Some double assertions in tests to check action argument and .processedArg\n\ntest('when argument not specified then callback not called', () => {\n  const mockCoercion = jest.fn();\n  const program = new commander.Command();\n  program.argument('[n]', 'number', mockCoercion).action(() => {});\n  program.parse([], { from: 'user' });\n  expect(mockCoercion).not.toHaveBeenCalled();\n});\n\ntest('when argument not specified then action argument undefined', () => {\n  let actionValue = 'foo';\n  const program = new commander.Command();\n  program.argument('[n]', 'number', parseFloat).action((arg) => {\n    actionValue = arg;\n  });\n  program.parse([], { from: 'user' });\n  expect(actionValue).toBeUndefined();\n});\n\ntest('when custom with starting value and argument not specified then callback not called', () => {\n  const mockCoercion = jest.fn();\n  const program = new commander.Command();\n  program.argument('[n]', 'number', parseFloat, 1).action(() => {});\n  program.parse([], { from: 'user' });\n  expect(mockCoercion).not.toHaveBeenCalled();\n});\n\ntest('when custom with starting value and argument not specified with action handler then action argument is starting value', () => {\n  const startingValue = 1;\n  let actionValue;\n  const program = new commander.Command();\n  program.argument('[n]', 'number', parseFloat, startingValue).action((arg) => {\n    actionValue = arg;\n  });\n  program.parse([], { from: 'user' });\n  expect(actionValue).toEqual(startingValue);\n  expect(program.processedArgs).toEqual([startingValue]);\n});\n\ntest('when custom with starting value and argument not specified without action handler then .processedArgs has starting value', () => {\n  const startingValue = 1;\n  const program = new commander.Command();\n  program.argument('[n]', 'number', parseFloat, startingValue);\n  program.parse([], { from: 'user' });\n  expect(program.processedArgs).toEqual([startingValue]);\n});\n\ntest('when default value is defined (without custom processing) and argument not specified with action handler then action argument is default value', () => {\n  const defaultValue = 1;\n  let actionValue;\n  const program = new commander.Command();\n  program.argument('[n]', 'number', defaultValue).action((arg) => {\n    actionValue = arg;\n  });\n  program.parse([], { from: 'user' });\n  expect(actionValue).toEqual(defaultValue);\n  expect(program.processedArgs).toEqual([defaultValue]);\n});\n\ntest('when default value is defined (without custom processing) and argument not specified without action handler then .processedArgs is default value', () => {\n  const defaultValue = 1;\n  const program = new commander.Command();\n  program.argument('[n]', 'number', defaultValue);\n  program.parse([], { from: 'user' });\n  expect(program.processedArgs).toEqual([defaultValue]);\n});\n\ntest('when argument specified then callback called with value', () => {\n  const mockCoercion = jest.fn();\n  const value = '1';\n  const program = new commander.Command();\n  program.argument('[n]', 'number', mockCoercion).action(() => {});\n  program.parse([value], { from: 'user' });\n  expect(mockCoercion).toHaveBeenCalledWith(value, undefined);\n});\n\ntest('when argument specified with action handler then action value is as returned from callback', () => {\n  const callbackResult = 2;\n  let actionValue;\n  const program = new commander.Command();\n  program\n    .argument('[n]', 'number', () => {\n      return callbackResult;\n    })\n    .action((arg) => {\n      actionValue = arg;\n    });\n  program.parse(['node', 'test', 'alpha']);\n  expect(actionValue).toEqual(callbackResult);\n  expect(program.processedArgs).toEqual([callbackResult]);\n});\n\ntest('when argument specified without action handler then .processedArgs is as returned from callback', () => {\n  const callbackResult = 2;\n  const program = new commander.Command();\n  program.argument('[n]', 'number', () => {\n    return callbackResult;\n  });\n  program.parse(['node', 'test', 'alpha']);\n  expect(program.processedArgs).toEqual([callbackResult]);\n});\n\ntest('when argument specified then program.args has original rather than custom', () => {\n  // This is as intended, so check behaviour.\n  const callbackResult = 2;\n  const program = new commander.Command();\n  program\n    .argument('[n]', 'number', () => {\n      return callbackResult;\n    })\n    .action(() => {});\n  program.parse(['node', 'test', 'alpha']);\n  expect(program.args).toEqual(['alpha']);\n});\n\ntest('when custom with starting value and argument specified then callback called with value and starting value', () => {\n  const mockCoercion = jest.fn();\n  const startingValue = 1;\n  const value = '2';\n  const program = new commander.Command()\n    .argument('[n]', 'number', mockCoercion, startingValue)\n    .action(() => {});\n  program.parse(['node', 'test', value]);\n  expect(mockCoercion).toHaveBeenCalledWith(value, startingValue);\n});\n\ntest('when variadic argument specified multiple times then callback called with value and previousValue', () => {\n  const mockCoercion = jest.fn().mockImplementation(() => {\n    return 'callback';\n  });\n  const program = new commander.Command();\n  program.argument('<n...>', 'number', mockCoercion).action(() => {});\n  program.parse(['1', '2'], { from: 'user' });\n  expect(mockCoercion).toHaveBeenCalledTimes(2);\n  expect(mockCoercion).toHaveBeenNthCalledWith(1, '1', undefined);\n  expect(mockCoercion).toHaveBeenNthCalledWith(2, '2', 'callback');\n});\n\ntest('when variadic argument without action handler then .processedArg has array', () => {\n  const program = new commander.Command();\n  program.argument('<n...>', 'number');\n  program.parse(['1', '2'], { from: 'user' });\n  expect(program.processedArgs).toEqual([['1', '2']]);\n});\n\ntest('when parseFloat \"1e2\" then action argument is 100', () => {\n  let actionValue;\n  const program = new commander.Command();\n  program.argument('<number>', 'float argument', parseFloat).action((arg) => {\n    actionValue = arg;\n  });\n  program.parse(['1e2'], { from: 'user' });\n  expect(actionValue).toEqual(100);\n  expect(program.processedArgs).toEqual([actionValue]);\n});\n\ntest('when defined default value for required argument then throw', () => {\n  const program = new commander.Command();\n  expect(() => {\n    program.argument('<number>', 'float argument', 4);\n  }).toThrow();\n});\n\ntest('when custom processing for argument throws plain error then not CommanderError caught', () => {\n  function justSayNo(value) {\n    throw new Error('no no no');\n  }\n  const program = new commander.Command();\n  program\n    .exitOverride()\n    .argument('[n]', 'number', justSayNo)\n    .action(() => {});\n\n  let caughtErr;\n  try {\n    program.parse(['green'], { from: 'user' });\n  } catch (err) {\n    caughtErr = err;\n  }\n\n  expect(caughtErr).toBeInstanceOf(Error);\n  expect(caughtErr).not.toBeInstanceOf(commander.CommanderError);\n});\n"
  },
  {
    "path": "tests/argument.required.test.js",
    "content": "const commander = require('../');\n\n// Low-level tests of setting Argument.required.\n// Higher level tests of optional/required arguments elsewhere.\n\ntest('when name with surrounding <> then argument required', () => {\n  const argument = new commander.Argument('<name>');\n  expect(argument.required).toBe(true);\n});\n\ntest('when name with surrounding [] then argument optional', () => {\n  const argument = new commander.Argument('[name]');\n  expect(argument.required).toBe(false);\n});\n\ntest('when name without surrounding brackets then argument required', () => {\n  // default behaviour, allowed from Commander 8\n  const argument = new commander.Argument('name');\n  expect(argument.required).toBe(true);\n});\n\ntest('when call .argRequired() then argument required', () => {\n  const argument = new commander.Argument('name');\n  argument.required = false;\n  argument.argRequired();\n  expect(argument.required).toBe(true);\n});\n\ntest('when call .argOptional() then argument optional', () => {\n  const argument = new commander.Argument('name');\n  argument.required = true;\n  argument.argOptional();\n  expect(argument.required).toBe(false);\n});\n"
  },
  {
    "path": "tests/argument.variadic.test.js",
    "content": "const commander = require('../');\n\n// Testing variadic arguments. Testing all the action arguments, but could test just variadicArg.\n\ndescribe('variadic argument', () => {\n  test('when no extra arguments specified for program then variadic arg is empty array', () => {\n    const actionMock = jest.fn();\n    const program = new commander.Command();\n    program.argument('<id>').argument('[variadicArg...]').action(actionMock);\n\n    program.parse(['node', 'test', 'id']);\n\n    expect(actionMock).toHaveBeenCalledWith('id', [], program.opts(), program);\n  });\n\n  test('when extra arguments specified for program then variadic arg is array of values', () => {\n    const actionMock = jest.fn();\n    const program = new commander.Command();\n    program\n      .addArgument(new commander.Argument('<id>'))\n      .argument('[variadicArg...]')\n      .action(actionMock);\n    const extraArguments = ['a', 'b', 'c'];\n\n    program.parse(['node', 'test', 'id', ...extraArguments]);\n\n    expect(actionMock).toHaveBeenCalledWith(\n      'id',\n      extraArguments,\n      program.opts(),\n      program,\n    );\n  });\n\n  test('when no extra arguments specified for command then variadic arg is empty array', () => {\n    const actionMock = jest.fn();\n    const program = new commander.Command();\n    const cmd = program.command('sub [variadicArg...]').action(actionMock);\n\n    program.parse(['node', 'test', 'sub']);\n\n    expect(actionMock).toHaveBeenCalledWith([], cmd.opts(), cmd);\n  });\n\n  test('when extra arguments specified for command then variadic arg is array of values', () => {\n    const actionMock = jest.fn();\n    const program = new commander.Command();\n    const cmd = program.command('sub [variadicArg...]').action(actionMock);\n    const extraArguments = ['a', 'b', 'c'];\n\n    program.parse(['node', 'test', 'sub', ...extraArguments]);\n\n    expect(actionMock).toHaveBeenCalledWith(extraArguments, cmd.opts(), cmd);\n  });\n\n  test('when program variadic argument not last then error', () => {\n    const program = new commander.Command();\n\n    expect(() => {\n      program.argument('<variadicArg...>').argument('[optionalArg]');\n    }).toThrow(\"only the last argument can be variadic 'variadicArg'\");\n  });\n\n  test('when command variadic argument not last then error', () => {\n    const program = new commander.Command();\n\n    expect(() => {\n      program.command('sub <variadicArg...> [optionalArg]');\n    }).toThrow(\"only the last argument can be variadic 'variadicArg'\");\n  });\n\n  test('when variadic argument then usage shows variadic', () => {\n    const program = new commander.Command();\n    program.name('foo').argument('[args...]');\n\n    expect(program.usage()).toBe('[options] [args...]');\n  });\n\n  test('when variadic used with choices and one value then set in array', () => {\n    const program = new commander.Command();\n    let passedArg;\n    program\n      .addArgument(new commander.Argument('<value...>').choices(['one', 'two']))\n      .action((value) => {\n        passedArg = value;\n      });\n\n    program.parse(['one'], { from: 'user' });\n    expect(passedArg).toEqual(['one']);\n  });\n\n  test('when variadic used with choices and two values then set in array', () => {\n    const program = new commander.Command();\n    let passedArg;\n    program\n      .addArgument(new commander.Argument('<value...>').choices(['one', 'two']))\n      .action((value) => {\n        passedArg = value;\n      });\n\n    program.parse(['one', 'two'], { from: 'user' });\n    expect(passedArg).toEqual(['one', 'two']);\n  });\n\n  test('when variadic has default array then specified value is used instead of default (not appended)', () => {\n    const program = new commander.Command();\n    let passedArg;\n    program\n      .addArgument(new commander.Argument('[value...]').default(['DEFAULT']))\n      .action((value) => {\n        passedArg = value;\n      });\n\n    program.parse(['one', 'two'], { from: 'user' });\n    expect(passedArg).toEqual(['one', 'two']);\n  });\n});\n"
  },
  {
    "path": "tests/command.action.test.js",
    "content": "const commander = require('../');\n\n// Test some behaviours of .action not covered in more specific tests.\n\ntest('when .action called then command passed to action', () => {\n  const actionMock = jest.fn();\n  const program = new commander.Command();\n  const cmd = program.command('info').action(actionMock);\n  program.parse(['node', 'test', 'info']);\n  expect(actionMock).toHaveBeenCalledWith(cmd.opts(), cmd);\n});\n\ntest('when .action called then this is set to command', () => {\n  const program = new commander.Command();\n  let actionThis;\n  const cmd = program.command('info').action(function () {\n    actionThis = this;\n  });\n  program.parse(['node', 'test', 'info']);\n  expect(actionThis).toBe(cmd);\n});\n\ntest('when .action called then program.args only contains args', () => {\n  // At one time program.args was being modified to contain the same args as the call to .action\n  // and so included the command as an extra and unexpected complex item in array.\n  const program = new commander.Command();\n  program.command('info <file>').action(() => {});\n  program.parse(['node', 'test', 'info', 'my-file']);\n  expect(program.args).toEqual(['info', 'my-file']);\n});\n\ntest.each(getTestCases('<file>'))(\n  'when .action on program with required argument via %s and argument supplied then action called',\n  (methodName, program) => {\n    const actionMock = jest.fn();\n    program.action(actionMock);\n    program.parse(['node', 'test', 'my-file']);\n    expect(actionMock).toHaveBeenCalledWith('my-file', program.opts(), program);\n  },\n);\n\ntest.each(getTestCases('<file>'))(\n  'when .action on program with required argument via %s and argument not supplied then action not called',\n  (methodName, program) => {\n    const actionMock = jest.fn();\n    program\n      .exitOverride()\n      .configureOutput({ writeErr: () => {} })\n      .action(actionMock);\n    expect(() => {\n      program.parse(['node', 'test']);\n    }).toThrow();\n    expect(actionMock).not.toHaveBeenCalled();\n  },\n);\n\n// Changes made in #729 to call program action handler\ntest('when .action on program and no arguments then action called', () => {\n  const actionMock = jest.fn();\n  const program = new commander.Command();\n  program.action(actionMock);\n  program.parse(['node', 'test']);\n  expect(actionMock).toHaveBeenCalledWith(program.opts(), program);\n});\n\ntest.each(getTestCases('[file]'))(\n  'when .action on program with optional argument via %s supplied then action called',\n  (methodName, program) => {\n    const actionMock = jest.fn();\n    program.action(actionMock);\n    program.parse(['node', 'test', 'my-file']);\n    expect(actionMock).toHaveBeenCalledWith('my-file', program.opts(), program);\n  },\n);\n\ntest.each(getTestCases('[file]'))(\n  'when .action on program without optional argument supplied then action called',\n  (methodName, program) => {\n    const actionMock = jest.fn();\n    program.action(actionMock);\n    program.parse(['node', 'test']);\n    expect(actionMock).toHaveBeenCalledWith(undefined, program.opts(), program);\n  },\n);\n\ntest.each(getTestCases('[file]'))(\n  'when .action on program with optional argument via %s and subcommand and program argument then program action called',\n  (methodName, program) => {\n    const actionMock = jest.fn();\n    program.action(actionMock);\n    program.command('subcommand');\n\n    program.parse(['node', 'test', 'a']);\n\n    expect(actionMock).toHaveBeenCalledWith('a', program.opts(), program);\n  },\n);\n\n// Changes made in #1062 to allow this case\ntest.each(getTestCases('[file]'))(\n  'when .action on program with optional argument via %s and subcommand and no program argument then program action called',\n  (methodName, program) => {\n    const actionMock = jest.fn();\n    program.action(actionMock);\n    program.command('subcommand');\n\n    program.parse(['node', 'test']);\n\n    expect(actionMock).toHaveBeenCalledWith(undefined, program.opts(), program);\n  },\n);\n\ntest('when action is async then can await parseAsync', async () => {\n  let asyncFinished = false;\n  async function delay() {\n    await new Promise((resolve) => setTimeout(resolve, 100));\n    asyncFinished = true;\n  }\n  const program = new commander.Command();\n  program.action(delay);\n\n  const later = program.parseAsync(['node', 'test']);\n  expect(asyncFinished).toBe(false);\n  await later;\n  expect(asyncFinished).toBe(true);\n});\n\nfunction getTestCases(arg) {\n  const withArguments = new commander.Command().arguments(arg);\n  const withArgument = new commander.Command().argument(arg);\n  const withAddArgument = new commander.Command().addArgument(\n    new commander.Argument(arg),\n  );\n  return [\n    ['.arguments', withArguments],\n    ['.argument', withArgument],\n    ['.addArgument', withAddArgument],\n  ];\n}\n"
  },
  {
    "path": "tests/command.addCommand.test.js",
    "content": "const commander = require('../');\n\n// simple sanity check subcommand works\ntest('when addCommand and specify subcommand then called', () => {\n  const program = new commander.Command();\n  const leafAction = jest.fn();\n  const sub = new commander.Command();\n  sub.name('sub').action(leafAction);\n  program.addCommand(sub);\n\n  program.parse('node test.js sub'.split(' '));\n  expect(leafAction).toHaveBeenCalled();\n});\n\ntest('when commands added using .addCommand and .command then internals similar', () => {\n  const program1 = new commander.Command();\n  program1.command('sub');\n  const program2 = new commander.Command();\n  program2.addCommand(new commander.Command('sub'));\n\n  // This is a bit of a cheat to check using .addCommand() produces similar result to .command(),\n  // since .command() is well tested and understood.\n\n  const cmd1 = program1.commands[0];\n  const cmd2 = program2.commands[0];\n  expect(cmd1.parent).toBe(program1);\n  expect(cmd2.parent).toBe(program2);\n\n  for (const key of Object.keys(cmd1)) {\n    switch (typeof cmd1[key]) {\n      case 'string':\n      case 'boolean':\n      case 'number':\n      case 'undefined':\n        // Compare values in a way that will be readable in test failure message.\n        // eslint-disable-next-line jest/no-conditional-expect\n        expect(`${key}:${cmd1[key]}`).toEqual(`${key}:${cmd2[key]}`);\n        break;\n    }\n  }\n});\n\ntest('when command without name passed to .addCommand then throw', () => {\n  const program = new commander.Command();\n  const cmd = new commander.Command();\n  expect(() => {\n    program.addCommand(cmd);\n  }).toThrow();\n});\n\ntest('when executable command with custom executableFile passed to .addCommand then ok', () => {\n  const program = new commander.Command();\n  const cmd = new commander.Command('sub');\n  cmd.command('exec', 'exec description', { executableFile: 'custom' });\n  expect(() => {\n    program.addCommand(cmd);\n  }).not.toThrow();\n});\n"
  },
  {
    "path": "tests/command.addHelpOption.test.js",
    "content": "const { Command, Option } = require('../');\n\n// More complete tests are in command.helpOption.test.js.\n\ndescribe('addHelpOption', () => {\n  let writeSpy;\n  let writeErrorSpy;\n\n  beforeAll(() => {\n    // Optional. Suppress expected output to keep test output clean.\n    writeSpy = jest.spyOn(process.stdout, 'write').mockImplementation(() => {});\n    writeErrorSpy = jest\n      .spyOn(process.stderr, 'write')\n      .mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    writeSpy.mockClear();\n    writeErrorSpy.mockClear();\n  });\n\n  afterAll(() => {\n    writeSpy.mockRestore();\n    writeErrorSpy.mockRestore();\n  });\n\n  test('when addHelpOption has custom flags then custom short flag invokes help', () => {\n    const program = new Command();\n    program.exitOverride().addHelpOption(new Option('-c,--custom-help'));\n\n    expect(() => {\n      program.parse(['-c'], { from: 'user' });\n    }).toThrow('(outputHelp)');\n  });\n\n  test('when addHelpOption has custom flags then custom long flag invokes help', () => {\n    const program = new Command();\n    program.exitOverride().addHelpOption(new Option('-c,--custom-help'));\n\n    expect(() => {\n      program.parse(['--custom-help'], { from: 'user' });\n    }).toThrow('(outputHelp)');\n  });\n\n  test('when addHelpOption with hidden help option then help does not include help option', () => {\n    const program = new Command();\n    program.addHelpOption(\n      new Option('-c,--custom-help', 'help help help').hideHelp(),\n    );\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).not.toMatch(/help/);\n  });\n});\n"
  },
  {
    "path": "tests/command.addHelpText.test.js",
    "content": "const commander = require('../');\n\n// Using outputHelp to simplify testing.\n\ndescribe('program calls to addHelpText', () => {\n  let writeSpy;\n\n  beforeAll(() => {\n    writeSpy = jest.spyOn(process.stdout, 'write').mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    writeSpy.mockClear();\n  });\n\n  afterAll(() => {\n    writeSpy.mockRestore();\n  });\n\n  test('when \"before\" string then string before built-in help', () => {\n    const program = new commander.Command();\n    program.addHelpText('before', 'text');\n    program.outputHelp();\n    expect(writeSpy).toHaveBeenNthCalledWith(1, 'text\\n');\n    expect(writeSpy).toHaveBeenNthCalledWith(2, program.helpInformation());\n  });\n\n  test('when \"before\" function then function result before built-in help', () => {\n    const program = new commander.Command();\n    program.addHelpText('before', () => 'text');\n    program.outputHelp();\n    expect(writeSpy).toHaveBeenNthCalledWith(1, 'text\\n');\n    expect(writeSpy).toHaveBeenNthCalledWith(2, program.helpInformation());\n  });\n\n  test('when \"before\" function returns nothing then no effect', () => {\n    const program = new commander.Command();\n    program.addHelpText('before', () => {});\n    program.outputHelp();\n    expect(writeSpy).toHaveBeenNthCalledWith(1, program.helpInformation());\n  });\n\n  test('when \"beforeAll\" string then string before built-in help', () => {\n    const program = new commander.Command();\n    program.addHelpText('beforeAll', 'text');\n    program.outputHelp();\n    expect(writeSpy).toHaveBeenNthCalledWith(1, 'text\\n');\n    expect(writeSpy).toHaveBeenNthCalledWith(2, program.helpInformation());\n  });\n\n  test('when \"after\" string then string after built-in help', () => {\n    const program = new commander.Command();\n    program.addHelpText('after', 'text');\n    program.outputHelp();\n    expect(writeSpy).toHaveBeenNthCalledWith(1, program.helpInformation());\n    expect(writeSpy).toHaveBeenNthCalledWith(2, 'text\\n');\n  });\n\n  test('when \"afterAll\" string then string after built-in help', () => {\n    const program = new commander.Command();\n    program.addHelpText('afterAll', 'text');\n    program.outputHelp();\n    expect(writeSpy).toHaveBeenNthCalledWith(1, program.helpInformation());\n    expect(writeSpy).toHaveBeenNthCalledWith(2, 'text\\n');\n  });\n\n  test('when all the simple positions then strings in order', () => {\n    const program = new commander.Command();\n    program.addHelpText('before', 'before');\n    program.addHelpText('after', 'after');\n    program.addHelpText('beforeAll', 'beforeAll');\n    program.addHelpText('afterAll', 'afterAll');\n    program.outputHelp();\n    expect(writeSpy).toHaveBeenNthCalledWith(1, 'beforeAll\\n');\n    expect(writeSpy).toHaveBeenNthCalledWith(2, 'before\\n');\n    expect(writeSpy).toHaveBeenNthCalledWith(3, program.helpInformation());\n    expect(writeSpy).toHaveBeenNthCalledWith(4, 'after\\n');\n    expect(writeSpy).toHaveBeenNthCalledWith(5, 'afterAll\\n');\n  });\n\n  test('when \"silly\" position then throw', () => {\n    const program = new commander.Command();\n    expect(() => {\n      program.addHelpText('silly', 'text');\n    }).toThrow();\n  });\n});\n\ndescribe('program and subcommand calls to addHelpText', () => {\n  let writeSpy;\n\n  beforeAll(() => {\n    writeSpy = jest.spyOn(process.stdout, 'write').mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    writeSpy.mockClear();\n  });\n\n  afterAll(() => {\n    writeSpy.mockRestore();\n  });\n\n  test('when \"before\" on program then not called on subcommand', () => {\n    const program = new commander.Command();\n    const sub = program.command('sub');\n    const testMock = jest.fn();\n    program.addHelpText('before', testMock);\n    sub.outputHelp();\n    expect(testMock).not.toHaveBeenCalled();\n  });\n\n  test('when \"beforeAll\" on program then is called on subcommand', () => {\n    const program = new commander.Command();\n    const sub = program.command('sub');\n    const testMock = jest.fn();\n    program.addHelpText('beforeAll', testMock);\n    sub.outputHelp();\n    expect(testMock).toHaveBeenCalled();\n  });\n\n  test('when \"after\" on program then not called on subcommand', () => {\n    const program = new commander.Command();\n    const sub = program.command('sub');\n    const testMock = jest.fn();\n    program.addHelpText('after', testMock);\n    sub.outputHelp();\n    expect(testMock).not.toHaveBeenCalled();\n  });\n\n  test('when \"afterAll\" on program then is called on subcommand', () => {\n    const program = new commander.Command();\n    const sub = program.command('sub');\n    const testMock = jest.fn();\n    program.addHelpText('afterAll', testMock);\n    sub.outputHelp();\n    expect(testMock).toHaveBeenCalled();\n  });\n});\n\ndescribe('context checks with full parse', () => {\n  let stdoutSpy;\n  let stderrSpy;\n\n  beforeAll(() => {\n    stdoutSpy = jest\n      .spyOn(process.stdout, 'write')\n      .mockImplementation(() => {});\n    stderrSpy = jest\n      .spyOn(process.stderr, 'write')\n      .mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    stdoutSpy.mockClear();\n    stderrSpy.mockClear();\n  });\n\n  afterAll(() => {\n    stdoutSpy.mockRestore();\n    stderrSpy.mockRestore();\n  });\n\n  test('when help requested then text is on stdout', () => {\n    const program = new commander.Command();\n    program.exitOverride().addHelpText('before', 'text');\n    expect(() => {\n      program.parse(['--help'], { from: 'user' });\n    }).toThrow();\n    expect(stdoutSpy).toHaveBeenCalledWith('text\\n');\n  });\n\n  test('when help for error then text is on stderr', () => {\n    const program = new commander.Command();\n    program.exitOverride().addHelpText('before', 'text').command('sub');\n    expect(() => {\n      program.parse([], { from: 'user' });\n    }).toThrow();\n    expect(stderrSpy).toHaveBeenCalledWith('text\\n');\n  });\n\n  test('when help requested then context.error is false', () => {\n    let context;\n    const program = new commander.Command();\n    program.exitOverride().addHelpText('before', (contextParam) => {\n      context = contextParam;\n    });\n    expect(() => {\n      program.parse(['--help'], { from: 'user' });\n    }).toThrow();\n    expect(context.error).toBe(false);\n  });\n\n  test('when help for error then context.error is true', () => {\n    let context;\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .addHelpText('before', (contextParam) => {\n        context = contextParam;\n      })\n      .command('sub');\n    expect(() => {\n      program.parse([], { from: 'user' });\n    }).toThrow();\n    expect(context.error).toBe(true);\n  });\n\n  test('when help on program then context.command is program', () => {\n    let context;\n    const program = new commander.Command();\n    program.exitOverride().addHelpText('before', (contextParam) => {\n      context = contextParam;\n    });\n    expect(() => {\n      program.parse(['--help'], { from: 'user' });\n    }).toThrow();\n    expect(context.command).toBe(program);\n  });\n\n  test('when help on subcommand and \"before\" subcommand then context.command is subcommand', () => {\n    let context;\n    const program = new commander.Command();\n    program.exitOverride();\n    const sub = program.command('sub').addHelpText('before', (contextParam) => {\n      context = contextParam;\n    });\n    expect(() => {\n      program.parse(['sub', '--help'], { from: 'user' });\n    }).toThrow();\n    expect(context.command).toBe(sub);\n  });\n\n  test('when help on subcommand and \"beforeAll\" on program then context.command is subcommand', () => {\n    let context;\n    const program = new commander.Command();\n    program.exitOverride().addHelpText('beforeAll', (contextParam) => {\n      context = contextParam;\n    });\n    const sub = program.command('sub');\n    expect(() => {\n      program.parse(['sub', '--help'], { from: 'user' });\n    }).toThrow();\n    expect(context.command).toBe(sub);\n  });\n});\n"
  },
  {
    "path": "tests/command.alias.test.js",
    "content": "const commander = require('../');\n\n// Running alias commands is tested in command.executableSubcommand.lookup.test.js\n// Test various other behaviours for .alias\n\ntest('when command has alias then appears in help', () => {\n  const program = new commander.Command();\n  program.command('info [thing]').alias('i');\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch('info|i');\n});\n\ntest('when command has aliases added separately then only first appears in help', () => {\n  const program = new commander.Command();\n  program.command('list [thing]').alias('ls').alias('dir');\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch('list|ls ');\n});\n\ntest('when command has aliases then only first appears in help', () => {\n  const program = new commander.Command();\n  program.command('list [thing]').aliases(['ls', 'dir']);\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch('list|ls ');\n});\n\ntest('when command name = alias then error', () => {\n  const program = new commander.Command();\n  expect(() => {\n    program.command('fail').alias('fail');\n  }).toThrow(\"Command alias can't be the same as its name\");\n});\n\ntest('when use alias then action handler called', () => {\n  const program = new commander.Command();\n  const actionMock = jest.fn();\n  program.command('list').alias('ls').action(actionMock);\n  program.parse(['ls'], { from: 'user' });\n  expect(actionMock).toHaveBeenCalled();\n});\n\ntest('when use second alias added separately then action handler called', () => {\n  const program = new commander.Command();\n  const actionMock = jest.fn();\n  program.command('list').alias('ls').alias('dir').action(actionMock);\n  program.parse(['dir'], { from: 'user' });\n  expect(actionMock).toHaveBeenCalled();\n});\n\ntest('when use second of aliases then action handler called', () => {\n  const program = new commander.Command();\n  const actionMock = jest.fn();\n  program.command('list').aliases(['ls', 'dir']).action(actionMock);\n  program.parse(['dir'], { from: 'user' });\n  expect(actionMock).toHaveBeenCalled();\n});\n\ntest('when set alias then can get alias', () => {\n  const program = new commander.Command();\n  const alias = 'abcde';\n  program.alias(alias);\n  expect(program.alias()).toEqual(alias);\n});\n\ntest('when set aliases then can get aliases', () => {\n  const program = new commander.Command();\n  const aliases = ['a', 'b'];\n  program.aliases(aliases);\n  expect(program.aliases()).toEqual(aliases);\n});\n\ntest('when set alias on executable then can get alias', () => {\n  const program = new commander.Command();\n  const alias = 'abcde';\n  program.command('external', 'external command').alias(alias);\n  expect(program.commands[0].alias()).toEqual(alias);\n});\n\ndescribe('aliases parameter is treated as readonly, per TypeScript declaration', () => {\n  test('when aliases called then parameter does not change', () => {\n    // Unlikely this could break, but check the API we are declaring in TypeScript.\n    const original = ['b', 'bld'];\n    const param = original.slice();\n    new commander.Command('build').aliases(param);\n    expect(param).toEqual(original);\n  });\n\n  test('when aliases called and aliases later changed then parameter does not change', () => {\n    const original = ['b', 'bld'];\n    const param = original.slice();\n    const cmd = new commander.Command('build').aliases(param);\n    cmd.alias('BBB');\n    expect(param).toEqual(original);\n  });\n\n  test('when aliases called and parameter later changed then aliases does not change', () => {\n    const original = ['b', 'bld'];\n    const param = original.slice();\n    const cmd = new commander.Command('build').aliases(param);\n    param.length = 0;\n    expect(cmd.aliases()).toEqual(original);\n  });\n});\n"
  },
  {
    "path": "tests/command.allowExcessArguments.test.js",
    "content": "const commander = require('../');\n\n// Not testing output, just testing whether an error is detected.\n\ndescribe.each([true, false])(\n  'allowExcessArguments when action handler: %s',\n  (hasActionHandler) => {\n    function configureCommand(cmd) {\n      cmd.exitOverride().configureOutput({\n        writeErr: () => {},\n      });\n      if (hasActionHandler) {\n        cmd.action(() => {});\n      }\n    }\n\n    test('when specify excess program argument then error by default', () => {\n      const program = new commander.Command();\n      configureCommand(program);\n\n      expect(() => {\n        program.parse(['excess'], { from: 'user' });\n      }).toThrow();\n    });\n\n    test('when specify excess program argument and allowExcessArguments(false) then error', () => {\n      const program = new commander.Command();\n      configureCommand(program);\n      program.allowExcessArguments(false);\n\n      expect(() => {\n        program.parse(['excess'], { from: 'user' });\n      }).toThrow();\n    });\n\n    test('when specify excess program argument and allowExcessArguments() then no error', () => {\n      const program = new commander.Command();\n      configureCommand(program);\n      program.allowExcessArguments();\n\n      expect(() => {\n        program.parse(['excess'], { from: 'user' });\n      }).not.toThrow();\n    });\n\n    test('when specify excess program argument and allowExcessArguments(true) then no error', () => {\n      const program = new commander.Command();\n      configureCommand(program);\n      program.allowExcessArguments(true);\n\n      expect(() => {\n        program.parse(['excess'], { from: 'user' });\n      }).not.toThrow();\n    });\n\n    test('when specify excess command argument then error (by default)', () => {\n      const program = new commander.Command();\n      const sub = program.command('sub');\n      configureCommand(sub);\n\n      expect(() => {\n        program.parse(['sub', 'excess'], { from: 'user' });\n      }).toThrow();\n    });\n\n    test('when specify excess command argument and allowExcessArguments(false) then error', () => {\n      const program = new commander.Command();\n      const sub = program.command('sub').allowExcessArguments(false);\n      configureCommand(sub);\n\n      expect(() => {\n        program.parse(['sub', 'excess'], { from: 'user' });\n      }).toThrow();\n    });\n\n    test('when specify expected arg and allowExcessArguments(false) then no error', () => {\n      const program = new commander.Command();\n      configureCommand(program);\n      program.argument('<file>').allowExcessArguments(false);\n\n      expect(() => {\n        program.parse(['file'], { from: 'user' });\n      }).not.toThrow();\n    });\n\n    test('when specify excess after <arg> and allowExcessArguments(false) then error', () => {\n      const program = new commander.Command();\n      configureCommand(program);\n      program.argument('<file>').allowExcessArguments(false);\n\n      expect(() => {\n        program.parse(['file', 'excess'], { from: 'user' });\n      }).toThrow();\n    });\n\n    test('when specify excess after [arg] and allowExcessArguments(false) then error', () => {\n      const program = new commander.Command();\n      configureCommand(program);\n      program.argument('[file]').allowExcessArguments(false);\n\n      expect(() => {\n        program.parse(['file', 'excess'], { from: 'user' });\n      }).toThrow();\n    });\n\n    test('when specify args for [args...] and allowExcessArguments(false) then no error', () => {\n      const program = new commander.Command();\n      configureCommand(program);\n      program.argument('[files...]').allowExcessArguments(false);\n\n      expect(() => {\n        program.parse(['file1', 'file2', 'file3'], { from: 'user' });\n      }).not.toThrow();\n    });\n  },\n);\n"
  },
  {
    "path": "tests/command.allowUnknownOption.test.js",
    "content": "const commander = require('../');\n\n// Not testing output, just testing whether an error is detected.\n\ndescribe('allowUnknownOption', () => {\n  // Optional. Use internal knowledge to suppress output to keep test output clean.\n  let writeErrorSpy;\n\n  beforeAll(() => {\n    writeErrorSpy = jest\n      .spyOn(process.stderr, 'write')\n      .mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    writeErrorSpy.mockClear();\n  });\n\n  afterAll(() => {\n    writeErrorSpy.mockRestore();\n  });\n\n  test('when specify unknown program option then error', () => {\n    const program = new commander.Command();\n    program.exitOverride().option('-p, --pepper', 'add pepper');\n\n    expect(() => {\n      program.parse(['node', 'test', '-m']);\n    }).toThrow();\n  });\n\n  test('when specify unknown program option and allowUnknownOption(false) then error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .allowUnknownOption(false)\n      .option('-p, --pepper', 'add pepper');\n\n    expect(() => {\n      program.parse(['node', 'test', '-m']);\n    }).toThrow();\n  });\n\n  test('when specify unknown program option and allowUnknownOption() then no error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .allowUnknownOption()\n      .argument('[args...]') // unknown option will be passed as an argument\n      .option('-p, --pepper', 'add pepper');\n\n    expect(() => {\n      program.parse(['node', 'test', '-m']);\n    }).not.toThrow();\n  });\n\n  test('when specify unknown program option and allowUnknownOption(true) then no error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .allowUnknownOption(true)\n      .argument('[args...]') // unknown option will be passed as an argument\n      .option('-p, --pepper', 'add pepper');\n\n    expect(() => {\n      program.parse(['node', 'test', '-m']);\n    }).not.toThrow();\n  });\n\n  test('when specify unknown command option then error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .command('sub')\n      .option('-p, --pepper', 'add pepper')\n      .action(() => {});\n\n    expect(() => {\n      program.parse(['node', 'test', 'sub', '-m']);\n    }).toThrow();\n  });\n\n  test('when specify unknown command option and allowUnknownOption then no error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .command('sub')\n      .argument('[args...]') // unknown option will be passed as an argument\n      .allowUnknownOption()\n      .option('-p, --pepper', 'add pepper')\n      .action(() => {});\n\n    expect(() => {\n      program.parse(['node', 'test', 'sub', '-m']);\n    }).not.toThrow();\n  });\n});\n"
  },
  {
    "path": "tests/command.argumentVariations.test.js",
    "content": "const commander = require('../');\n\n// Do some low-level checks that the multiple ways of specifying command arguments produce same internal result,\n// and not exhaustively testing all methods elsewhere.\n\ntest.each(getSingleArgCases('<explicit-required>'))(\n  'when add \"<arg>\" using %s then argument required',\n  (methodName, cmd) => {\n    const argument = cmd.registeredArguments[0];\n    const expectedShape = {\n      _name: 'explicit-required',\n      required: true,\n      variadic: false,\n      description: '',\n    };\n    expect(argument).toEqual(expectedShape);\n  },\n);\n\ntest.each(getSingleArgCases('implicit-required'))(\n  'when add \"arg\" using %s then argument required',\n  (methodName, cmd) => {\n    const argument = cmd.registeredArguments[0];\n    const expectedShape = {\n      _name: 'implicit-required',\n      required: true,\n      variadic: false,\n      description: '',\n    };\n    expect(argument).toEqual(expectedShape);\n  },\n);\n\ntest.each(getSingleArgCases('[optional]'))(\n  'when add \"[arg]\" using %s then argument optional',\n  (methodName, cmd) => {\n    const argument = cmd.registeredArguments[0];\n    const expectedShape = {\n      _name: 'optional',\n      required: false,\n      variadic: false,\n      description: '',\n    };\n    expect(argument).toEqual(expectedShape);\n  },\n);\n\ntest.each(getSingleArgCases('<explicit-required...>'))(\n  'when add \"<arg...>\" using %s then argument required and variadic',\n  (methodName, cmd) => {\n    const argument = cmd.registeredArguments[0];\n    const expectedShape = {\n      _name: 'explicit-required',\n      required: true,\n      variadic: true,\n      description: '',\n    };\n    expect(argument).toEqual(expectedShape);\n  },\n);\n\ntest.each(getSingleArgCases('implicit-required...'))(\n  'when add \"arg...\" using %s then argument required and variadic',\n  (methodName, cmd) => {\n    const argument = cmd.registeredArguments[0];\n    const expectedShape = {\n      _name: 'implicit-required',\n      required: true,\n      variadic: true,\n      description: '',\n    };\n    expect(argument).toEqual(expectedShape);\n  },\n);\n\ntest.each(getSingleArgCases('[optional...]'))(\n  'when add \"[arg...]\" using %s then argument optional and variadic',\n  (methodName, cmd) => {\n    const argument = cmd.registeredArguments[0];\n    const expectedShape = {\n      _name: 'optional',\n      required: false,\n      variadic: true,\n      description: '',\n    };\n    expect(argument).toEqual(expectedShape);\n  },\n);\n\nfunction getSingleArgCases(arg) {\n  return [\n    ['.arguments', new commander.Command().arguments(arg)],\n    ['.argument', new commander.Command().argument(arg)],\n    [\n      '.addArgument',\n      new commander.Command('add-argument').addArgument(\n        new commander.Argument(arg),\n      ),\n    ],\n    ['.command', new commander.Command().command(`command ${arg}`)],\n  ];\n}\n\ntest.each(getMultipleArgCases('<first>', '[second]'))(\n  'when add two arguments using %s then two arguments',\n  (methodName, cmd) => {\n    expect(cmd.registeredArguments[0].name()).toEqual('first');\n    expect(cmd.registeredArguments[1].name()).toEqual('second');\n  },\n);\n\nfunction getMultipleArgCases(arg1, arg2) {\n  return [\n    ['.arguments', new commander.Command().arguments(`${arg1} ${arg2}`)],\n    ['.argument', new commander.Command().argument(arg1).argument(arg2)],\n    [\n      '.addArgument',\n      new commander.Command('add-argument')\n        .addArgument(new commander.Argument(arg1))\n        .addArgument(new commander.Argument(arg2)),\n    ],\n    ['.command', new commander.Command().command(`command ${arg1} ${arg2}`)],\n  ];\n}\n\ntest('when add arguments using multiple methods then all added', () => {\n  // This is not a key use case, but explicitly test that additive behaviour.\n  const program = new commander.Command();\n  const cmd = program.command('sub <arg1> <arg2>');\n  cmd.arguments('<arg3> <arg4>');\n  cmd.argument('<arg5>');\n  cmd.addArgument(new commander.Argument('arg6'));\n  const argNames = cmd.registeredArguments.map((arg) => arg.name());\n  expect(argNames).toEqual(['arg1', 'arg2', 'arg3', 'arg4', 'arg5', 'arg6']);\n});\n"
  },
  {
    "path": "tests/command.asterisk.test.js",
    "content": "const commander = require('../');\n\n// .command('*') is the old main/default command handler. It adds a listener\n// for 'command:*'. It has been somewhat replaced by the program action handler,\n// so most uses are probably old code. Current plan is keep the code backwards compatible\n// and put work in elsewhere for new code (e.g. evolving behaviour for program action handler).\n//\n// The event 'command:*' is also listened for directly for testing for unknown commands\n// due to an example in the README.\n//\n// Historical: the event 'command:*' used to also be shared by the action handler on the program.\n\ndescribe(\".command('*')\", () => {\n  test('when no arguments then asterisk action not called', () => {\n    const writeMock = jest\n      .spyOn(process.stderr, 'write')\n      .mockImplementation(() => {});\n    const mockAction = jest.fn();\n    const program = new commander.Command();\n    program\n      .exitOverride() // to catch help\n      .command('*')\n      .action(mockAction);\n    try {\n      program.parse(['node', 'test']);\n    } catch (err) {\n      /* empty */\n    }\n    expect(mockAction).not.toHaveBeenCalled();\n    writeMock.mockRestore();\n  });\n\n  test('when unrecognised argument then asterisk action called', () => {\n    const mockAction = jest.fn();\n    const program = new commander.Command();\n    program.command('*').argument('[args...]').action(mockAction);\n    program.parse(['node', 'test', 'unrecognised-command']);\n    expect(mockAction).toHaveBeenCalled();\n  });\n\n  test('when recognised command then asterisk action not called', () => {\n    const mockAction = jest.fn();\n    const program = new commander.Command();\n    program.command('install').action(() => {});\n    program.command('*').action(mockAction);\n    program.parse(['node', 'test', 'install']);\n    expect(mockAction).not.toHaveBeenCalled();\n  });\n\n  test('when unrecognised command/argument then asterisk action called', () => {\n    const mockAction = jest.fn();\n    const program = new commander.Command();\n    program.command('install');\n    program.command('*').argument('[args...]').action(mockAction);\n    program.parse(['node', 'test', 'unrecognised-command']);\n    expect(mockAction).toHaveBeenCalled();\n  });\n\n  test('when unrecognised argument and known option then asterisk action called', () => {\n    // This tests for a regression between v4 and v5. Known default option should not be rejected by program.\n    const mockAction = jest.fn();\n    const program = new commander.Command();\n    program.command('install');\n    const star = program\n      .command('*')\n      .argument('[args...]')\n      .option('-d, --debug')\n      .action(mockAction);\n    program.parse(['node', 'test', 'unrecognised-command', '--debug']);\n    expect(mockAction).toHaveBeenCalled();\n    expect(star.opts().debug).toEqual(true);\n  });\n\n  test('when non-command argument and unknown option then error for unknown option', () => {\n    // This is a change in behaviour from v2 which did not error, but is consistent with modern better detection of invalid options\n    const mockAction = jest.fn();\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .configureOutput({\n        writeErr: () => {},\n      })\n      .command('install');\n    program.command('*').argument('[args...]').action(mockAction);\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', 'some-argument', '--unknown']);\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toEqual('commander.unknownOption');\n  });\n});\n\n// Test .on explicitly rather than assuming covered by .command\ndescribe(\".on('command:*')\", () => {\n  test('when no arguments then listener not called', () => {\n    const mockAction = jest.fn();\n    const program = new commander.Command();\n    program.on('command:*', mockAction);\n    program.parse(['node', 'test']);\n    expect(mockAction).not.toHaveBeenCalled();\n  });\n\n  test('when unrecognised argument then listener called', () => {\n    const mockAction = jest.fn();\n    const program = new commander.Command();\n    program.on('command:*', mockAction);\n    program.parse(['node', 'test', 'unrecognised-command']);\n    expect(mockAction).toHaveBeenCalled();\n  });\n\n  test('when recognised command then listener not called', () => {\n    const mockAction = jest.fn();\n    const program = new commander.Command();\n    program.command('install').action(() => {});\n    program.on('command:*', mockAction);\n    program.parse(['node', 'test', 'install']);\n    expect(mockAction).not.toHaveBeenCalled();\n  });\n\n  test('when unrecognised command/argument then listener called', () => {\n    const mockAction = jest.fn();\n    const program = new commander.Command();\n    program.command('install');\n    program.on('command:*', mockAction);\n    program.parse(['node', 'test', 'unrecognised-command']);\n    expect(mockAction).toHaveBeenCalled();\n  });\n\n  test('when unrecognised command/argument and unknown option then listener called', () => {\n    // Give listener a chance to make a suggestion for misspelled command. The option\n    // could only be unknown because the command is not correct.\n    // Regression identified in https://github.com/tj/commander.js/issues/1460#issuecomment-772313494\n    const mockAction = jest.fn();\n    const program = new commander.Command();\n    program.command('install');\n    program.on('command:*', mockAction);\n    program.parse(['node', 'test', 'intsall', '--unknown']);\n    expect(mockAction).toHaveBeenCalled();\n  });\n});\n"
  },
  {
    "path": "tests/command.chain.test.js",
    "content": "const { Command, Option, Argument } = require('../');\n\n// Testing the functions which should chain.\n// parse and parseAsync are tested in command.parse.test.js\n\ndescribe('Command methods that should return this for chaining', () => {\n  test('when call .command() with description for stand-alone executable then returns this', () => {\n    const program = new Command();\n    const result = program.command('foo', 'foo description');\n    expect(result).toBe(program);\n  });\n\n  test('when call .addCommand() then returns this', () => {\n    const program = new Command();\n    const result = program.addCommand(new Command('name'));\n    expect(result).toBe(program);\n  });\n\n  test('when call .argument() then returns this', () => {\n    const program = new Command();\n    const result = program.argument('<file>');\n    expect(result).toBe(program);\n  });\n\n  test('when call .addArgument() then returns this', () => {\n    const program = new Command();\n    const result = program.addArgument(new Argument('<file>'));\n    expect(result).toBe(program);\n  });\n\n  test('when set .arguments() then returns this', () => {\n    const program = new Command();\n    const result = program.arguments('<file>');\n    expect(result).toBe(program);\n  });\n\n  test('when call .addHelpCommand(cmd) then returns this', () => {\n    const program = new Command();\n    const result = program.addHelpCommand(new Command('assist'));\n    expect(result).toBe(program);\n  });\n\n  test('when call deprecated .addHelpCommand() then returns this', () => {\n    const program = new Command();\n    const result = program.addHelpCommand();\n    expect(result).toBe(program);\n  });\n\n  test('when call deprecated .addHelpCommand(boolean) then returns this', () => {\n    const program = new Command();\n    const result1 = program.addHelpCommand(true);\n    expect(result1).toBe(program);\n    const result2 = program.addHelpCommand(false);\n    expect(result2).toBe(program);\n  });\n\n  test('when call deprecated .addHelpCommand(string[, string]) then returns this', () => {\n    const program = new Command();\n    const result1 = program.addHelpCommand('assist');\n    expect(result1).toBe(program);\n    const result2 = program.addHelpCommand('assist', 'assist description');\n    expect(result2).toBe(program);\n  });\n\n  test('when call .helpCommand(name) then returns this', () => {\n    const program = new Command();\n    const result = program.helpCommand();\n    expect(result).toBe(program);\n  });\n\n  test('when call .helpCommand(name, description) then returns this', () => {\n    const program = new Command();\n    const result1 = program.helpCommand('assist', 'assist description');\n    expect(result1).toBe(program);\n  });\n\n  test('when call .helpCommand(boolean) then returns this', () => {\n    const program = new Command();\n    const result1 = program.helpCommand(true);\n    expect(result1).toBe(program);\n    const result2 = program.helpCommand(false);\n    expect(result2).toBe(program);\n  });\n\n  test('when call .exitOverride() then returns this', () => {\n    const program = new Command();\n    const result = program.exitOverride(() => {});\n    expect(result).toBe(program);\n  });\n\n  test('when call .action() then returns this', () => {\n    const program = new Command();\n    const result = program.action(() => {});\n    expect(result).toBe(program);\n  });\n\n  test('when call .addOption() then returns this', () => {\n    const program = new Command();\n    const result = program.addOption(new Option('-e'));\n    expect(result).toBe(program);\n  });\n\n  test('when call .option() then returns this', () => {\n    const program = new Command();\n    const result = program.option('-e');\n    expect(result).toBe(program);\n  });\n\n  test('when call .requiredOption() then returns this', () => {\n    const program = new Command();\n    const result = program.requiredOption('-r');\n    expect(result).toBe(program);\n  });\n\n  test('when call .combineFlagAndOptionalValue() then returns this', () => {\n    const program = new Command();\n    const result = program.combineFlagAndOptionalValue();\n    expect(result).toBe(program);\n  });\n\n  test('when call .allowUnknownOption() then returns this', () => {\n    const program = new Command();\n    const result = program.allowUnknownOption();\n    expect(result).toBe(program);\n  });\n\n  test('when call .allowExcessArguments() then returns this', () => {\n    const program = new Command();\n    const result = program.allowExcessArguments();\n    expect(result).toBe(program);\n  });\n\n  test('when call .storeOptionsAsProperties() then returns this', () => {\n    const program = new Command();\n    const result = program.storeOptionsAsProperties();\n    expect(result).toBe(program);\n  });\n\n  test('when call .version() then returns this', () => {\n    const program = new Command();\n    const result = program.version('1.2.3');\n    expect(result).toBe(program);\n  });\n\n  test('when set .description() then returns this', () => {\n    const program = new Command();\n    const result = program.description('description');\n    expect(result).toBe(program);\n  });\n\n  test('when set .alias() then returns this', () => {\n    const program = new Command();\n    const result = program.alias('alias');\n    expect(result).toBe(program);\n  });\n\n  test('when set .aliases() then returns this', () => {\n    const program = new Command();\n    const result = program.aliases(['foo', 'bar']);\n    expect(result).toBe(program);\n  });\n\n  test('when set .usage() then returns this', () => {\n    const program = new Command();\n    const result = program.usage('[options]');\n    expect(result).toBe(program);\n  });\n\n  test('when set .name() then returns this', () => {\n    const program = new Command();\n    const result = program.name('easy');\n    expect(result).toBe(program);\n  });\n\n  test('when call .helpOption(flags) then returns this', () => {\n    const program = new Command();\n    const flags = '-h, --help';\n    const result = program.helpOption(flags);\n    expect(result).toBe(program);\n  });\n\n  test('when call .addHelpOption() then returns this', () => {\n    const program = new Command();\n    const result = program.addHelpOption(new Option('-h, --help'));\n    expect(result).toBe(program);\n  });\n\n  test('when call .addHelpText() then returns this', () => {\n    const program = new Command();\n    const result = program.addHelpText('before', 'example');\n    expect(result).toBe(program);\n  });\n\n  test('when call .configureHelp() then returns this', () => {\n    const program = new Command();\n    const result = program.configureHelp({});\n    expect(result).toBe(program);\n  });\n\n  test('when call .configureOutput() then returns this', () => {\n    const program = new Command();\n    const result = program.configureOutput({});\n    expect(result).toBe(program);\n  });\n\n  test('when call .passThroughOptions() then returns this', () => {\n    const program = new Command();\n    const result = program.passThroughOptions();\n    expect(result).toBe(program);\n  });\n\n  test('when call .enablePositionalOptions() then returns this', () => {\n    const program = new Command();\n    const result = program.enablePositionalOptions();\n    expect(result).toBe(program);\n  });\n\n  test('when call .hook() then returns this', () => {\n    const program = new Command();\n    const result = program.hook('preAction', () => {});\n    expect(result).toBe(program);\n  });\n\n  test('when call .setOptionValue() then returns this', () => {\n    const program = new Command();\n    const result = program.setOptionValue('foo', 'bar');\n    expect(result).toBe(program);\n  });\n\n  test('when call .setOptionValueWithSource() then returns this', () => {\n    const program = new Command();\n    const result = program.setOptionValueWithSource('foo', 'bar', 'cli');\n    expect(result).toBe(program);\n  });\n\n  test('when call .showHelpAfterError() then returns this', () => {\n    const program = new Command();\n    const result = program.showHelpAfterError();\n    expect(result).toBe(program);\n  });\n\n  test('when call .showSuggestionAfterError() then returns this', () => {\n    const program = new Command();\n    const result = program.showSuggestionAfterError();\n    expect(result).toBe(program);\n  });\n\n  test('when call .copyInheritedSettings() then returns this', () => {\n    const program = new Command();\n    const cmd = new Command();\n    const result = cmd.copyInheritedSettings(program);\n    expect(result).toBe(cmd);\n  });\n\n  test('when set .nameFromFilename() then returns this', () => {\n    const program = new Command();\n    const result = program.nameFromFilename('name');\n    expect(result).toBe(program);\n  });\n\n  test('when set .helpGroup(heading) then returns this', () => {\n    const program = new Command();\n    const result = program.helpGroup('Commands:');\n    expect(result).toBe(program);\n  });\n\n  test('when set .commandsGroup(heading) then returns this', () => {\n    const program = new Command();\n    const result = program.commandsGroup('Commands:');\n    expect(result).toBe(program);\n  });\n\n  test('when set .optionsGroup(heading) then returns this', () => {\n    const program = new Command();\n    const result = program.optionsGroup('Options:');\n    expect(result).toBe(program);\n  });\n});\n"
  },
  {
    "path": "tests/command.commandHelp.test.js",
    "content": "const commander = require('../');\n\n// This is a ported legacy test.\n\ntest('when program has command then appears in help', () => {\n  const program = new commander.Command();\n  program.command('bare');\n  const commandHelp = program.helpInformation();\n  expect(commandHelp).toMatch(/Commands:\\n +bare\\n/);\n});\n\ntest('when program has command with optional arg then appears in help', () => {\n  const program = new commander.Command();\n  program.command('bare [bare-arg]');\n  const commandHelp = program.helpInformation();\n  expect(commandHelp).toMatch(/Commands:\\n +bare \\[bare-arg\\]\\n/);\n});\n"
  },
  {
    "path": "tests/command.configureHelp.test.js",
    "content": "const commander = require('../');\n\ntest('when configure program then affects program helpInformation', () => {\n  const program = new commander.Command();\n  program.configureHelp({\n    formatHelp: () => {\n      return 'custom';\n    },\n  });\n  expect(program.helpInformation()).toEqual('custom');\n});\n\ntest('when configure program then affects subcommand helpInformation', () => {\n  const program = new commander.Command();\n  program.configureHelp({\n    formatHelp: () => {\n      return 'custom';\n    },\n  });\n  const sub = program.command('sub');\n  expect(sub.helpInformation()).toEqual('custom');\n});\n\ntest('when configure with unknown property then createHelp has unknown property', () => {\n  const program = new commander.Command();\n  program.configureHelp({ mySecretValue: 'secret' });\n  expect(program.createHelp().mySecretValue).toEqual('secret');\n});\n\ntest('when configure with unknown property then helper passed to formatHelp has unknown property', () => {\n  const program = new commander.Command();\n  program.configureHelp({\n    mySecretValue: 'secret',\n    formatHelp: (cmd, helper) => {\n      return helper.mySecretValue;\n    },\n  });\n  expect(program.helpInformation()).toEqual('secret');\n});\n"
  },
  {
    "path": "tests/command.configureOutput.test.js",
    "content": "const commander = require('../');\nconst process = require('node:process');\n\ntest('when default writeErr() then error on stderr', () => {\n  const writeSpy = jest\n    .spyOn(process.stderr, 'write')\n    .mockImplementation(() => {});\n  const program = new commander.Command();\n  program.exitOverride();\n\n  try {\n    program.parse(['--unknown'], { from: 'user' });\n  } catch (err) {\n    /* empty */\n  }\n\n  expect(writeSpy).toHaveBeenCalledTimes(1);\n  writeSpy.mockRestore();\n});\n\ntest('when custom writeErr() then error on custom output', () => {\n  const writeSpy = jest\n    .spyOn(process.stderr, 'write')\n    .mockImplementation(() => {});\n  const customWrite = jest.fn();\n  const program = new commander.Command();\n  program.exitOverride().configureOutput({ writeErr: customWrite });\n\n  try {\n    program.parse(['--unknown'], { from: 'user' });\n  } catch (err) {\n    /* empty */\n  }\n\n  expect(writeSpy).toHaveBeenCalledTimes(0);\n  expect(customWrite).toHaveBeenCalledTimes(1);\n  writeSpy.mockRestore();\n});\n\ntest('when default write() then version on stdout', () => {\n  const writeSpy = jest\n    .spyOn(process.stdout, 'write')\n    .mockImplementation(() => {});\n  const program = new commander.Command();\n  program.exitOverride().version('1.2.3');\n\n  expect(() => {\n    program.parse(['--version'], { from: 'user' });\n  }).toThrow();\n\n  expect(writeSpy).toHaveBeenCalledTimes(1);\n  writeSpy.mockRestore();\n});\n\ntest('when custom write() then version on custom output', () => {\n  const writeSpy = jest\n    .spyOn(process.stdout, 'write')\n    .mockImplementation(() => {});\n  const customWrite = jest.fn();\n  const program = new commander.Command();\n  program\n    .exitOverride()\n    .version('1.2.3')\n    .configureOutput({ writeOut: customWrite });\n\n  expect(() => {\n    program.parse(['--version'], { from: 'user' });\n  }).toThrow();\n\n  expect(writeSpy).toHaveBeenCalledTimes(0);\n  expect(customWrite).toHaveBeenCalledTimes(1);\n  writeSpy.mockRestore();\n});\n\ntest('when default write() then help on stdout', () => {\n  const writeSpy = jest\n    .spyOn(process.stdout, 'write')\n    .mockImplementation(() => {});\n  const program = new commander.Command();\n  program.outputHelp();\n\n  expect(writeSpy).toHaveBeenCalledTimes(1);\n  writeSpy.mockRestore();\n});\n\ntest('when custom write() then help error on custom output', () => {\n  const writeSpy = jest\n    .spyOn(process.stdout, 'write')\n    .mockImplementation(() => {});\n  const customWrite = jest.fn();\n  const program = new commander.Command();\n  program.configureOutput({ writeOut: customWrite });\n  program.outputHelp();\n\n  expect(writeSpy).toHaveBeenCalledTimes(0);\n  expect(customWrite).toHaveBeenCalledTimes(1);\n  writeSpy.mockRestore();\n});\n\ntest('when default writeErr then help error on stderr', () => {\n  const writeSpy = jest\n    .spyOn(process.stderr, 'write')\n    .mockImplementation(() => {});\n  const program = new commander.Command();\n  program.outputHelp({ error: true });\n\n  expect(writeSpy).toHaveBeenCalledTimes(1);\n  writeSpy.mockRestore();\n});\n\ntest('when custom writeErr then help error on custom output', () => {\n  const writeSpy = jest\n    .spyOn(process.stderr, 'write')\n    .mockImplementation(() => {});\n  const customWrite = jest.fn();\n  const program = new commander.Command();\n  program.configureOutput({ writeErr: customWrite });\n  program.outputHelp({ error: true });\n\n  expect(writeSpy).toHaveBeenCalledTimes(0);\n  expect(customWrite).toHaveBeenCalledTimes(1);\n  writeSpy.mockRestore();\n});\n\ntest('when default getOutHelpWidth then help helpWidth from stdout', () => {\n  const expectedColumns = 123;\n  const holdIsTTY = process.stdout.isTTY;\n  const holdColumns = process.stdout.columns;\n  let helpWidth;\n\n  process.stderr.isTTY = true;\n  process.stdout.columns = expectedColumns;\n  process.stdout.isTTY = true;\n  const program = new commander.Command();\n  program.configureHelp({\n    formatHelp: (cmd, helper) => {\n      helpWidth = helper.helpWidth;\n      return '';\n    },\n  });\n  program.outputHelp();\n\n  expect(helpWidth).toBe(expectedColumns);\n  process.stdout.columns = holdColumns;\n  process.stdout.isTTY = holdIsTTY;\n});\n\ntest('when custom getOutHelpWidth then help helpWidth custom', () => {\n  const expectedColumns = 123;\n  let helpWidth;\n\n  const program = new commander.Command();\n  program\n    .configureHelp({\n      formatHelp: (cmd, helper) => {\n        helpWidth = helper.helpWidth;\n        return '';\n      },\n    })\n    .configureOutput({\n      getOutHelpWidth: () => expectedColumns,\n    });\n  program.outputHelp();\n\n  expect(helpWidth).toBe(expectedColumns);\n});\n\ntest('when default getErrHelpWidth then help error helpWidth from stderr', () => {\n  const expectedColumns = 123;\n  const holdIsTTY = process.stderr.isTTY;\n  const holdColumns = process.stderr.columns;\n  let helpWidth;\n\n  process.stderr.isTTY = true;\n  process.stderr.columns = expectedColumns;\n  const program = new commander.Command();\n  program.configureHelp({\n    formatHelp: (cmd, helper) => {\n      helpWidth = helper.helpWidth;\n      return '';\n    },\n  });\n  program.outputHelp({ error: true });\n\n  expect(helpWidth).toBe(expectedColumns);\n  process.stderr.isTTY = holdIsTTY;\n  process.stderr.columns = holdColumns;\n});\n\ntest('when custom getErrHelpWidth then help error helpWidth custom', () => {\n  const expectedColumns = 123;\n  let helpWidth;\n\n  const program = new commander.Command();\n  program\n    .configureHelp({\n      formatHelp: (cmd, helper) => {\n        helpWidth = helper.helpWidth;\n        return '';\n      },\n    })\n    .configureOutput({\n      getErrHelpWidth: () => expectedColumns,\n    });\n  program.outputHelp({ error: true });\n\n  expect(helpWidth).toBe(expectedColumns);\n});\n\ntest('when custom getOutHelpWidth and configureHelp:helpWidth then help helpWidth from configureHelp', () => {\n  const expectedColumns = 123;\n  let helpWidth;\n\n  const program = new commander.Command();\n  program\n    .configureHelp({\n      formatHelp: (cmd, helper) => {\n        helpWidth = helper.helpWidth;\n        return '';\n      },\n      helpWidth: expectedColumns,\n    })\n    .configureOutput({\n      getOutHelpWidth: () => 999,\n    });\n  program.outputHelp();\n\n  expect(helpWidth).toBe(expectedColumns);\n});\n\ntest('when custom getErrHelpWidth and configureHelp:helpWidth then help error helpWidth from configureHelp', () => {\n  const expectedColumns = 123;\n  let helpWidth;\n\n  const program = new commander.Command();\n  program\n    .configureHelp({\n      formatHelp: (cmd, helper) => {\n        helpWidth = helper.helpWidth;\n        return '';\n      },\n      helpWidth: expectedColumns,\n    })\n    .configureOutput({\n      getErrHelpWidth: () => 999,\n    });\n  program.outputHelp({ error: true });\n\n  expect(helpWidth).toBe(expectedColumns);\n});\n\ntest('when no custom setup and call formatHelp direct then effective helpWidth is fallback 80', () => {\n  // Not an important case, but filling out testing coverage.\n  const helper = new commander.Help();\n  let wrapWidth;\n  helper.boxWrap = (str, width) => {\n    wrapWidth = wrapWidth ?? width;\n    return '';\n  };\n  const program = new commander.Command()\n    .description('description')\n    .helpOption(false);\n  helper.formatHelp(program, helper);\n  expect(wrapWidth).toBe(80);\n});\n\ntest('when no custom setup and call formatItem direct then effective helpWidth is fallback 80', () => {\n  // Not an important case, but filling out testing coverage.\n  const helper = new commander.Help();\n  let wrapWidth;\n  helper.boxWrap = (str, width) => {\n    wrapWidth = wrapWidth ?? width;\n    return '';\n  };\n\n  const termWidth = 8;\n  helper.formatItem('term', termWidth, 'description', helper);\n  const itemIndent = 2;\n  const spacerWidth = 2; // between term and description\n  const remainingWidth = 80 - termWidth - spacerWidth - itemIndent;\n\n  expect(wrapWidth).toBe(remainingWidth);\n});\n\ntest('when set configureOutput then get configureOutput', () => {\n  const outputOptions = {\n    writeOut: jest.fn(),\n    writeErr: jest.fn(),\n    getOutHelpWidth: jest.fn(),\n    getErrHelpWidth: jest.fn(),\n    getOutHasColors: jest.fn(),\n    getErrHasColors: jest.fn(),\n    outputError: jest.fn(),\n    stripColor: jest.fn(),\n  };\n  const program = new commander.Command();\n  program.configureOutput(outputOptions);\n  expect(program.configureOutput()).toEqual(outputOptions);\n});\n\ntest('when custom outputErr and error then outputErr called', () => {\n  const outputError = jest.fn();\n  const program = new commander.Command();\n  program.exitOverride().configureOutput({\n    outputError,\n  });\n\n  expect(() => {\n    program.parse(['--unknownOption'], { from: 'user' });\n  }).toThrow();\n  expect(outputError).toHaveBeenCalledWith(\n    \"error: unknown option '--unknownOption'\\n\",\n    program._outputConfiguration.writeErr,\n  );\n});\n\ntest('when custom outputErr and writeErr and error then outputErr passed writeErr', () => {\n  const writeErr = () => jest.fn();\n  const outputError = jest.fn();\n  const program = new commander.Command();\n  program.exitOverride().configureOutput({ writeErr, outputError });\n\n  expect(() => {\n    program.parse(['--unknownOption'], { from: 'user' });\n  }).toThrow();\n  expect(outputError).toHaveBeenCalledWith(\n    \"error: unknown option '--unknownOption'\\n\",\n    writeErr,\n  );\n});\n\ntest('when configureOutput after copyInheritedSettings then original unchanged', () => {\n  const program = new commander.Command();\n  program.configureOutput({ getOutHelpWidth: () => 80 });\n  const copy = program.createCommand('copy');\n  copy.copyInheritedSettings(program);\n  expect(copy.configureOutput().getOutHelpWidth()).toBe(80);\n  copy.configureOutput({ getOutHelpWidth: () => 40 });\n  expect(copy.configureOutput().getOutHelpWidth()).toBe(40);\n  expect(program.configureOutput().getOutHelpWidth()).toBe(80);\n});\n\ndescribe.each([['getOutHasColors'], ['getErrHasColors']])(\n  '%s',\n  (configProperty) => {\n    // Tried and failed to mock/modify process.stdout.isTTY to test that part of implementation.\n    // Just test overrides work as expected!\n\n    const getHasColors = new commander.Command().configureOutput()[\n      configProperty\n    ];\n\n    test.each([\n      [true, 'NO_COLOR', false],\n      [false, 'FORCE_COLOR', true],\n      [false, 'CLICOLOR_FORCE', true],\n    ])('when isTTY=%o but %s then returns %o', (isTTY, envvar, result) => {\n      const holdEnv = process.env[envvar];\n      process.env[envvar] = '1';\n      expect(getHasColors()).toBe(result);\n      if (holdEnv === undefined) delete process.env[envvar];\n      else process.env[envvar] = holdEnv;\n    });\n  },\n);\n"
  },
  {
    "path": "tests/command.copySettings.test.js",
    "content": "const commander = require('../');\n\n// Tests some private properties as simpler than pure tests of observable behaviours.\n// Testing before and after values in some cases, to ensure value actually changes (when copied).\n\ntest('when add subcommand with .command() then calls copyInheritedSettings from parent', () => {\n  const program = new commander.Command();\n\n  // This is a bit intrusive, but check expectation that copyInheritedSettings is called internally.\n  const copySettingMock = jest.fn();\n  program.createCommand = (name) => {\n    const cmd = new commander.Command(name);\n    cmd.copyInheritedSettings = copySettingMock;\n    return cmd;\n  };\n  program.command('sub');\n\n  expect(copySettingMock).toHaveBeenCalledWith(program);\n});\n\ndescribe('copyInheritedSettings property tests', () => {\n  test('when copyInheritedSettings then copies outputConfiguration(config)', () => {\n    const source = new commander.Command();\n    const cmd = new commander.Command();\n\n    source.configureOutput({ foo: 'bar' });\n    cmd.copyInheritedSettings(source);\n    expect(cmd.configureOutput().foo).toEqual('bar');\n  });\n\n  test('when copyInheritedSettings then copies helpOption(false)', () => {\n    const source = new commander.Command();\n    const cmd = new commander.Command();\n\n    source.helpOption(false);\n    cmd.copyInheritedSettings(source);\n    expect(cmd._getHelpOption()).toBe(null);\n  });\n\n  test('when copyInheritedSettings then copies helpOption(flags, description)', () => {\n    const source = new commander.Command();\n    const cmd = new commander.Command();\n\n    source.helpOption('-Z, --zz', 'ddd');\n    cmd.copyInheritedSettings(source);\n    expect(cmd._getHelpOption()).toBe(source._getHelpOption());\n    // const helpOption = cmd._getHelpOption();\n    // expect(helpOption.flags).toBe('-Z, --zz');\n    // expect(helpOption.description).toBe('ddd');\n    // expect(helpOption.short).toBe('-Z');\n    // expect(helpOption.long).toBe('--zz');\n  });\n\n  test('when copyInheritedSettings then copies custom help command', () => {\n    const source = new commander.Command();\n    const cmd = new commander.Command();\n\n    source.helpCommand('HELP [cmd]', 'ddd');\n    cmd.copyInheritedSettings(source);\n    cmd.helpCommand(true); // force enable\n    const helpCommand = cmd._getHelpCommand();\n    expect(helpCommand).toBeTruthy();\n    expect(helpCommand.name()).toBe('HELP');\n    expect(helpCommand.description()).toBe('ddd');\n  });\n\n  test('when copyInheritedSettings then does not copy help enable override', () => {\n    const source = new commander.Command();\n    const cmd = new commander.Command();\n\n    // Existing behaviour, force enable/disable does not inherit,\n    // largely so (probably redundant) program.helpCommand(true) does not inherit to leaf subcommands.\n    source.helpCommand(true);\n    cmd.copyInheritedSettings(source);\n    expect(cmd._addHelpOption).toBeUndefined();\n  });\n\n  test('when copyInheritedSettings then copies configureHelp(config)', () => {\n    const source = new commander.Command();\n    const cmd = new commander.Command();\n\n    const configuration = { foo: 'bar', helpWidth: 123, sortSubcommands: true };\n    source.configureHelp(configuration);\n    cmd.copyInheritedSettings(source);\n    expect(cmd.configureHelp()).toEqual(configuration);\n  });\n\n  test('when copyInheritedSettings then copies exitOverride()', () => {\n    const source = new commander.Command();\n    const cmd = new commander.Command();\n\n    expect(cmd._exitCallback).toBeFalsy();\n    source.exitOverride();\n    cmd.copyInheritedSettings(source);\n    expect(cmd._exitCallback).toBeTruthy(); // actually a function\n  });\n\n  test('when copyInheritedSettings then copies storeOptionsAsProperties()', () => {\n    const source = new commander.Command();\n    const cmd = new commander.Command();\n\n    expect(cmd._storeOptionsAsProperties).toBeFalsy();\n    source.storeOptionsAsProperties();\n    cmd.copyInheritedSettings(source);\n    expect(cmd._storeOptionsAsProperties).toBeTruthy();\n  });\n\n  test('when copyInheritedSettings then copies combineFlagAndOptionalValue()', () => {\n    const source = new commander.Command();\n    const cmd = new commander.Command();\n\n    expect(cmd._combineFlagAndOptionalValue).toBeTruthy();\n    source.combineFlagAndOptionalValue(false);\n    cmd.copyInheritedSettings(source);\n    expect(cmd._combineFlagAndOptionalValue).toBeFalsy();\n  });\n\n  test('when copyInheritedSettings then copies allowExcessArguments()', () => {\n    const source = new commander.Command();\n    const cmd = new commander.Command();\n\n    expect(cmd._allowExcessArguments).toBeFalsy();\n    source.allowExcessArguments();\n    cmd.copyInheritedSettings(source);\n    expect(cmd._allowExcessArguments).toBeTruthy();\n  });\n\n  test('when copyInheritedSettings then copies enablePositionalOptions()', () => {\n    const source = new commander.Command();\n    const cmd = new commander.Command();\n\n    expect(cmd._enablePositionalOptions).toBeFalsy();\n    source.enablePositionalOptions();\n    cmd.copyInheritedSettings(source);\n    expect(cmd._enablePositionalOptions).toBeTruthy();\n  });\n\n  test('when copyInheritedSettings then copies showHelpAfterError()', () => {\n    const source = new commander.Command();\n    const cmd = new commander.Command();\n\n    expect(cmd._showHelpAfterError).toBeFalsy();\n    source.showHelpAfterError();\n    cmd.copyInheritedSettings(source);\n    expect(cmd._showHelpAfterError).toBeTruthy();\n  });\n});\n"
  },
  {
    "path": "tests/command.createArgument.test.js",
    "content": "const commander = require('../');\n\nclass MyArgument extends commander.Argument {\n  constructor(name, description) {\n    super(name, description);\n    this.myProperty = 'MyArgument';\n  }\n}\n\nclass MyCommand extends commander.Command {\n  createArgument(name, description) {\n    return new MyArgument(name, description);\n  }\n\n  // createCommand for testing .command('sub <file>')\n  createCommand(name) {\n    return new MyCommand(name);\n  }\n}\n\ntest('when override createArgument then used for argument()', () => {\n  const program = new MyCommand();\n  program.argument('<file>');\n  expect(program.registeredArguments.length).toEqual(1);\n  expect(program.registeredArguments[0].myProperty).toEqual('MyArgument');\n});\n\ntest('when override createArgument then used for arguments()', () => {\n  const program = new MyCommand();\n  program.arguments('<file>');\n  expect(program.registeredArguments.length).toEqual(1);\n  expect(program.registeredArguments[0].myProperty).toEqual('MyArgument');\n});\n\ntest('when override createArgument and createCommand then used for argument of command()', () => {\n  const program = new MyCommand();\n  const sub = program.command('sub <file>');\n  expect(sub.registeredArguments.length).toEqual(1);\n  expect(sub.registeredArguments[0].myProperty).toEqual('MyArgument');\n});\n"
  },
  {
    "path": "tests/command.createHelp.test.js",
    "content": "const commander = require('../');\n\ntest('when override createCommand then affects help', () => {\n  class MyHelp extends commander.Help {\n    formatHelp(cmd, helper) {\n      return 'custom';\n    }\n  }\n\n  class MyCommand extends commander.Command {\n    createHelp() {\n      return Object.assign(new MyHelp(), this.configureHelp());\n    }\n  }\n\n  const program = new MyCommand();\n  expect(program.helpInformation()).toEqual('custom');\n});\n"
  },
  {
    "path": "tests/command.createOption.test.js",
    "content": "const commander = require('../');\n\nclass MyOption extends commander.Option {\n  constructor(flags, description) {\n    super(flags, description);\n    this.myProperty = 'MyOption';\n  }\n}\n\nclass MyCommand extends commander.Command {\n  createOption(flags, description) {\n    return new MyOption(flags, description);\n  }\n}\n\ntest('when override createOption then used for option()', () => {\n  const program = new MyCommand();\n  program.option('-a, --alpha');\n  expect(program.options.length).toEqual(1);\n  expect(program.options[0].myProperty).toEqual('MyOption');\n});\n\ntest('when override createOption then used for requiredOption()', () => {\n  const program = new MyCommand();\n  program.requiredOption('-a, --alpha');\n  expect(program.options.length).toEqual(1);\n  expect(program.options[0].myProperty).toEqual('MyOption');\n});\n\ntest('when override createOption then used for version()', () => {\n  const program = new MyCommand();\n  program.version('1.2.3');\n  expect(program.options.length).toEqual(1);\n  expect(program.options[0].myProperty).toEqual('MyOption');\n});\n\ntest('when override createOption then used for help option in visibleOptions', () => {\n  const program = new MyCommand();\n  const visibleOptions = program.createHelp().visibleOptions(program);\n  expect(visibleOptions.length).toEqual(1);\n  expect(visibleOptions[0].myProperty).toEqual('MyOption');\n});\n"
  },
  {
    "path": "tests/command.default.test.js",
    "content": "const childProcess = require('child_process');\nconst commander = require('../');\nconst path = require('path');\nconst util = require('util');\n\nconst execFileAsync = util.promisify(childProcess.execFile);\n\ndescribe('default executable command', () => {\n  // Calling node explicitly so pm works without file suffix cross-platform.\n  const pm = path.join(__dirname, './fixtures/pm');\n\n  test('when default subcommand and no command then call default', async () => {\n    const { stdout } = await execFileAsync('node', [pm]);\n    expect(stdout).toBe('default\\n');\n  });\n\n  test('when default subcommand and unrecognised argument then call default with argument', async () => {\n    const { stdout } = await execFileAsync('node', [pm, 'an-argument']);\n    expect(stdout).toBe(\"default\\n[ 'an-argument' ]\\n\");\n  });\n\n  test('when default subcommand and unrecognised option then call default with option', async () => {\n    const { stdout } = await execFileAsync('node', [pm, '--an-option']);\n    expect(stdout).toBe(\"default\\n[ '--an-option' ]\\n\");\n  });\n});\n\ndescribe('default action command', () => {\n  function makeProgram() {\n    const program = new commander.Command();\n    const actionMock = jest.fn();\n    program.command('other');\n    program\n      .command('default', { isDefault: true })\n      .allowUnknownOption()\n      .allowExcessArguments()\n      .action(actionMock);\n    return { program, actionMock };\n  }\n\n  test('when default subcommand and no command then call default', () => {\n    const { program, actionMock } = makeProgram();\n    program.parse('node test.js'.split(' '));\n    expect(actionMock).toHaveBeenCalled();\n  });\n\n  test('when default subcommand and unrecognised argument then call default', () => {\n    const { program, actionMock } = makeProgram();\n    program.parse('node test.js an-argument'.split(' '));\n    expect(actionMock).toHaveBeenCalled();\n  });\n\n  test('when default subcommand and unrecognised option then call default', () => {\n    const { program, actionMock } = makeProgram();\n    program.parse('node test.js --an-option'.split(' '));\n    expect(actionMock).toHaveBeenCalled();\n  });\n});\n\ndescribe('default added command', () => {\n  function makeProgram() {\n    const actionMock = jest.fn();\n    const defaultCmd = new commander.Command('default')\n      .allowUnknownOption()\n      .allowExcessArguments()\n      .action(actionMock);\n\n    const program = new commander.Command();\n    program.command('other');\n    program.addCommand(defaultCmd, { isDefault: true });\n    return { program, actionMock };\n  }\n\n  test('when default subcommand and no command then call default', () => {\n    const { program, actionMock } = makeProgram();\n    program.parse('node test.js'.split(' '));\n    expect(actionMock).toHaveBeenCalled();\n  });\n\n  test('when default subcommand and unrecognised argument then call default', () => {\n    const { program, actionMock } = makeProgram();\n    program.parse('node test.js an-argument'.split(' '));\n    expect(actionMock).toHaveBeenCalled();\n  });\n\n  test('when default subcommand and unrecognised option then call default', () => {\n    const { program, actionMock } = makeProgram();\n    program.parse('node test.js --an-option'.split(' '));\n    expect(actionMock).toHaveBeenCalled();\n  });\n});\n"
  },
  {
    "path": "tests/command.description.test.js",
    "content": "const commander = require('../');\n\ntest('when set description then get description', () => {\n  const program = new commander.Command();\n  const description = 'abcdef';\n  program.description(description);\n  expect(program.description()).toMatch(description);\n});\n"
  },
  {
    "path": "tests/command.error.test.js",
    "content": "const commander = require('../');\n\ntest('when error called with message then message displayed on stderr', () => {\n  const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {});\n  const stderrSpy = jest\n    .spyOn(process.stderr, 'write')\n    .mockImplementation(() => {});\n\n  const program = new commander.Command();\n  const message = 'Goodbye';\n  program.error(message);\n\n  expect(stderrSpy).toHaveBeenCalledWith(`${message}\\n`);\n  stderrSpy.mockRestore();\n  exitSpy.mockRestore();\n});\n\ntest('when error called with no exitCode then process.exit(1)', () => {\n  const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {});\n\n  const program = new commander.Command();\n  program.configureOutput({\n    writeErr: () => {},\n  });\n\n  program.error('Goodbye');\n\n  expect(exitSpy).toHaveBeenCalledWith(1);\n  exitSpy.mockRestore();\n});\n\ntest('when error called with exitCode 2 then process.exit(2)', () => {\n  const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {});\n\n  const program = new commander.Command();\n  program.configureOutput({\n    writeErr: () => {},\n  });\n  program.error('Goodbye', { exitCode: 2 });\n\n  expect(exitSpy).toHaveBeenCalledWith(2);\n  exitSpy.mockRestore();\n});\n\ntest('when error called with code and exitOverride then throws with code', () => {\n  const program = new commander.Command();\n  let errorThrown;\n  program\n    .exitOverride((err) => {\n      errorThrown = err;\n      throw err;\n    })\n    .configureOutput({\n      writeErr: () => {},\n    });\n\n  const code = 'commander.test';\n  expect(() => {\n    program.error('Goodbye', { code });\n  }).toThrow();\n  expect(errorThrown.code).toEqual(code);\n});\n"
  },
  {
    "path": "tests/command.executableSubcommand.inspect.test.js",
    "content": "const childProcess = require('child_process');\nconst path = require('path');\nconst util = require('util');\n\nconst execFileAsync = util.promisify(childProcess.execFile);\n\n// Test the special handling for --inspect to increment fixed debug port numbers.\n// If we reuse port we can get conflicts because port not released fast enough.\n\nconst inspectCommand = path.join(__dirname, './fixtures', 'inspect.js');\n\ntest('when execArgv empty then spawn execArgs empty', async () => {\n  const { stdout } = await execFileAsync('node', [inspectCommand, 'sub']);\n  expect(stdout).toBe('[]\\n');\n});\n\ntest('when execArgv --harmony then spawn execArgs --harmony', async () => {\n  const { stdout } = await execFileAsync('node', [\n    '--harmony',\n    inspectCommand,\n    'sub',\n  ]);\n  expect(stdout).toBe(\"[ '--harmony' ]\\n\");\n});\n\n// --inspect defaults to 127.0.0.1:9229, port should be incremented\ntest('when execArgv --inspect then spawn execArgs using port 9230', async () => {\n  const { stdout } = await execFileAsync('node', [\n    '--inspect',\n    inspectCommand,\n    'sub',\n  ]);\n  expect(stdout).toBe(\"[ '--inspect=127.0.0.1:9230' ]\\n\");\n});\n\n// custom port\ntest('when execArgv --inspect=9240 then spawn execArgs using port 9241', async () => {\n  const { stdout } = await execFileAsync('node', [\n    '--inspect=9240',\n    inspectCommand,\n    'sub',\n  ]);\n  expect(stdout).toBe(\"[ '--inspect=127.0.0.1:9241' ]\\n\");\n});\n\n// zero is special, random port\ntest('when execArgv --inspect=0 then spawn execArgs --inspect=0', async () => {\n  const { stdout } = await execFileAsync('node', [\n    '--inspect=0',\n    inspectCommand,\n    'sub',\n  ]);\n  expect(stdout).toBe(\"[ '--inspect=0' ]\\n\");\n});\n\n// ip address\ntest('when execArgv --inspect=127.0.0.1:9250 then spawn execArgs --inspect=127.0.0.1:9251', async () => {\n  const { stdout } = await execFileAsync('node', [\n    '--inspect=127.0.0.1:9250',\n    inspectCommand,\n    'sub',\n  ]);\n  expect(stdout).toBe(\"[ '--inspect=127.0.0.1:9251' ]\\n\");\n});\n\n// localhost\ntest('when execArgv --inspect=localhost:9260 then spawn execArgs --inspect=localhost:9261', async () => {\n  const { stdout } = await execFileAsync('node', [\n    '--inspect=localhost:9260',\n    inspectCommand,\n    'sub',\n  ]);\n  expect(stdout).toBe(\"[ '--inspect=localhost:9261' ]\\n\");\n});\n\n// --inspect-port, just test most likely format\ntest('when execArgv --inspect-port=9270 then spawn execArgs --inspect-port=127.0.0.1:9271', async () => {\n  const { stdout } = await execFileAsync('node', [\n    '--inspect-port=9270',\n    inspectCommand,\n    'sub',\n  ]);\n  expect(stdout).toBe(\"[ '--inspect-port=127.0.0.1:9271' ]\\n\");\n});\n"
  },
  {
    "path": "tests/command.executableSubcommand.lookup.test.js",
    "content": "const childProcess = require('child_process');\nconst path = require('path');\nconst util = require('util');\nconst execFileAsync = util.promisify(childProcess.execFile);\n\n// Calling node explicitly so pm works without file suffix cross-platform.\n// This file does end-to-end tests actually spawning program.\n// See also command.executableSubcommand.search.test.js\n\n// Suppress false positive warnings due to use of testOrSkipOnWindows\n/* eslint-disable jest/no-standalone-expect */\n\nconst testOrSkipOnWindows = process.platform === 'win32' ? test.skip : test;\nconst pm = path.join(__dirname, './fixtures/pm');\n\ntest('when subcommand file missing then error', () => {\n  expect.assertions(1);\n  return execFileAsync('node', [pm, 'list']).catch((err) => {\n    if (process.platform === 'win32') {\n      // Get uncaught thrown error on Windows\n      // eslint-disable-next-line jest/no-conditional-expect\n      expect(err.stderr).toBeDefined();\n    } else {\n      // eslint-disable-next-line jest/no-conditional-expect\n      expect(err.stderr).toMatch(/Error: 'pm-list' does not exist/);\n    }\n  });\n});\n\ntest('when alias subcommand file missing then error', () => {\n  expect.assertions(1);\n  return execFileAsync('node', [pm, 'lst']).catch((err) => {\n    if (process.platform === 'win32') {\n      // Get uncaught thrown error on Windows\n      // eslint-disable-next-line jest/no-conditional-expect\n      expect(err.stderr).toBeDefined();\n    } else {\n      // eslint-disable-next-line jest/no-conditional-expect\n      expect(err.stderr).toMatch(/Error: 'pm-list' does not exist/);\n    }\n  });\n});\n\ntest('when subcommand file has no suffix then lookup succeeds', async () => {\n  const { stdout } = await execFileAsync('node', [pm, 'install']);\n  expect(stdout).toBe('install\\n');\n});\n\ntest('when alias subcommand file has no suffix then lookup succeeds', async () => {\n  const { stdout } = await execFileAsync('node', [pm, 'i']);\n  expect(stdout).toBe('install\\n');\n});\n\ntest('when subcommand target executablefile has no suffix then lookup succeeds', async () => {\n  const { stdout } = await execFileAsync('node', [pm, 'specifyInstall']);\n  expect(stdout).toBe('install\\n');\n});\n\ntest('when subcommand file suffix .js then lookup succeeds', async () => {\n  const { stdout } = await execFileAsync('node', [pm, 'publish']);\n  expect(stdout).toBe('publish\\n');\n});\n\ntest('when alias subcommand file suffix .js then lookup succeeds', async () => {\n  const { stdout } = await execFileAsync('node', [pm, 'p']);\n  expect(stdout).toBe('publish\\n');\n});\n\ntest('when subcommand target executablefile has suffix .js then lookup succeeds', async () => {\n  const { stdout } = await execFileAsync('node', [pm, 'specifyPublish']);\n  expect(stdout).toBe('publish\\n');\n});\n\ntestOrSkipOnWindows(\n  'when subcommand file is symlink then lookup succeeds',\n  async () => {\n    const pmlink = path.join(__dirname, 'fixtures', 'pmlink');\n    const { stdout } = await execFileAsync('node', [pmlink, 'install']);\n    expect(stdout).toBe('install\\n');\n  },\n);\n\ntestOrSkipOnWindows(\n  'when subcommand file is double symlink then lookup succeeds',\n  async () => {\n    const pmlink = path.join(__dirname, 'fixtures', 'another-dir', 'pm');\n    const { stdout } = await execFileAsync('node', [pmlink, 'install']);\n    expect(stdout).toBe('install\\n');\n  },\n);\n\ntest('when subcommand suffix is .ts then lookup succeeds', async () => {\n  // We support looking for ts files for ts-node in particular, but don't need to test ts-node itself.\n  // The subcommand is both plain JavaScript code for this test.\n  const binLinkTs = path.join(__dirname, 'fixtures-extensions', 'pm.js');\n  // childProcess.execFile('node', ['-r', 'ts-node/register', binLinkTs, 'install'], function(_error, stdout, stderr) {\n  const { stdout } = await execFileAsync('node', [binLinkTs, 'try-ts']);\n  expect(stdout).toBe('found .ts\\n');\n});\n\ntest('when subcommand suffix is .cjs then lookup succeeds', async () => {\n  const binLinkTs = path.join(__dirname, 'fixtures-extensions', 'pm.js');\n  const { stdout } = await execFileAsync('node', [binLinkTs, 'try-cjs']);\n  expect(stdout).toBe('found .cjs\\n');\n});\n\ntest('when subcommand suffix is .mjs then lookup succeeds', async () => {\n  const binLinkTs = path.join(__dirname, 'fixtures-extensions', 'pm.js');\n  const { stdout } = await execFileAsync('node', [binLinkTs, 'try-mjs']);\n  expect(stdout).toBe('found .mjs\\n');\n});\n\ntest('when subsubcommand then lookup sub-sub-command', async () => {\n  const { stdout } = await execFileAsync('node', [pm, 'cache', 'clear']);\n  expect(stdout).toBe('cache-clear\\n');\n});\n"
  },
  {
    "path": "tests/command.executableSubcommand.mock.test.js",
    "content": "const commander = require('../');\nconst childProcess = require('child_process');\nconst EventEmitter = require('events');\n\n// Using mock to allow try/catch around what is otherwise out-of-stack error handling.\n// Injecting errors, these are not end-to-end tests.\n\nfunction makeSystemError(code) {\n  // We can not make an actual SystemError, but our usage is lightweight so easy to match.\n  const err = new Error();\n  err.code = code;\n  return err;\n}\n\n// Suppress false positive warnings due to use of testOrSkipOnWindows\n/* eslint-disable jest/no-standalone-expect */\n\nconst testOrSkipOnWindows = process.platform === 'win32' ? test.skip : test;\n\ntestOrSkipOnWindows(\n  'when subcommand executable missing (ENOENT) then throw custom message',\n  () => {\n    // If the command is not found, we show a custom error with an explanation and offer\n    // some advice for possible fixes.\n    const mockProcess = new EventEmitter();\n    const spawnSpy = jest\n      .spyOn(childProcess, 'spawn')\n      .mockImplementation(() => {\n        return mockProcess;\n      });\n    const program = new commander.Command();\n    program.exitOverride();\n    program.command('executable', 'executable description');\n    program.parse(['executable'], { from: 'user' });\n    expect(() => {\n      mockProcess.emit('error', makeSystemError('ENOENT'));\n    }).toThrow('use the executableFile option to supply a custom name'); // part of custom message\n    spawnSpy.mockRestore();\n  },\n);\n\ntestOrSkipOnWindows(\n  'when subcommand executable not executable (EACCES) then throw custom message',\n  () => {\n    const mockProcess = new EventEmitter();\n    const spawnSpy = jest\n      .spyOn(childProcess, 'spawn')\n      .mockImplementation(() => {\n        return mockProcess;\n      });\n    const program = new commander.Command();\n    program.exitOverride();\n    program.command('executable', 'executable description');\n    program.parse(['executable'], { from: 'user' });\n    expect(() => {\n      mockProcess.emit('error', makeSystemError('EACCES'));\n    }).toThrow('not executable'); // part of custom message\n    spawnSpy.mockRestore();\n  },\n);\n\ntest('when subcommand executable fails with other error and exitOverride then return in custom wrapper', () => {\n  // The existing behaviour is to just silently fail for unexpected errors, as it is happening\n  // asynchronously in spawned process and client can not catch errors.\n  const mockProcess = new EventEmitter();\n  const spawnSpy = jest.spyOn(childProcess, 'spawn').mockImplementation(() => {\n    return mockProcess;\n  });\n  const program = new commander.Command();\n  program._checkForMissingExecutable = () => {}; // suppress error, call mocked spawn\n  program.exitOverride((err) => {\n    throw err;\n  });\n  program.command('executable', 'executable description');\n  program.parse(['executable'], { from: 'user' });\n  let caughtErr;\n  try {\n    mockProcess.emit('error', makeSystemError('OTHER'));\n  } catch (err) {\n    caughtErr = err;\n  }\n  expect(caughtErr.code).toEqual('commander.executeSubCommandAsync');\n  expect(caughtErr.nestedError.code).toEqual('OTHER');\n  spawnSpy.mockRestore();\n});\n\ntest('when subcommand executable fails with other error then exit', () => {\n  // The existing behaviour is to just silently fail for unexpected errors, as it is happening\n  // asynchronously in spawned process and client can not catch errors.\n  const mockProcess = new EventEmitter();\n  const spawnSpy = jest.spyOn(childProcess, 'spawn').mockImplementation(() => {\n    return mockProcess;\n  });\n  const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {});\n  const program = new commander.Command();\n  program._checkForMissingExecutable = () => {}; // suppress error, call mocked spawn\n  program.command('executable', 'executable description');\n  program.parse(['executable'], { from: 'user' });\n  mockProcess.emit('error', makeSystemError('OTHER'));\n  expect(exitSpy).toHaveBeenCalledWith(1);\n  exitSpy.mockRestore();\n  spawnSpy.mockRestore();\n});\n"
  },
  {
    "path": "tests/command.executableSubcommand.search.test.js",
    "content": "const childProcess = require('child_process');\nconst fs = require('fs');\nconst path = require('path');\nconst commander = require('../');\n\n// This file does in-process mocking. Bit clumsy but faster and less external clutter than using fixtures.\n// See also command.executableSubcommand.lookup.test.js for tests using fixtures.\n\nconst gLocalDirectory = path.resolve(__dirname, 'fixtures'); // Real directory, although not actually searching for files in it.\n\nfunction extractMockSpawnArgs(mock) {\n  expect(mock).toHaveBeenCalled();\n  // non-Win, launchWithNode: childProcess.spawn(process.argv[0], args, { stdio: 'inherit' });\n  // Win always: childProcess.spawn(process.execPath, args, { stdio: 'inherit' });\n  return mock.mock.calls[0][1];\n}\n\nfunction extractMockSpawnCommand(mock) {\n  expect(mock).toHaveBeenCalled();\n  // child_process.spawn(command[, args][, options])\n  return mock.mock.calls[0][0];\n}\n\nconst describeOrSkipOnWindows =\n  process.platform === 'win32' ? describe.skip : describe;\n\ndescribe('search for subcommand', () => {\n  let spawnSpy;\n  let existsSpy;\n\n  beforeAll(() => {\n    spawnSpy = jest.spyOn(childProcess, 'spawn').mockImplementation(() => {\n      return {\n        on: () => {},\n        killed: true,\n      };\n    });\n  });\n\n  beforeEach(() => {\n    existsSpy = jest.spyOn(fs, 'existsSync');\n  });\n\n  afterEach(() => {\n    spawnSpy.mockClear();\n    existsSpy.mockRestore();\n  });\n\n  afterAll(() => {\n    spawnSpy.mockRestore();\n  });\n\n  // fs.existsSync gets called on Windows outside the search, so skip the tests (or come up with a different way of checking).\n  describe('whether perform search for local files', () => {\n    beforeEach(() => {\n      existsSpy.mockImplementation(() => false);\n    });\n\n    test('when no script arg or executableDir then no search for local file', () => {\n      const program = new commander.Command();\n      program._checkForMissingExecutable = () => {}; // suppress error, call mocked spawn\n      program.name('pm');\n      program.command('sub', 'executable description');\n      program.parse(['sub'], { from: 'user' });\n\n      expect(existsSpy).not.toHaveBeenCalled();\n    });\n\n    test('when script arg then search for local files', () => {\n      const program = new commander.Command();\n      program._checkForMissingExecutable = () => {}; // suppress error, call mocked spawn\n      program.name('pm');\n      program.command('sub', 'executable description');\n      program.parse(['node', 'script-name', 'sub']);\n\n      expect(existsSpy).toHaveBeenCalled();\n    });\n\n    test('when executableDir then search for local files)', () => {\n      const program = new commander.Command();\n      program._checkForMissingExecutable = () => {}; // suppress error, call mocked spawn\n      program.name('pm');\n      program.executableDir(__dirname);\n      program.command('sub', 'executable description');\n      program.parse(['sub'], { from: 'user' });\n\n      expect(existsSpy).toHaveBeenCalled();\n    });\n  });\n\n  // We always use node on Windows, and don't spawn executable as the command (which may be a feature or a shortcoming!?).\n  describeOrSkipOnWindows(\n    'subcommand command name with no matching local file (non-Windows)',\n    () => {\n      beforeEach(() => {\n        existsSpy.mockImplementation(() => false);\n      });\n\n      test('when named pm and no script arg or executableDir then spawn pm-sub as command', () => {\n        const program = new commander.Command();\n        program.name('pm');\n        program.command('sub', 'executable description');\n        program.parse(['sub'], { from: 'user' });\n\n        expect(extractMockSpawnCommand(spawnSpy)).toEqual('pm-sub');\n      });\n\n      test('when named pm and script arg then still spawn pm-sub as command', () => {\n        const program = new commander.Command();\n        program.name('pm');\n        program.command('sub', 'executable description');\n        program.parse(['node', 'script-name', 'sub']);\n\n        expect(extractMockSpawnCommand(spawnSpy)).toEqual('pm-sub');\n      });\n\n      test('when no name and script arg then spawn script-sub as command', () => {\n        const program = new commander.Command();\n        program.command('sub', 'executable description');\n        program.parse(['node', 'script.js', 'sub']);\n\n        expect(extractMockSpawnCommand(spawnSpy)).toEqual('script-sub');\n      });\n\n      test('when named pm and script arg and executableFile then spawn executableFile as command', () => {\n        const program = new commander.Command();\n        program.command('sub', 'executable description', {\n          executableFile: 'myExecutable',\n        });\n        program.parse(['node', 'script.js', 'sub']);\n\n        expect(extractMockSpawnCommand(spawnSpy)).toEqual('myExecutable');\n      });\n    },\n  );\n\n  describe('subcommand command name with matching local file', () => {\n    test('when construct with name pm and script arg then spawn local pm-sub.js', () => {\n      const program = new commander.Command('pm');\n      program.command('sub', 'executable description');\n\n      const localPath = path.resolve(gLocalDirectory, 'pm-sub.js');\n      existsSpy.mockImplementation((path) => path === localPath);\n      program.parse([\n        'node',\n        path.resolve(gLocalDirectory, 'script.js'),\n        'sub',\n      ]);\n\n      expect(extractMockSpawnArgs(spawnSpy)).toEqual([localPath]);\n    });\n\n    test('when name pm and script arg then spawn local pm-sub.js', () => {\n      const program = new commander.Command();\n      program.name('pm');\n      program.command('sub', 'executable description');\n\n      const localPath = path.resolve(gLocalDirectory, 'pm-sub.js');\n      existsSpy.mockImplementation((path) => path === localPath);\n      program.parse([\n        'node',\n        path.resolve(gLocalDirectory, 'script.js'),\n        'sub',\n      ]);\n\n      expect(extractMockSpawnArgs(spawnSpy)).toEqual([localPath]);\n    });\n\n    test('when script arg then spawn local script-sub.js', () => {\n      const program = new commander.Command();\n      program.command('sub', 'executable description');\n\n      const localPath = path.resolve(gLocalDirectory, 'script-sub.js');\n      existsSpy.mockImplementation((path) => path === localPath);\n      program.parse([\n        'node',\n        path.resolve(gLocalDirectory, 'script.js'),\n        'sub',\n      ]);\n\n      expect(extractMockSpawnArgs(spawnSpy)).toEqual([localPath]);\n    });\n\n    test('when name pm and script arg and only script-sub.js then fallback to spawn local script-sub.js', () => {\n      const program = new commander.Command();\n      program.name('pm');\n      program.command('sub', 'executable description');\n\n      // Fallback for compatibility with Commander <= v8\n      const localPath = path.resolve(gLocalDirectory, 'script-sub.js');\n      existsSpy.mockImplementation((path) => path === localPath);\n      program.parse([\n        'node',\n        path.resolve(gLocalDirectory, 'script.js'),\n        'sub',\n      ]);\n\n      expect(extractMockSpawnArgs(spawnSpy)).toEqual([localPath]);\n    });\n\n    test('when name pm and executableDir then spawn local pm-sub.js', () => {\n      const program = new commander.Command();\n      program.name('pm');\n      program.command('sub', 'executable description');\n\n      const execDir = path.resolve(gLocalDirectory, 'exec-dir');\n      program.executableDir(execDir);\n      const localPath = path.resolve(execDir, 'pm-sub.js');\n      existsSpy.mockImplementation((path) => path === localPath);\n      program.parse(['sub'], { from: 'user' });\n\n      expect(extractMockSpawnArgs(spawnSpy)).toEqual([localPath]);\n    });\n\n    test('when script arg and relative executableDir then spawn relative script-sub.js', () => {\n      const program = new commander.Command();\n      program.command('sub', 'executable description');\n\n      const execDir = 'exec-dir';\n      program.executableDir(execDir);\n      const localPath = path.resolve(gLocalDirectory, execDir, 'script-sub.js');\n      existsSpy.mockImplementation((path) => path === localPath);\n      program.parse(['node', path.resolve(gLocalDirectory, 'script'), 'sub']);\n\n      expect(extractMockSpawnArgs(spawnSpy)).toEqual([localPath]);\n    });\n\n    test('when script arg and absolute executableDir then spawn absolute script-sub.js', () => {\n      const program = new commander.Command();\n      program.command('sub', 'executable description');\n\n      const execDir = path.resolve(gLocalDirectory, 'exec-dir');\n      program.executableDir(execDir);\n      const localPath = path.resolve(execDir, 'script-sub.js');\n      existsSpy.mockImplementation((path) => path === localPath);\n      program.parse([\n        'node',\n        path.resolve(gLocalDirectory, 'script-Dir', 'script'),\n        'sub',\n      ]);\n\n      expect(extractMockSpawnArgs(spawnSpy)).toEqual([localPath]);\n    });\n\n    test('when script arg is link and and link-sub relative to link target then spawn local link-sub', () => {\n      const program = new commander.Command();\n      program.command('sub', 'executable description');\n\n      const linkPath = path.resolve(gLocalDirectory, 'link', 'link');\n      const scriptPath = path.resolve(gLocalDirectory, 'script', 'script.js');\n      const scriptSubPath = path.resolve(\n        gLocalDirectory,\n        'script',\n        'link-sub.js',\n      );\n      const realPathSyncSpy = jest\n        .spyOn(fs, 'realpathSync')\n        .mockImplementation((path) => {\n          return path === linkPath ? scriptPath : linkPath;\n        });\n      existsSpy.mockImplementation((path) => path === scriptSubPath);\n      program.parse(['node', linkPath, 'sub']);\n      realPathSyncSpy.mockRestore();\n\n      expect(extractMockSpawnArgs(spawnSpy)).toEqual([scriptSubPath]);\n    });\n\n    test('when name pm and script arg and relative executableFile then spawn local exec.js', () => {\n      const program = new commander.Command('pm');\n      const localPath = path.join('relative', 'exec.js');\n      const absolutePath = path.resolve(gLocalDirectory, localPath);\n      program.command('sub', 'executable description', {\n        executableFile: localPath,\n      });\n\n      existsSpy.mockImplementation((path) => path === absolutePath);\n      program.parse([\n        'node',\n        path.resolve(gLocalDirectory, 'script.js'),\n        'sub',\n      ]);\n\n      expect(extractMockSpawnArgs(spawnSpy)).toEqual([absolutePath]);\n    });\n\n    test('when name pm and script arg and absolute executableFile then spawn local exec.js', () => {\n      const program = new commander.Command('pm');\n      const localPath = path.resolve(gLocalDirectory, 'absolute', 'exec.js');\n      program.command('sub', 'executable description', {\n        executableFile: localPath,\n      });\n\n      existsSpy.mockImplementation((path) => path === localPath);\n      program.parse([\n        'node',\n        path.resolve(gLocalDirectory, 'script.js'),\n        'sub',\n      ]);\n\n      expect(extractMockSpawnArgs(spawnSpy)).toEqual([localPath]);\n    });\n  });\n\n  describe('search for local file', () => {\n    test('when script arg then search for local script-sub.js, .ts, .tsx, .mpjs, .cjs', () => {\n      existsSpy.mockImplementation((path) => false);\n      const program = new commander.Command();\n      program._checkForMissingExecutable = () => {}; // suppress error, call mocked spawn\n      program.command('sub', 'executable description');\n      const scriptPath = path.resolve(gLocalDirectory, 'script');\n      program.parse(['node', scriptPath, 'sub']);\n      const sourceExt = ['.js', '.ts', '.tsx', '.mjs', '.cjs'];\n      sourceExt.forEach((ext) => {\n        expect(existsSpy).toHaveBeenCalledWith(\n          path.resolve(gLocalDirectory, `script-sub${ext}`),\n        );\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "tests/command.executableSubcommand.signals.test.js",
    "content": "const childProcess = require('child_process');\nconst path = require('path');\n\nconst pmPath = path.join(__dirname, 'fixtures', 'pm');\n\n// Disabling some tests on Windows as:\n// \"Windows does not support sending signals\"\n//  https://nodejs.org/api/process.html#process_signal_events\nconst describeOrSkipOnWindows =\n  process.platform === 'win32' ? describe.skip : describe;\n\ndescribeOrSkipOnWindows('signals', () => {\n  test.each(['SIGINT', 'SIGHUP', 'SIGTERM', 'SIGUSR1', 'SIGUSR2'])(\n    'when program sent %s then executableSubcommand sent signal too',\n    (signal, done) => {\n      // Spawn program. The listen subcommand waits for a signal and writes the name of the signal to stdout.\n      const proc = childProcess.spawn(pmPath, ['listen'], {});\n\n      let processOutput = '';\n      proc.stdout.on('data', (data) => {\n        if (processOutput.length === 0) {\n          // Send signal to program.\n          proc.kill(`${signal}`);\n        }\n        processOutput += data.toString();\n      });\n      proc.on('close', (code) => {\n        // Check the child subcommand received the signal too.\n        expect(processOutput).toBe(`Listening for signal...${signal}`);\n        done();\n      });\n    },\n  );\n\n  test('when executable subcommand sent signal then program exit code is non-zero', () => {\n    const { status } = childProcess.spawnSync(pmPath, ['terminate'], {});\n    expect(status).toBeGreaterThan(0);\n  });\n\n  test('when command has exitOverride and executable subcommand sent signal then exit code is non-zero', () => {\n    const { status } = childProcess.spawnSync(\n      pmPath,\n      ['exit-override', 'terminate'],\n      {},\n    );\n    expect(status).toBeGreaterThan(0);\n  });\n\n  // Not a signal test, but closely related code so adding here.\n  test('when command has exitOverride and executable subcommand fails then program exit code is subcommand exit code', () => {\n    const { status } = childProcess.spawnSync(\n      pmPath,\n      ['exit-override', 'fail'],\n      {},\n    );\n    expect(status).toEqual(42);\n  });\n});\n"
  },
  {
    "path": "tests/command.executableSubcommand.test.js",
    "content": "const commander = require('../');\n\n// Executable subcommand tests that didn't fit in elsewhere.\n\n// This is the default behaviour when no default command and no action handlers\ntest('when no command specified and executable then display help', () => {\n  // Optional. Suppress normal output to keep test output clean.\n  const writeSpy = jest\n    .spyOn(process.stderr, 'write')\n    .mockImplementation(() => {});\n  const program = new commander.Command();\n  program\n    .exitOverride((err) => {\n      throw err;\n    })\n    .command('install', 'install description');\n  expect(() => {\n    program.parse(['node', 'test']);\n  }).toThrow('(outputHelp)');\n  writeSpy.mockClear();\n});\n"
  },
  {
    "path": "tests/command.exitOverride.test.js",
    "content": "const commander = require('../');\nconst path = require('path');\n\n// Test details of the exitOverride errors.\n// The important checks are the exitCode and code which are intended to be stable for\n// semver minor versions. For now, also testing the error.message and that output occurred\n// to detect accidental changes in behaviour.\n\n/* eslint jest/expect-expect: [\"error\", { \"assertFunctionNames\": [\"expect\", \"expectCommanderError\"] }] */\n\nfunction expectCommanderError(err, exitCode, code, message) {\n  expect(err).toBeInstanceOf(commander.CommanderError);\n  expect(err.exitCode).toBe(exitCode);\n  expect(err.code).toBe(code);\n  expect(err.message).toBe(message);\n}\n\ndescribe('.exitOverride and error details', () => {\n  // Use internal knowledge to suppress output to keep test output clean.\n  let stderrSpy;\n\n  beforeAll(() => {\n    stderrSpy = jest\n      .spyOn(process.stderr, 'write')\n      .mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    stderrSpy.mockClear();\n  });\n\n  afterAll(() => {\n    stderrSpy.mockRestore();\n  });\n\n  test('when specify unknown program option then throw CommanderError', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', '-m']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expect(stderrSpy).toHaveBeenCalled();\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.unknownOption',\n      \"error: unknown option '-m'\",\n    );\n  });\n\n  test('when specify unknown command then throw CommanderError', () => {\n    const program = new commander.Command();\n    program.name('prog').exitOverride().command('sub');\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', 'oops']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expect(stderrSpy).toHaveBeenCalled();\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.unknownCommand',\n      \"error: unknown command 'oops'\",\n    );\n  });\n\n  // Same error as above, but with custom handler.\n  test('when supply custom handler then throw custom error', () => {\n    const customError = new commander.CommanderError(\n      123,\n      'custom-code',\n      'custom-message',\n    );\n    const program = new commander.Command();\n    program.exitOverride((_err) => {\n      throw customError;\n    });\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', '-m']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expectCommanderError(\n      caughtErr,\n      customError.exitCode,\n      customError.code,\n      customError.message,\n    );\n  });\n\n  test('when specify option without required value then throw CommanderError', () => {\n    const optionFlags = '-p, --pepper <type>';\n    const program = new commander.Command();\n    program.exitOverride().option(optionFlags, 'add pepper');\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', '--pepper']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expect(stderrSpy).toHaveBeenCalled();\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.optionMissingArgument',\n      `error: option '${optionFlags}' argument missing`,\n    );\n  });\n\n  test('when specify command without required argument then throw CommanderError', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .command('compress <arg-name>')\n      .action(() => {});\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', 'compress']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expect(stderrSpy).toHaveBeenCalled();\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.missingArgument',\n      \"error: missing required argument 'arg-name'\",\n    );\n  });\n\n  test('when specify program without required argument and no action handler then throw CommanderError', () => {\n    const program = new commander.Command();\n    program.exitOverride().argument('<arg-name>');\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expect(stderrSpy).toHaveBeenCalled();\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.missingArgument',\n      \"error: missing required argument 'arg-name'\",\n    );\n  });\n\n  test('when specify excess argument then throw CommanderError', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .allowExcessArguments(false)\n      .action(() => {});\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', 'excess']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expect(stderrSpy).toHaveBeenCalled();\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.excessArguments',\n      'error: too many arguments. Expected 0 arguments but got 1.',\n    );\n  });\n\n  test('when specify command with excess argument then throw CommanderError', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .command('speak')\n      .allowExcessArguments(false)\n      .action(() => {});\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', 'speak', 'excess']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expect(stderrSpy).toHaveBeenCalled();\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.excessArguments',\n      \"error: too many arguments for 'speak'. Expected 0 arguments but got 1.\",\n    );\n  });\n\n  test('when specify --help then throw CommanderError', () => {\n    const writeSpy = jest\n      .spyOn(process.stdout, 'write')\n      .mockImplementation(() => {});\n    const program = new commander.Command();\n    program.exitOverride();\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', '--help']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expectCommanderError(\n      caughtErr,\n      0,\n      'commander.helpDisplayed',\n      '(outputHelp)',\n    );\n    writeSpy.mockRestore();\n  });\n\n  test('when executable subcommand and no command specified then throw CommanderError', () => {\n    const program = new commander.Command();\n    program.exitOverride().command('compress', 'compress description');\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expectCommanderError(caughtErr, 1, 'commander.help', '(outputHelp)');\n  });\n\n  test('when specify --version then throw CommanderError', () => {\n    const stdoutSpy = jest\n      .spyOn(process.stdout, 'write')\n      .mockImplementation(() => {});\n    const myVersion = '1.2.3';\n    const program = new commander.Command();\n    program.exitOverride().version(myVersion);\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', '--version']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expectCommanderError(caughtErr, 0, 'commander.version', myVersion);\n    stdoutSpy.mockRestore();\n  });\n\n  test('when executableSubcommand succeeds then call exitOverride', async () => {\n    expect.hasAssertions();\n    const pm = path.join(__dirname, 'fixtures/pm');\n    const program = new commander.Command();\n    await new Promise((resolve) => {\n      program\n        .exitOverride((err) => {\n          expectCommanderError(\n            err,\n            0,\n            'commander.executeSubCommandAsync',\n            '(close)',\n          );\n          resolve();\n        })\n        .command('silent', 'description');\n      program.parse(['node', pm, 'silent']);\n    });\n  });\n\n  test('when mandatory program option missing then throw CommanderError', () => {\n    const optionFlags = '-p, --pepper <type>';\n    const program = new commander.Command();\n    program.exitOverride().requiredOption(optionFlags, 'add pepper');\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.missingMandatoryOptionValue',\n      `error: required option '${optionFlags}' not specified`,\n    );\n  });\n\n  test('when option argument not in choices then throw CommanderError', () => {\n    const optionFlags = '--colour <shade>';\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .addOption(new commander.Option(optionFlags).choices(['red', 'blue']));\n\n    let caughtErr;\n    try {\n      program.parse(['--colour', 'green'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.invalidArgument',\n      \"error: option '--colour <shade>' argument 'green' is invalid. Allowed choices are red, blue.\",\n    );\n  });\n\n  test('when command argument not in choices then throw CommanderError', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .addArgument(new commander.Argument('<shade>').choices(['red', 'blue']))\n      .action(() => {});\n\n    let caughtErr;\n    try {\n      program.parse(['green'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.invalidArgument',\n      \"error: command-argument value 'green' is invalid for argument 'shade'. Allowed choices are red, blue.\",\n    );\n  });\n\n  test('when custom processing for option throws InvalidArgumentError then catch CommanderError', () => {\n    function justSayNo(value) {\n      throw new commander.InvalidArgumentError('NO');\n    }\n    const optionFlags = '--colour <shade>';\n    const program = new commander.Command();\n    program.exitOverride().option(optionFlags, 'specify shade', justSayNo);\n\n    let caughtErr;\n    try {\n      program.parse(['--colour', 'green'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.invalidArgument',\n      \"error: option '--colour <shade>' argument 'green' is invalid. NO\",\n    );\n  });\n\n  test('when custom processing for argument throws InvalidArgumentError then catch CommanderError', () => {\n    function justSayNo(value) {\n      throw new commander.InvalidArgumentError('NO');\n    }\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .argument('[n]', 'number', justSayNo)\n      .action(() => {});\n\n    let caughtErr;\n    try {\n      program.parse(['green'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.invalidArgument',\n      \"error: command-argument value 'green' is invalid for argument 'n'. NO\",\n    );\n  });\n\n  test('when has conflicting option then throw CommanderError', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .addOption(new commander.Option('--silent'))\n      .addOption(new commander.Option('--debug').conflicts(['silent']));\n\n    let caughtErr;\n    try {\n      program.parse(['--debug', '--silent'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expectCommanderError(\n      caughtErr,\n      1,\n      'commander.conflictingOption',\n      \"error: option '--debug' cannot be used with option '--silent'\",\n    );\n  });\n\n  test('when call error() then throw CommanderError', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n\n    let caughtErr;\n    try {\n      program.error('message');\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expectCommanderError(caughtErr, 1, 'commander.error', 'message');\n  });\n});\n\ntest('when no override and error then exit(1)', () => {\n  const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {});\n  const program = new commander.Command();\n  program.configureOutput({ outputError: () => {} });\n  program.parse(['--unknownOption'], { from: 'user' });\n  expect(exitSpy).toHaveBeenCalledWith(1);\n  exitSpy.mockRestore();\n});\n\ntest('when custom processing throws custom error then throw custom error', () => {\n  function justSayNo(value) {\n    throw new Error('custom');\n  }\n  const program = new commander.Command();\n  program\n    .exitOverride()\n    .option('-s, --shade <value>', 'specify shade', justSayNo);\n\n  expect(() => {\n    program.parse(['--shade', 'green'], { from: 'user' });\n  }).toThrow('custom');\n});\n"
  },
  {
    "path": "tests/command.help.test.js",
    "content": "const commander = require('../');\n\n// Testing various help incantations.\n//\n// Note there are also specific help tests included in many of the feature tests,\n// such as the alias, version, usage, name, helpOption, and commandHelp tests.\n\n// Avoid doing many full format tests as will be broken by any layout changes!\ntest('when call helpInformation for program then help format is as expected (usage, options, commands)', () => {\n  const program = new commander.Command();\n  program.command('my-command <file>');\n  const expectedHelpInformation = `Usage: test [options] [command]\n\nOptions:\n  -h, --help         display help for command\n\nCommands:\n  my-command <file>\n  help [command]     display help for command\n`;\n\n  program.name('test');\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toBe(expectedHelpInformation);\n});\n\ntest('when use .description for command then help includes description', () => {\n  const program = new commander.Command();\n  program.command('simple-command').description('custom-description');\n  program._help = 'test';\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch(/simple-command +custom-description/);\n});\n\ntest('when call .help then exit', () => {\n  // Optional. Suppress normal output to keep test output clean.\n  const writeSpy = jest\n    .spyOn(process.stdout, 'write')\n    .mockImplementation(() => {});\n  const program = new commander.Command();\n  program.exitOverride();\n  expect(() => {\n    program.help();\n  }).toThrow('(outputHelp)');\n  writeSpy.mockClear();\n});\n\ntest('when specify --help then exit', () => {\n  // Optional. Suppress normal output to keep test output clean.\n  const writeSpy = jest\n    .spyOn(process.stdout, 'write')\n    .mockImplementation(() => {});\n  const program = new commander.Command();\n  program.exitOverride();\n  expect(() => {\n    program.parse(['node', 'test', '--help']);\n  }).toThrow('(outputHelp)');\n  writeSpy.mockClear();\n});\n\ntest('when call help(cb) then display cb output and exit', () => {\n  // Using spy to detect custom output\n  const writeSpy = jest\n    .spyOn(process.stdout, 'write')\n    .mockImplementation(() => {});\n  const helpReplacement = 'reformatted help';\n  const program = new commander.Command();\n  program.exitOverride();\n  expect(() => {\n    program.help((helpInformation) => {\n      return helpReplacement;\n    });\n  }).toThrow('(outputHelp)');\n  expect(writeSpy).toHaveBeenCalledWith(helpReplacement);\n  writeSpy.mockClear();\n});\n\ntest('when call outputHelp(cb) then display cb output', () => {\n  // Using spy to detect custom output\n  const writeSpy = jest\n    .spyOn(process.stdout, 'write')\n    .mockImplementation(() => {});\n  const helpReplacement = 'reformatted help';\n  const program = new commander.Command();\n  program.outputHelp((helpInformation) => {\n    return helpReplacement;\n  });\n  expect(writeSpy).toHaveBeenCalledWith(helpReplacement);\n  writeSpy.mockClear();\n});\n\ntest('when call deprecated outputHelp(cb) with wrong callback return type then throw', () => {\n  const program = new commander.Command();\n  expect(() => {\n    program.outputHelp((helpInformation) => 3);\n  }).toThrow();\n});\n\ntest('when command sets deprecated noHelp then not displayed in helpInformation', () => {\n  const program = new commander.Command();\n  program.command('secret', 'secret description', { noHelp: true });\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).not.toMatch('secret');\n});\n\ntest('when command sets hidden then not displayed in helpInformation', () => {\n  const program = new commander.Command();\n  program.command('secret', 'secret description', { hidden: true });\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).not.toMatch('secret');\n});\n\ntest('when addCommand with hidden:true then not displayed in helpInformation', () => {\n  const secretCmd = new commander.Command('secret');\n\n  const program = new commander.Command();\n  program.addCommand(secretCmd, { hidden: true });\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).not.toMatch('secret');\n});\n\ntest('when help short flag masked then not displayed in helpInformation', () => {\n  const program = new commander.Command();\n  program.option('-h, --host', 'select host');\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).not.toMatch(/\\W-h\\W.*display help/);\n});\n\ntest('when both help flags masked then not displayed in helpInformation', () => {\n  const program = new commander.Command();\n  program.option('-h, --help', 'custom');\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).not.toMatch('display help');\n});\n\ntest('when call .help then output on stdout', () => {\n  const writeSpy = jest\n    .spyOn(process.stdout, 'write')\n    .mockImplementation(() => {});\n  const program = new commander.Command();\n  program.exitOverride();\n  expect(() => {\n    program.help();\n  }).toThrow('(outputHelp)');\n  expect(writeSpy).toHaveBeenCalledWith(program.helpInformation());\n  writeSpy.mockClear();\n});\n\ntest('when call .help with { error: true } then output on stderr', () => {\n  const writeSpy = jest\n    .spyOn(process.stderr, 'write')\n    .mockImplementation(() => {});\n  const program = new commander.Command();\n  program.exitOverride();\n  expect(() => {\n    program.help({ error: true });\n  }).toThrow('(outputHelp)');\n  expect(writeSpy).toHaveBeenCalledWith(program.helpInformation());\n  writeSpy.mockClear();\n});\n\ntest('when no options then Options not included in helpInformation', () => {\n  const program = new commander.Command();\n  // No custom options, no version option, no help option\n  program.helpOption(false);\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).not.toMatch('Options');\n});\n\ntest('when negated option then option included in helpInformation', () => {\n  const program = new commander.Command();\n  program.option('-C, --no-colour', 'colourless');\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch('--no-colour');\n  expect(helpInformation).toMatch('colourless');\n});\n\ntest('when option.hideHelp() then option not included in helpInformation', () => {\n  const program = new commander.Command();\n  program.addOption(\n    new commander.Option('-s,--secret', 'secret option').hideHelp(),\n  );\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).not.toMatch('secret');\n});\n\ntest('when option.hideHelp(true) then option not included in helpInformation', () => {\n  const program = new commander.Command();\n  program.addOption(\n    new commander.Option('-s,--secret', 'secret option').hideHelp(true),\n  );\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).not.toMatch('secret');\n});\n\ntest('when option.hideHelp(false) then option included in helpInformation', () => {\n  const program = new commander.Command();\n  program.addOption(\n    new commander.Option('-s,--secret', 'secret option').hideHelp(false),\n  );\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch('secret');\n});\n\ntest('when option has default value then default included in helpInformation', () => {\n  const program = new commander.Command();\n  program.option('-p, --port <portNumber>', 'port number', 80);\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch('(default: 80)');\n});\n\ntest('when option has default value description then default description included in helpInformation', () => {\n  const program = new commander.Command();\n  program.addOption(\n    new commander.Option('-a, --address <dotted>', 'ip address').default(\n      '127.0.0.1',\n      'home',\n    ),\n  );\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch('(default: home)');\n});\n\ntest('when option has choices then choices included in helpInformation', () => {\n  const program = new commander.Command();\n  program.addOption(\n    new commander.Option('-c, --colour <colour>').choices(['red', 'blue']),\n  );\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch('(choices: \"red\", \"blue\")');\n});\n\ntest('when option has choices and default then both included in helpInformation', () => {\n  const program = new commander.Command();\n  program.addOption(\n    new commander.Option('-c, --colour <colour>')\n      .choices(['red', 'blue'])\n      .default('red'),\n  );\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch('(choices: \"red\", \"blue\", default: \"red\")');\n});\n\ntest('when argument then included in helpInformation', () => {\n  const program = new commander.Command();\n  program.name('foo').argument('<file>');\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch('Usage: foo [options] <file>');\n});\n\ntest('when argument described then included in helpInformation', () => {\n  const program = new commander.Command();\n  program.argument('<file>', 'input source').helpOption(false);\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch(/Arguments:\\n +file +input source/);\n});\n\ntest('when argument described with default then included in helpInformation', () => {\n  const program = new commander.Command();\n  program.argument('[file]', 'input source', 'test.txt').helpOption(false);\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch(\n    /Arguments:\\n +file +input source \\(default: \"test.txt\"\\)/,\n  );\n});\n\ntest('when arguments described in deprecated way then included in helpInformation', () => {\n  const program = new commander.Command();\n  program\n    .arguments('<file>')\n    .helpOption(false)\n    .description('description', { file: 'input source' });\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch(/Arguments:\\n +file +input source/);\n});\n\ntest('when arguments described in deprecated way and empty description then arguments still included in helpInformation', () => {\n  const program = new commander.Command();\n  program\n    .arguments('<file>')\n    .helpOption(false)\n    .description('', { file: 'input source' });\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch(/Arguments:\\n +file +input source/);\n});\n\ntest('when argument has choices then choices included in helpInformation', () => {\n  const program = new commander.Command();\n  program.addArgument(\n    new commander.Argument('<colour>', 'preferred colour').choices([\n      'red',\n      'blue',\n    ]),\n  );\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch('(choices: \"red\", \"blue\")');\n});\n\ntest('when argument has choices and default then both included in helpInformation', () => {\n  const program = new commander.Command();\n  program.addArgument(\n    new commander.Argument('<colour>', 'preferred colour')\n      .choices(['red', 'blue'])\n      .default('red'),\n  );\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch('(choices: \"red\", \"blue\", default: \"red\")');\n});\n"
  },
  {
    "path": "tests/command.helpCommand.test.js",
    "content": "const commander = require('../');\n\ndescribe('help command listed in helpInformation', () => {\n  test('when program has no subcommands then no automatic help command', () => {\n    const program = new commander.Command();\n    const helpInformation = program.helpInformation();\n    expect(helpInformation).not.toMatch(/help \\[command\\]/);\n  });\n\n  test('when program has no subcommands and add help command then has help command', () => {\n    const program = new commander.Command();\n    program.addHelpCommand(true);\n    const helpInformation = program.helpInformation();\n    expect(helpInformation).toMatch(/help \\[command\\]/);\n  });\n\n  test('when program has subcommands then has automatic help command', () => {\n    const program = new commander.Command();\n    program.command('foo');\n    const helpInformation = program.helpInformation();\n    expect(helpInformation).toMatch(/help \\[command\\]/);\n  });\n\n  test('when program has subcommands and specify only unknown option then display help', () => {\n    const program = new commander.Command();\n    program\n      .configureHelp({ formatHelp: () => '' })\n      .exitOverride()\n      .allowUnknownOption()\n      .command('foo');\n    let caughtErr;\n    try {\n      program.parse(['--unknown'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toEqual('commander.help');\n  });\n\n  test('when program has subcommands and suppress help command then no help command', () => {\n    const program = new commander.Command();\n    program.addHelpCommand(false);\n    program.command('foo');\n    const helpInformation = program.helpInformation();\n    expect(helpInformation).not.toMatch(/help \\[command\\]/);\n  });\n\n  test('when add custom help command then custom help command', () => {\n    const program = new commander.Command();\n    program.addHelpCommand('myHelp', 'help description');\n    const helpInformation = program.helpInformation();\n    expect(helpInformation).toMatch(/myHelp +help description/);\n  });\n});\n\ndescribe('help command processed on correct command', () => {\n  // Use internal knowledge to suppress output to keep test output clean.\n  let writeErrorSpy;\n  let writeSpy;\n\n  beforeAll(() => {\n    writeErrorSpy = jest\n      .spyOn(process.stderr, 'write')\n      .mockImplementation(() => {});\n    writeSpy = jest.spyOn(process.stdout, 'write').mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    writeErrorSpy.mockClear();\n    writeSpy.mockClear();\n  });\n\n  afterAll(() => {\n    writeErrorSpy.mockRestore();\n    writeSpy.mockRestore();\n  });\n\n  test('when \"program help\" then program', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n    program.command('sub1');\n    program.exitOverride(() => {\n      throw new Error('program');\n    });\n    expect(() => {\n      program.parse('node test.js help'.split(' '));\n    }).toThrow('program');\n  });\n\n  test('when \"program help unknown\" then program', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n    program.command('sub1');\n    program.exitOverride(() => {\n      throw new Error('program');\n    });\n    expect(() => {\n      program.parse('node test.js help unknown'.split(' '));\n    }).toThrow('program');\n  });\n\n  test('when \"program help sub1\" then sub1', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n    const sub1 = program.command('sub1');\n    sub1.exitOverride(() => {\n      throw new Error('sub1');\n    });\n    expect(() => {\n      program.parse('node test.js help sub1'.split(' '));\n    }).toThrow('sub1');\n  });\n\n  test('when \"program sub1 help sub2\" then sub2', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n    const sub1 = program.command('sub1');\n    const sub2 = sub1.command('sub2');\n    sub2.exitOverride(() => {\n      throw new Error('sub2');\n    });\n    expect(() => {\n      program.parse('node test.js sub1 help sub2'.split(' '));\n    }).toThrow('sub2');\n  });\n\n  test('when default command and \"program help\" then program', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n    program.command('sub1', { isDefault: true });\n    program.exitOverride(() => {\n      throw new Error('program');\n    });\n    expect(() => {\n      program.parse('node test.js help'.split(' '));\n    }).toThrow('program');\n  });\n\n  test('when no long help flag then \"help sub\" works', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n    program.helpOption('-H');\n    const sub = program.command('sub');\n    // Patch help for easy way to check called.\n    sub.help = () => {\n      throw new Error('sub help');\n    };\n    expect(() => {\n      program.parse(['help', 'sub'], { from: 'user' });\n    }).toThrow('sub help');\n  });\n\n  test('when no help options in sub then \"help sub\" works', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n    const sub = program.command('sub').helpOption(false);\n    // Patch help for easy way to check called.\n    sub.help = () => {\n      throw new Error('sub help');\n    };\n    expect(() => {\n      program.parse(['help', 'sub'], { from: 'user' });\n    }).toThrow('sub help');\n  });\n\n  test('when different help options in sub then \"help sub\" works', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n    const sub = program.command('sub');\n    program.helpOption('-h, --help');\n    sub.helpOption('-a, --assist');\n    // Patch help for easy way to check called.\n    sub.help = () => {\n      throw new Error('sub help');\n    };\n    expect(() => {\n      program.parse(['help', 'sub'], { from: 'user' });\n    }).toThrow('sub help');\n  });\n});\n"
  },
  {
    "path": "tests/command.helpOption.test.js",
    "content": "const commander = require('../');\n\ndescribe('helpOption', () => {\n  let writeSpy;\n  let writeErrorSpy;\n\n  beforeAll(() => {\n    // Optional. Suppress expected output to keep test output clean.\n    writeSpy = jest.spyOn(process.stdout, 'write').mockImplementation(() => {});\n    writeErrorSpy = jest\n      .spyOn(process.stderr, 'write')\n      .mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    writeSpy.mockClear();\n    writeErrorSpy.mockClear();\n  });\n\n  afterAll(() => {\n    writeSpy.mockRestore();\n    writeErrorSpy.mockRestore();\n  });\n\n  test('when helpOption has custom flags then custom short flag invokes help', () => {\n    const program = new commander.Command();\n    program.exitOverride().helpOption('-c,--custom-help', 'custom help output');\n    expect(() => {\n      program.parse(['-c'], { from: 'user' });\n    }).toThrow('(outputHelp)');\n  });\n\n  test('when helpOption has custom flags then custom long flag invokes help', () => {\n    const program = new commander.Command();\n    program.exitOverride().helpOption('-c,--custom-help', 'custom help output');\n    expect(() => {\n      program.parse(['--custom-help'], { from: 'user' });\n    }).toThrow('(outputHelp)');\n  });\n\n  test('when helpOption has just custom short flag then custom short flag invokes help', () => {\n    const program = new commander.Command();\n    program.exitOverride().helpOption('-c', 'custom help output');\n    expect(() => {\n      program.parse(['-c'], { from: 'user' });\n    }).toThrow('(outputHelp)');\n  });\n\n  test('when helpOption has just custom long flag then custom long flag invokes help', () => {\n    const program = new commander.Command();\n    program.exitOverride().helpOption('--custom-help', 'custom help output');\n    expect(() => {\n      program.parse(['--custom-help'], { from: 'user' });\n    }).toThrow('(outputHelp)');\n  });\n\n  test('when helpOption has custom description then helpInformation include custom description', () => {\n    const program = new commander.Command();\n    program.helpOption('-C,--custom-help', 'custom help output');\n    const helpInformation = program.helpInformation();\n    expect(helpInformation).toMatch(/-C,--custom-help +custom help output/);\n  });\n\n  test('when helpOption has just flags then helpInformation includes default description', () => {\n    const program = new commander.Command();\n    program.helpOption('-C,--custom-help');\n    const helpInformation = program.helpInformation();\n    expect(helpInformation).toMatch(\n      /-C,--custom-help +display help for command/,\n    );\n  });\n\n  test('when helpOption has just description then helpInformation includes default flags', () => {\n    const program = new commander.Command();\n    program.helpOption(undefined, 'custom help output');\n    const helpInformation = program.helpInformation();\n    expect(helpInformation).toMatch(/-h, --help +custom help output/);\n  });\n\n  test('when helpOption(false) then helpInformation does not include --help', () => {\n    const program = new commander.Command();\n    program.helpOption(false);\n    const helpInformation = program.helpInformation();\n    expect(helpInformation).not.toMatch('--help');\n  });\n\n  test('when helpOption(false) then --help is an unknown option', () => {\n    const program = new commander.Command();\n    program.exitOverride().helpOption(false);\n    let caughtErr;\n    try {\n      program.parse(['--help'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.unknownOption');\n  });\n\n  test('when helpOption(false) then -h is an unknown option', () => {\n    const program = new commander.Command();\n    program.exitOverride().helpOption(false);\n    let caughtErr;\n    try {\n      program.parse(['-h'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.unknownOption');\n  });\n\n  test('when helpOption(false) then unknown command error does not suggest --help', () => {\n    const program = new commander.Command();\n    program.exitOverride().helpOption(false).command('foo');\n    expect(() => {\n      program.parse(['UNKNOWN'], { from: 'user' });\n    }).toThrow(\"error: unknown command 'UNKNOWN'\");\n  });\n\n  test('when helpOption(true) after false then helpInformation does include --help', () => {\n    const program = new commander.Command();\n    program.helpOption(false);\n    program.helpOption(true);\n    const helpInformation = program.helpInformation();\n    expect(helpInformation).toMatch('--help');\n  });\n\n  test('when helpOption(true) after customise then helpInformation still customised', () => {\n    const program = new commander.Command();\n    program.helpOption('--ASSIST');\n    program.helpOption(true);\n    const helpInformation = program.helpInformation();\n    expect(helpInformation).toMatch('--ASSIST');\n  });\n});\n"
  },
  {
    "path": "tests/command.hook.test.js",
    "content": "const commander = require('../');\n\ntest('when hook event wrong then throw', () => {\n  const program = new commander.Command();\n  expect(() => {\n    program.hook('silly', () => {});\n  }).toThrow();\n});\n\ntest('when no action then action hooks not called', () => {\n  const hook = jest.fn();\n  const program = new commander.Command();\n  program.hook('preAction', hook).hook('postAction', hook);\n  program.parse([], { from: 'user' });\n  expect(hook).not.toHaveBeenCalled();\n});\n\ndescribe('action hooks with synchronous hooks, order', () => {\n  test('when hook preAction then hook called before action', () => {\n    const calls = [];\n    const program = new commander.Command();\n    program\n      .hook('preAction', () => calls.push('before'))\n      .action(() => calls.push('action'));\n    program.parse([], { from: 'user' });\n    expect(calls).toEqual(['before', 'action']);\n  });\n\n  test('when hook postAction then hook called after action', () => {\n    const calls = [];\n    const program = new commander.Command();\n    program\n      .hook('postAction', () => calls.push('after'))\n      .action(() => calls.push('action'));\n    program.parse([], { from: 'user' });\n    expect(calls).toEqual(['action', 'after']);\n  });\n\n  test('when hook preAction twice then hooks called FIFO', () => {\n    const calls = [];\n    const program = new commander.Command();\n    program\n      .hook('preAction', () => calls.push('1'))\n      .hook('preAction', () => calls.push('2'))\n      .action(() => calls.push('action'));\n    program.parse([], { from: 'user' });\n    expect(calls).toEqual(['1', '2', 'action']);\n  });\n\n  test('when hook postAction twice then hooks called LIFO', () => {\n    const calls = [];\n    const program = new commander.Command();\n    program\n      .hook('postAction', () => calls.push('1'))\n      .hook('postAction', () => calls.push('2'))\n      .action(() => calls.push('action'));\n    program.parse([], { from: 'user' });\n    expect(calls).toEqual(['action', '2', '1']);\n  });\n\n  test('when hook preAction at program and sub then hooks called program then sub', () => {\n    const calls = [];\n    const program = new commander.Command();\n    program.hook('preAction', () => calls.push('program'));\n    program\n      .command('sub')\n      .hook('preAction', () => calls.push('sub'))\n      .action(() => calls.push('action'));\n    program.parse(['sub'], { from: 'user' });\n    expect(calls).toEqual(['program', 'sub', 'action']);\n  });\n\n  test('when hook postAction at program and sub then hooks called sub then program', () => {\n    const calls = [];\n    const program = new commander.Command();\n    program.hook('postAction', () => calls.push('program'));\n    program\n      .command('sub')\n      .hook('postAction', () => calls.push('sub'))\n      .action(() => calls.push('action'));\n    program.parse(['sub'], { from: 'user' });\n    expect(calls).toEqual(['action', 'sub', 'program']);\n  });\n\n  test('when hook everything then hooks called nested', () => {\n    const calls = [];\n    const program = new commander.Command();\n    program\n      .hook('preAction', () => calls.push('pb1'))\n      .hook('postAction', () => calls.push('pa1'));\n    program\n      .hook('preAction', () => calls.push('pb2'))\n      .hook('postAction', () => calls.push('pa2'));\n    program\n      .command('sub')\n      .hook('preAction', () => calls.push('sb'))\n      .hook('postAction', () => calls.push('sa'))\n      .action(() => calls.push('action'));\n    program.parse(['sub'], { from: 'user' });\n    expect(calls).toEqual(['pb1', 'pb2', 'sb', 'action', 'sa', 'pa2', 'pa1']);\n  });\n});\n\ndescribe('action hooks context', () => {\n  test('when hook on program then passed program/program', () => {\n    const hook = jest.fn();\n    const program = new commander.Command();\n    program.hook('preAction', hook).action(() => {});\n    program.parse([], { from: 'user' });\n    expect(hook).toHaveBeenCalledWith(program, program);\n  });\n\n  test('when hook on program and call sub then passed program/sub', () => {\n    const hook = jest.fn();\n    const program = new commander.Command();\n    program.hook('preAction', hook);\n    const sub = program.command('sub').action(() => {});\n    program.parse(['sub'], { from: 'user' });\n    expect(hook).toHaveBeenCalledWith(program, sub);\n  });\n\n  test('when hook on sub and call sub then passed sub/sub', () => {\n    const hook = jest.fn();\n    const program = new commander.Command();\n    const sub = program\n      .command('sub')\n      .hook('preAction', hook)\n      .action(() => {});\n    program.parse(['sub'], { from: 'user' });\n    expect(hook).toHaveBeenCalledWith(sub, sub);\n  });\n\n  test('when hook program on preAction then thisCommand has options set', () => {\n    expect.assertions(1);\n    const program = new commander.Command();\n    program\n      .option('--debug')\n      .hook('preAction', (thisCommand) => {\n        expect(thisCommand.opts().debug).toEqual(true);\n      })\n      .action(() => {});\n    program.parse(['--debug'], { from: 'user' });\n  });\n\n  test('when hook program on preAction and call sub then thisCommand has program options set', () => {\n    expect.assertions(1);\n    const program = new commander.Command();\n    program.option('--debug').hook('preAction', (thisCommand) => {\n      expect(thisCommand.opts().debug).toEqual(true);\n    });\n    program.command('sub').action(() => {});\n    program.parse(['sub', '--debug'], { from: 'user' });\n  });\n\n  test('when hook program on preAction and call sub then actionCommand has sub options set', () => {\n    expect.assertions(1);\n    const program = new commander.Command();\n    program.hook('preAction', (thisCommand, actionCommand) => {\n      expect(actionCommand.opts().debug).toEqual(true);\n    });\n    program\n      .command('sub')\n      .option('--debug')\n      .action(() => {});\n    program.parse(['sub', '--debug'], { from: 'user' });\n  });\n\n  test('when hook program on preAction then actionCommand has args set', () => {\n    expect.assertions(1);\n    const program = new commander.Command();\n    program\n      .argument('[arg]')\n      .hook('preAction', (thisCommand, actionCommand) => {\n        expect(actionCommand.args).toEqual(['value']);\n      })\n      .action(() => {});\n    program.parse(['value'], { from: 'user' });\n  });\n\n  test('when hook program on preAction then actionCommand has args set with options removed', () => {\n    expect.assertions(1);\n    const program = new commander.Command();\n    program\n      .argument('[arg]')\n      .option('--debug')\n      .hook('preAction', (thisCommand, actionCommand) => {\n        expect(actionCommand.args).toEqual(['value']);\n      })\n      .action(() => {});\n    program.parse(['value', '--debug'], { from: 'user' });\n  });\n\n  test('when hook program on preAction and call sub then thisCommand has program args set', () => {\n    expect.assertions(1);\n    const program = new commander.Command();\n    program.argument('[arg]').hook('preAction', (thisCommand) => {\n      expect(thisCommand.args).toEqual(['sub', 'value']);\n    });\n    program\n      .command('sub')\n      .argument('<arg>')\n      .action(() => {});\n    program.parse(['sub', 'value'], { from: 'user' });\n  });\n\n  test('when hook program on preAction and call sub then actionCommand has sub args set', () => {\n    expect.assertions(1);\n    const program = new commander.Command();\n    program.hook('preAction', (thisCommand, actionCommand) => {\n      expect(actionCommand.args).toEqual(['value']);\n    });\n    program\n      .command('sub')\n      .argument('<arg>')\n      .action(() => {});\n    program.parse(['sub', 'value'], { from: 'user' });\n  });\n});\n\ndescribe('action hooks async', () => {\n  test('when async preAction then async from preAction', async () => {\n    const calls = [];\n    const program = new commander.Command();\n    program\n      .hook('preAction', async () => {\n        await 0;\n        calls.push('before');\n      })\n      .action(() => calls.push('action'));\n    const result = program.parseAsync([], { from: 'user' });\n    expect(calls).toEqual([]);\n    await result;\n    expect(calls).toEqual(['before', 'action']);\n  });\n\n  test('when async postAction then async from postAction', async () => {\n    const calls = [];\n    const program = new commander.Command();\n    program\n      .hook('postAction', async () => {\n        await 0;\n        calls.push('after');\n      })\n      .action(() => calls.push('action'));\n    const result = program.parseAsync([], { from: 'user' });\n    expect(calls).toEqual(['action']);\n    await result;\n    expect(calls).toEqual(['action', 'after']);\n  });\n\n  test('when async action then async from action', async () => {\n    const calls = [];\n    const program = new commander.Command();\n    program\n      .hook('preAction', () => calls.push('before'))\n      .hook('postAction', () => calls.push('after'))\n      .action(async () => {\n        await 0;\n        calls.push('action');\n      });\n    const result = program.parseAsync([], { from: 'user' });\n    expect(calls).toEqual(['before']);\n    await result;\n    expect(calls).toEqual(['before', 'action', 'after']);\n  });\n\n  test('when async first preAction then async from first preAction', async () => {\n    const calls = [];\n    const program = new commander.Command();\n    program\n      .hook('preAction', async () => {\n        await 0;\n        calls.push('1');\n      })\n      .hook('preAction', () => calls.push('2'))\n      .action(() => calls.push('action'));\n    const result = program.parseAsync([], { from: 'user' });\n    expect(calls).toEqual([]);\n    await result;\n    expect(calls).toEqual(['1', '2', 'action']);\n  });\n\n  test('when async second preAction then async from second preAction', async () => {\n    const calls = [];\n    const program = new commander.Command();\n    program\n      .hook('preAction', () => calls.push('1'))\n      .hook('preAction', async () => {\n        await 0;\n        calls.push('2');\n      })\n      .action(() => calls.push('action'));\n    const result = program.parseAsync([], { from: 'user' });\n    expect(calls).toEqual(['1']);\n    await result;\n    expect(calls).toEqual(['1', '2', 'action']);\n  });\n\n  test('when async hook everything then hooks called nested', async () => {\n    const calls = [];\n    const program = new commander.Command();\n    program\n      .hook('preAction', async () => {\n        await 0;\n        calls.push('pb1');\n      })\n      .hook('postAction', async () => {\n        await 0;\n        calls.push('pa1');\n      });\n    program\n      .hook('preAction', async () => {\n        await 0;\n        calls.push('pb2');\n      })\n      .hook('postAction', async () => {\n        await 0;\n        calls.push('pa2');\n      });\n    program\n      .command('sub')\n      .hook('preAction', async () => {\n        await 0;\n        calls.push('sb');\n      })\n      .hook('postAction', async () => {\n        await 0;\n        calls.push('sa');\n      })\n      .action(async () => {\n        await 0;\n        calls.push('action');\n      });\n    const result = program.parseAsync(['sub'], { from: 'user' });\n    expect(calls).toEqual([]);\n    await result;\n    expect(calls).toEqual(['pb1', 'pb2', 'sb', 'action', 'sa', 'pa2', 'pa1']);\n  });\n\n  test('preSubcommand hook should work', async () => {\n    const calls = [];\n    const program = new commander.Command();\n    program.hook('preSubcommand', async () => {\n      await 0;\n      calls.push(0);\n    });\n    program.command('sub').action(async () => {\n      await 1;\n      calls.push(1);\n    });\n    program.action(async () => {\n      await 2;\n      calls.push(2);\n    });\n    const result = program.parseAsync(['sub'], { from: 'user' });\n    expect(calls).toEqual([]);\n    await result;\n    expect(calls).toEqual([0, 1]);\n  });\n  test('preSubcommand hook should effective for direct subcommands', async () => {\n    const calls = [];\n    const program = new commander.Command();\n    program.hook('preSubcommand', async (thisCommand, subCommand) => {\n      await 'preSubcommand';\n      calls.push('preSubcommand');\n      calls.push(subCommand.name());\n    });\n    program\n      .command('first')\n      .action(async () => {\n        await 'first';\n        calls.push('first');\n      })\n      .command('second')\n      .action(async () => {\n        await 'second';\n        calls.push('second');\n      })\n      .command('third')\n      .action(async () => {\n        await 'third';\n        calls.push('third');\n      });\n    program.action(async () => {\n      await 2;\n      calls.push(2);\n    });\n    const result = program.parseAsync(['first', 'second', 'third'], {\n      from: 'user',\n    });\n    expect(calls).toEqual([]);\n    await result;\n    expect(calls).toEqual(['preSubcommand', 'first', 'third']);\n  });\n});\n"
  },
  {
    "path": "tests/command.name.test.js",
    "content": "const path = require('path');\nconst commander = require('../');\n\ntest('when construct with name then name is set', () => {\n  const program = new commander.Command('foo');\n  expect(program.name()).toBe('foo');\n});\n\ntest('when set program name and parse then name is as assigned', () => {\n  const program = new commander.Command();\n  program.name('custom');\n  program.parse(['node', 'test']);\n  expect(program.name()).toBe('custom');\n});\n\ntest('when program name not set and parse with script argument then plain name is found from script name', () => {\n  const program = new commander.Command();\n  program.parse(['node', path.resolve(process.cwd(), 'script.js')], {\n    from: 'node',\n  });\n  expect(program.name()).toBe('script');\n});\n\ntest('when command name not set and no script argument in parse then name is program', () => {\n  const program = new commander.Command();\n  program.parse([], { from: 'user' });\n  expect(program.name()).toBe('program');\n});\n\ntest('when add command then command is named', () => {\n  const program = new commander.Command();\n  const subcommand = program.command('mycommand <file>');\n  expect(subcommand.name()).toBe('mycommand');\n});\n\ntest('when set program name then name appears in help', () => {\n  const program = new commander.Command();\n  program.name('custom-name');\n  const helpInformation = program.helpInformation();\n  expect(helpInformation).toMatch(/^Usage: custom-name/);\n});\n\ntest('when pass path to nameFromFilename then name is plain name', () => {\n  const program = new commander.Command();\n  program.nameFromFilename(path.resolve(process.cwd(), 'foo.js'));\n  expect(program.name()).toBe('foo');\n});\n\ntest('when pass __filename to nameFromFilename then name is plain name of this file', () => {\n  const program = new commander.Command();\n  program.nameFromFilename(__filename);\n  expect(program.name()).toBe('command.name.test');\n});\n"
  },
  {
    "path": "tests/command.nested.test.js",
    "content": "const commander = require('../');\n\ntest('when call nested subcommand then runs', () => {\n  const program = new commander.Command();\n  const leafAction = jest.fn();\n  program.command('sub1').command('sub2').action(leafAction);\n  program.parse('node test.js sub1 sub2'.split(' '));\n  expect(leafAction).toHaveBeenCalled();\n});\n"
  },
  {
    "path": "tests/command.onCommand.test.js",
    "content": "const commander = require('../');\n\n// The action handler used to be implemented using command events and listeners.\n// Now, this is mostly just for backwards compatibility.\n\ndescribe(\".command('*')\", () => {\n  test('when action handler for subcommand then emit command:subcommand', () => {\n    const mockListener = jest.fn();\n    const program = new commander.Command();\n    program.command('sub').action(() => {});\n    program.on('command:sub', mockListener);\n    program.parse(['sub'], { from: 'user' });\n    expect(mockListener).toHaveBeenCalled();\n  });\n\n  test('when no action handler for subcommand then still emit command:subcommand', () => {\n    const mockListener = jest.fn();\n    const program = new commander.Command();\n    program.command('sub');\n    program.on('command:sub', mockListener);\n    program.parse(['sub'], { from: 'user' });\n    expect(mockListener).toHaveBeenCalled();\n  });\n\n  test('when subcommand has argument then emit command:subcommand with argument', () => {\n    const mockListener = jest.fn();\n    const program = new commander.Command();\n    program.command('sub <file>').action(() => {});\n    program.on('command:sub', mockListener);\n    program.parse(['sub', 'file'], { from: 'user' });\n    expect(mockListener).toHaveBeenCalledWith(['file'], []);\n  });\n});\n"
  },
  {
    "path": "tests/command.option-misuse.test.js",
    "content": "const { Command, Option } = require('../');\n\n// It is a reasonable and easy mistake to pass Option to .option(). Detect this\n// and offer advice.\n\nconst expectedMessage =\n  'To add an Option object use addOption() instead of option() or requiredOption()';\n\ntest('when pass Option to .option() then throw', () => {\n  const program = new Command();\n\n  expect(() => {\n    program.option(new Option('-d, debug'));\n  }).toThrow(expectedMessage);\n});\n\ntest('when pass Option to .requiredOption() then throw', () => {\n  const program = new Command();\n\n  expect(() => {\n    program.requiredOption(new Option('-d, debug'));\n  }).toThrow(expectedMessage);\n});\n"
  },
  {
    "path": "tests/command.parse.test.js",
    "content": "const commander = require('../');\n\n// Testing some Electron conventions but not directly using Electron to avoid overheads.\n// https://github.com/electron/electron/issues/4690#issuecomment-217435222\n// https://www.electronjs.org/docs/api/process#processdefaultapp-readonly\n\n// (If mutating process.argv and process.execArgv causes problems, could add utility\n// functions to get them and then mock the functions for tests.)\n\ndescribe('.parse() args from', () => {\n  test('when no args then use process.argv and app/script/args', () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    const hold = process.argv;\n    process.argv = 'node script.js user'.split(' ');\n    program.parse();\n    process.argv = hold;\n    expect(program.args).toEqual(['user']);\n  });\n\n  test('when no args and electron properties and not default app then use process.argv and app/args', () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    const holdArgv = process.argv;\n    process.versions.electron = '1.2.3';\n    process.argv = 'node user'.split(' ');\n    program.parse();\n    delete process.versions.electron;\n    process.argv = holdArgv;\n    expect(program.args).toEqual(['user']);\n  });\n\n  test('when args then app/script/args', () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    program.parse('node script.js user'.split(' '));\n    expect(program.args).toEqual(['user']);\n  });\n\n  test('when args from \"node\" then app/script/args', () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    program.parse('node script.js user'.split(' '), { from: 'node' });\n    expect(program.args).toEqual(['user']);\n  });\n\n  test('when args from \"electron\" and not default app then app/args', () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    const hold = process.defaultApp;\n    process.defaultApp = undefined;\n    program.parse('customApp user'.split(' '), { from: 'electron' });\n    process.defaultApp = hold;\n    expect(program.args).toEqual(['user']);\n  });\n\n  test('when args from \"electron\" and default app then app/script/args', () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    const hold = process.defaultApp;\n    process.defaultApp = true;\n    program.parse('electron script user'.split(' '), { from: 'electron' });\n    process.defaultApp = hold;\n    expect(program.args).toEqual(['user']);\n  });\n\n  test('when args from \"user\" then args', () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    program.parse('user'.split(' '), { from: 'user' });\n    expect(program.args).toEqual(['user']);\n  });\n\n  test('when args from \"silly\" then throw', () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    expect(() => {\n      program.parse(['node', 'script.js'], { from: 'silly' });\n    }).toThrow();\n  });\n\n  test.each(['-e', '--eval', '-p', '--print'])(\n    'when node execArgv includes %s then app/args',\n    (flag) => {\n      const program = new commander.Command();\n      program.argument('[args...]');\n      const holdExecArgv = process.execArgv;\n      const holdArgv = process.argv;\n      process.argv = ['node', 'user-arg'];\n      process.execArgv = [flag, 'console.log(\"hello, world\")'];\n      program.parse();\n      process.argv = holdArgv;\n      process.execArgv = holdExecArgv;\n      expect(program.args).toEqual(['user-arg']);\n      process.execArgv = holdExecArgv;\n    },\n  );\n});\n\ndescribe('return type', () => {\n  test('when call .parse then returns program', () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    program.action(() => {});\n\n    const result = program.parse(['node', 'test']);\n    expect(result).toBe(program);\n  });\n\n  test('when await .parseAsync then returns program', async () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    program.action(() => {});\n\n    const result = await program.parseAsync(['node', 'test']);\n    expect(result).toBe(program);\n  });\n});\n\n// Easy mistake to make when writing unit tests\ntest('when parse strings instead of array then throw', () => {\n  const program = new commander.Command();\n  program.argument('[args...]');\n  expect(() => {\n    program.parse('node', 'test');\n  }).toThrow();\n});\n\ndescribe('parse parameter is treated as readonly, per TypeScript declaration', () => {\n  test('when parse called then parameter does not change', () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    program.option('--debug');\n    const original = ['node', '--debug', 'arg'];\n    const param = original.slice();\n    program.parse(param);\n    expect(param).toEqual(original);\n  });\n\n  test('when parse called and parsed args later changed then parameter does not change', () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    program.option('--debug');\n    const original = ['node', '--debug', 'arg'];\n    const param = original.slice();\n    program.parse(param);\n    program.args.length = 0;\n    program.rawArgs.length = 0;\n    expect(param).toEqual(original);\n  });\n\n  test('when parse called and param later changed then parsed args do not change', () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    program.option('--debug');\n    const param = ['node', '--debug', 'arg'];\n    program.parse(param);\n    const oldArgs = program.args.slice();\n    const oldRawArgs = program.rawArgs.slice();\n    param.length = 0;\n    expect(program.args).toEqual(oldArgs);\n    expect(program.rawArgs).toEqual(oldRawArgs);\n  });\n});\n\ndescribe('parseAsync parameter is treated as readonly, per TypeScript declaration', () => {\n  test('when parse called then parameter does not change', async () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    program.option('--debug');\n    const original = ['node', '--debug', 'arg'];\n    const param = original.slice();\n    await program.parseAsync(param);\n    expect(param).toEqual(original);\n  });\n\n  test('when parseAsync called and parsed args later changed then parameter does not change', async () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    program.option('--debug');\n    const original = ['node', '--debug', 'arg'];\n    const param = original.slice();\n    await program.parseAsync(param);\n    program.args.length = 0;\n    program.rawArgs.length = 0;\n    expect(param).toEqual(original);\n  });\n\n  test('when parseAsync called and param later changed then parsed args do not change', async () => {\n    const program = new commander.Command();\n    program.argument('[args...]');\n    program.option('--debug');\n    const param = ['node', '--debug', 'arg'];\n    await program.parseAsync(param);\n    const oldArgs = program.args.slice();\n    const oldRawArgs = program.rawArgs.slice();\n    param.length = 0;\n    expect(program.args).toEqual(oldArgs);\n    expect(program.rawArgs).toEqual(oldRawArgs);\n  });\n});\n\ndescribe('.parse() called multiple times', () => {\n  test('when use boolean options then option values reset', () => {\n    const program = new commander.Command().option('--black').option('--white');\n\n    program.parse(['--black'], { from: 'user' });\n    expect(program.opts()).toEqual({ black: true });\n\n    program.parse(['--white'], { from: 'user' });\n    expect(program.opts()).toEqual({ white: true });\n  });\n\n  test('when use options with option-argument then option values and sources reset', () => {\n    const program = new commander.Command()\n      .option('-f, --foo <value>')\n      .option('-b, --bar <value>');\n\n    program.parse(['--foo', 'FOO'], { from: 'user' });\n    expect(program.opts()).toEqual({ foo: 'FOO' });\n    expect(program.getOptionValueSource('foo')).toEqual('cli');\n    expect(program.getOptionValueSource('bar')).toBeUndefined();\n\n    program.parse(['--bar', 'BAR'], { from: 'user' });\n    expect(program.opts()).toEqual({ bar: 'BAR' });\n    expect(program.getOptionValueSource('foo')).toBeUndefined();\n    expect(program.getOptionValueSource('bar')).toEqual('cli');\n  });\n\n  test('when use options with option-argument and default then option values and sources reset', () => {\n    const program = new commander.Command()\n      .option('-f, --foo <value>', 'description', 'default-FOO')\n      .option('-b, --bar <value>', 'description', 'default-BAR');\n\n    program.parse(['--foo', 'FOO'], { from: 'user' });\n    expect(program.opts()).toEqual({ foo: 'FOO', bar: 'default-BAR' });\n    expect(program.getOptionValueSource('foo')).toEqual('cli');\n    expect(program.getOptionValueSource('bar')).toEqual('default');\n\n    program.parse(['--bar', 'BAR'], { from: 'user' });\n    expect(program.opts()).toEqual({ foo: 'default-FOO', bar: 'BAR' });\n    expect(program.getOptionValueSource('foo')).toEqual('default');\n    expect(program.getOptionValueSource('bar')).toEqual('cli');\n  });\n\n  test('when use negated options then option values reset', () => {\n    const program = new commander.Command()\n      .option('--no-foo')\n      .option('--no-bar');\n\n    program.parse(['--no-foo'], { from: 'user' });\n    expect(program.opts()).toEqual({ foo: false, bar: true });\n\n    program.parse(['--no-bar'], { from: 'user' });\n    expect(program.opts()).toEqual({ foo: true, bar: false });\n  });\n\n  test('when use variadic option then option values reset', () => {\n    const program = new commander.Command().option('--var <items...>');\n\n    program.parse(['--var', 'a', 'b'], { from: 'user' });\n    expect(program.opts()).toEqual({ var: ['a', 'b'] });\n\n    program.parse(['--var', 'c'], { from: 'user' });\n    expect(program.opts()).toEqual({ var: ['c'] });\n  });\n\n  test('when use collect example then option value resets', () => {\n    function collect(value, previous) {\n      return previous.concat([value]);\n    }\n    const program = new commander.Command();\n    program.option('-c, --collect <value>', 'repeatable value', collect, []);\n\n    program.parse(['-c', 'a', '-c', 'b'], { from: 'user' });\n    expect(program.opts()).toEqual({ collect: ['a', 'b'] });\n\n    program.parse(['-c', 'c'], { from: 'user' });\n    expect(program.opts()).toEqual({ collect: ['c'] });\n  });\n\n  test('when use increaseVerbosity example then option value resets', () => {\n    function increaseVerbosity(dummyValue, previous) {\n      return previous + 1;\n    }\n    const program = new commander.Command();\n    program.option(\n      '-v, --verbose',\n      'verbosity that can be increased',\n      increaseVerbosity,\n      0,\n    );\n\n    program.parse(['-vvv'], { from: 'user' });\n    expect(program.opts()).toEqual({ verbose: 3 });\n    program.parse(['-vv'], { from: 'user' });\n\n    expect(program.opts()).toEqual({ verbose: 2 });\n    program.parse([], { from: 'user' });\n    expect(program.opts()).toEqual({ verbose: 0 });\n  });\n\n  test('when use parse and parseAsync then option values reset', async () => {\n    const program = new commander.Command().option('--black').option('--white');\n\n    program.parse(['--black'], { from: 'user' });\n    expect(program.opts()).toEqual({ black: true });\n    await program.parseAsync(['--white'], { from: 'user' });\n    expect(program.opts()).toEqual({ white: true });\n  });\n\n  test('when call subcommand then option values reset (program and subcommand)', () => {\n    const program = new commander.Command().option('--black').option('--white');\n    const subcommand = program.command('sub').option('--red').option('--green');\n\n    program.parse(['--black', 'sub', '--red'], { from: 'user' });\n    expect(subcommand.optsWithGlobals()).toEqual({ black: true, red: true });\n\n    program.parse(['--white', 'sub', '--green'], { from: 'user' });\n    expect(subcommand.optsWithGlobals()).toEqual({ white: true, green: true });\n  });\n\n  test('when call different subcommand then no reset because lazy', () => {\n    // This is not a required behaviour, but is the intended behaviour.\n    const program = new commander.Command();\n    const sub1 = program.command('sub1').option('--red');\n    const sub2 = program.command('sub2').option('--green');\n\n    program.parse(['sub1', '--red'], { from: 'user' });\n    expect(sub1.opts()).toEqual({ red: true });\n    expect(sub2.opts()).toEqual({});\n\n    program.parse(['sub2', '--green'], { from: 'user' });\n    expect(sub1.opts()).toEqual({ red: true });\n    expect(sub2.opts()).toEqual({ green: true });\n  });\n\n  test('when parse with different implied program name then name changes', () => {\n    const program = new commander.Command();\n\n    program.parse(['node', 'script1.js']);\n    expect(program.name()).toEqual('script1');\n\n    program.parse(['electron', 'script2.js']);\n    expect(program.name()).toEqual('script2');\n  });\n\n  test('when parse with different arguments then args change', () => {\n    // weak test, would work without store/reset!\n    const program = new commander.Command()\n      .argument('<first>')\n      .argument('[second]');\n\n    program.parse(['one', 'two'], { from: 'user' });\n    expect(program.args).toEqual(['one', 'two']);\n\n    program.parse(['alpha'], { from: 'user' });\n    expect(program.args).toEqual(['alpha']);\n  });\n\n  test('when parse with different arguments then rawArgs change', () => {\n    // weak test, would work without store/reset!\n    const program = new commander.Command()\n      .argument('<first>')\n      .option('--white')\n      .option('--black');\n\n    program.parse(['--white', 'one'], { from: 'user' });\n    expect(program.rawArgs).toEqual(['--white', 'one']);\n\n    program.parse(['--black', 'two'], { from: 'user' });\n    expect(program.rawArgs).toEqual(['--black', 'two']);\n  });\n\n  test('when parse with different arguments then processedArgs change', () => {\n    // weak test, would work without store/reset!\n    const program = new commander.Command().argument(\n      '<first>',\n      'first arg',\n      parseFloat,\n    );\n\n    program.parse([123], { from: 'user' });\n    expect(program.processedArgs).toEqual([123]);\n\n    program.parse([456], { from: 'user' });\n    expect(program.processedArgs).toEqual([456]);\n  });\n\n  test('when parse subcommand then reset state before preSubcommand hook called', () => {\n    let hookCalled = false;\n    const program = new commander.Command().hook(\n      'preSubcommand',\n      (thisCommand, subcommand) => {\n        hookCalled = true;\n        expect(subcommand.opts()).toEqual({});\n      },\n    );\n    const subcommand = program.command('sub').option('--red').option('--green');\n\n    hookCalled = false;\n    program.parse(['sub', '--red'], { from: 'user' });\n    expect(hookCalled).toBe(true);\n    expect(subcommand.opts()).toEqual({ red: true });\n\n    hookCalled = false;\n    program.parse(['sub', '--green'], { from: 'user' });\n    expect(hookCalled).toBe(true);\n    expect(subcommand.opts()).toEqual({ green: true });\n  });\n\n  test('when using storeOptionsAsProperties then throw on second parse', () => {\n    const program = new commander.Command().storeOptionsAsProperties();\n    program.parse();\n    expect(() => {\n      program.parse();\n    }).toThrow();\n  });\n});\n"
  },
  {
    "path": "tests/command.parseOptions.test.js",
    "content": "const childProcess = require('child_process');\nconst commander = require('../');\nconst path = require('path');\nconst util = require('util');\n\nconst execFileAsync = util.promisify(childProcess.execFile);\n\n// Combination of parse and parseOptions tests which are more about details\n// than high level behaviours which are tested elsewhere.\n\n// Tests created from reported bugs\ndescribe('regression tests', () => {\n  // https://github.com/tj/commander.js/issues/1032\n  function createProgram1032() {\n    const program = new commander.Command();\n    program\n      .command('doit [id]')\n      .option('--better', 'do it better')\n      .action((id, cmd) => {});\n    return program;\n  }\n\n  // https://github.com/tj/commander.js/issues/1032\n  test('when specify subcommand and argument then program.args not empty', () => {\n    const program = createProgram1032();\n    program.parse(['node', 'test.js', 'doit', 'myid']);\n    expect(program.args.length).toBeGreaterThan(0);\n  });\n\n  // https://github.com/tj/commander.js/issues/1032\n  test('when specify subcommand and option and argument then program.args not empty', () => {\n    const program = createProgram1032();\n    program.parse(['node', 'test.js', 'doit', '--better', 'myid']);\n    expect(program.args.length).toBeGreaterThan(0);\n  });\n\n  // https://github.com/tj/commander.js/issues/508\n  test('when arguments to executable include option flags then argument order preserved', async () => {\n    const pm = path.join(__dirname, 'fixtures/pm');\n    const { stdout } = await execFileAsync('node', [\n      pm,\n      'echo',\n      '1',\n      '2',\n      '--dry-run',\n      '3',\n      '4',\n      '5',\n      '6',\n    ]);\n    expect(stdout).toBe(\"[ '1', '2', '--dry-run', '3', '4', '5', '6' ]\\n\");\n  });\n});\n\ndescribe('parseOptions', () => {\n  function createProgram() {\n    const program = new commander.Command();\n    program\n      .option('--global-flag')\n      .option('--global-value <value>')\n      .command('sub [args...]')\n      .option('--sub-flag');\n    program.action(() => {});\n    return program;\n  }\n\n  // Subcommands are just another potential operand as far as parseOptions is concerned, so limited testing of subcommand as such.\n\n  test('when empty args then empty results', () => {\n    const program = createProgram();\n    const result = program.parseOptions([]);\n    expect(result).toEqual({ operands: [], unknown: [] });\n  });\n\n  test('when only operands then results has all operands', () => {\n    const program = createProgram();\n    const result = program.parseOptions('one two three'.split(' '));\n    expect(result).toEqual({ operands: ['one', 'two', 'three'], unknown: [] });\n  });\n\n  test('when subcommand and operand then results has subcommand and operand', () => {\n    const program = createProgram();\n    const result = program.parseOptions('sub one'.split(' '));\n    expect(result).toEqual({ operands: ['sub', 'one'], unknown: [] });\n  });\n\n  test('when program has flag then option removed', () => {\n    const program = createProgram();\n    const result = program.parseOptions('--global-flag'.split(' '));\n    expect(result).toEqual({ operands: [], unknown: [] });\n  });\n\n  test('when program has option with value then option removed', () => {\n    const program = createProgram();\n    const result = program.parseOptions('--global-value foo'.split(' '));\n    expect(result).toEqual({ operands: [], unknown: [] });\n  });\n\n  test('when program has flag before operand then option removed', () => {\n    const program = createProgram();\n    const result = program.parseOptions('--global-flag arg'.split(' '));\n    expect(result).toEqual({ operands: ['arg'], unknown: [] });\n  });\n\n  test('when program has flag after operand then option removed', () => {\n    const program = createProgram();\n    const result = program.parseOptions('arg --global-flag'.split(' '));\n    expect(result).toEqual({ operands: ['arg'], unknown: [] });\n  });\n\n  test('when program has flag after subcommand then option removed', () => {\n    const program = createProgram();\n    const result = program.parseOptions('sub --global-flag'.split(' '));\n    expect(result).toEqual({ operands: ['sub'], unknown: [] });\n  });\n\n  test('when program has unknown option then option returned in unknown', () => {\n    const program = createProgram();\n    const result = program.parseOptions('--unknown'.split(' '));\n    expect(result).toEqual({ operands: [], unknown: ['--unknown'] });\n  });\n\n  test('when program has unknown option before operands then all unknown in same order', () => {\n    const program = createProgram();\n    const result = program.parseOptions('--unknown arg'.split(' '));\n    expect(result).toEqual({ operands: [], unknown: ['--unknown', 'arg'] });\n  });\n\n  test('when program has unknown option after operand then option returned in unknown', () => {\n    const program = createProgram();\n    const result = program.parseOptions('arg --unknown'.split(' '));\n    expect(result).toEqual({ operands: ['arg'], unknown: ['--unknown'] });\n  });\n\n  test('when program has flag after unknown option then flag removed', () => {\n    const program = createProgram();\n    const result = program.parseOptions('--unknown --global-flag'.split(' '));\n    expect(result).toEqual({ operands: [], unknown: ['--unknown'] });\n  });\n\n  test('when subcommand has flag then flag returned as unknown', () => {\n    const program = createProgram();\n    const result = program.parseOptions('sub --sub-flag'.split(' '));\n    expect(result).toEqual({ operands: ['sub'], unknown: ['--sub-flag'] });\n  });\n\n  test('when program has literal before known flag then option returned as operand', () => {\n    const program = createProgram();\n    const result = program.parseOptions('-- --global-flag'.split(' '));\n    expect(result).toEqual({ operands: ['--global-flag'], unknown: [] });\n  });\n\n  test('when program has literal before unknown option then option returned as operand', () => {\n    const program = createProgram();\n    const result = program.parseOptions('-- --unknown uuu'.split(' '));\n    expect(result).toEqual({ operands: ['--unknown', 'uuu'], unknown: [] });\n  });\n\n  test('when program has literal after unknown option then literal preserved too', () => {\n    const program = createProgram();\n    const result = program.parseOptions('--unknown1 -- --unknown2'.split(' '));\n    expect(result).toEqual({\n      operands: [],\n      unknown: ['--unknown1', '--', '--unknown2'],\n    });\n  });\n});\n\n// parse now sets program.args to the result of parseOptions (operands + unknown). Some limited testing.\ndescribe('parse and program.args', () => {\n  test('when program has known flag and operand then option removed and operand returned', () => {\n    const program = new commander.Command();\n    program.option('--global-flag').argument('[arg...]');\n    program.parse('node test.js --global-flag arg'.split(' '));\n    expect(program.args).toEqual(['arg']);\n  });\n\n  test('when program has mixed arguments then known options removed and rest returned in same order', () => {\n    const program = new commander.Command();\n    program\n      .allowUnknownOption()\n      .option('--global-flag')\n      .option('--global-value <value>')\n      .argument('[arg...]');\n    program.parse(\n      'node test.js aaa --global-flag bbb --unknown ccc --global-value value'.split(\n        ' ',\n      ),\n    );\n    expect(program.args).toEqual(['aaa', 'bbb', '--unknown', 'ccc']);\n  });\n\n  test('when subcommand has mixed arguments then program flags removed and rest returned in same order', () => {\n    const program = new commander.Command();\n    program\n      .option('--global-flag')\n      .option('--global-value <value>')\n      .command('sub [args...]')\n      .option('--sub-flag');\n    program.parse(\n      'node test.js --global-flag sub --sub-flag arg --global-value value'.split(\n        ' ',\n      ),\n    );\n    expect(program.args).toEqual(['sub', '--sub-flag', 'arg']);\n  });\n});\n\n// Utility Conventions: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_01\n//\n// 12.1 Utility Argument Syntax\n// 2. Option-arguments are shown separated from their options by <blank> characters, except when the option-argument is\n// enclosed in the '[' and ']' notation to indicate that it is optional. This reflects the situation in which an\n// optional option-argument (if present) is included within the same argument string as the option; for a mandatory option-argument,\n// it is the next argument. The Utility Syntax Guidelines in Utility Syntax Guidelines require that the option be a separate argument\n// from its option-argument and that option-arguments not be optional, but there are some exceptions in POSIX.1-2017 to ensure\n// continued operation of historical applications:\n//\n// a. If the SYNOPSIS of a standard utility shows an option with a mandatory option-argument (as with [ -c option_argument] in the example),\n//    a conforming application shall use separate arguments for that option and its option-argument. However, a conforming implementation shall\n//    also permit applications to specify the option and option-argument in the same argument string without intervening <blank> characters.\n//\n// b. If the SYNOPSIS shows an optional option-argument (as with [ -f[ option_argument]] in the example), a conforming application\n//    shall place any option-argument for that option directly adjacent to the option in the same argument string, without intervening\n//    <blank> characters. If the utility receives an argument containing only the option, it shall behave as specified in its description\n//    for an omitted option-argument; it shall not treat the next argument (if any) as the option-argument for that option.\n//\n// 12.2 Utility Syntax Guidelines, Guideline 5:\n// One or more options without option-arguments, followed by at most one option that takes an option-argument, should be accepted when\n// grouped behind one '-' delimiter.\n\n// Commander conformance:\n// - allows separate argument for required option-argument\n// - allows value in same argument for short flag with required option-argument\n// - non-conforming: allows separate argument for optional option-argument if it does not start with '-'\n// - allows value in same argument for short flag with optional option-argument\n// - allows short flags as per 12.2\n//\n// The focus in this file is testing the behaviours with known vs unknown options.\n// See options.values.test.js for more general testing of known options.\n\ndescribe('Utility Conventions', () => {\n  function createProgram() {\n    const program = new commander.Command();\n    program\n      .option('-a,--aaa')\n      .option('-b,--bbb')\n      .option('-c,--ccc <value>')\n      .option('-d,--ddd [value]');\n    program.action(() => {});\n    return program;\n  }\n\n  test('when program has combo known boolean short flags then arg removed', () => {\n    const program = createProgram();\n    const result = program.parseOptions(['-ab']);\n    expect(result).toEqual({ operands: [], unknown: [] });\n    expect(program.opts()).toEqual({ aaa: true, bbb: true });\n  });\n\n  test('when program has combo unknown short flags then arg preserved', () => {\n    const program = createProgram();\n    const result = program.parseOptions(['-pq']);\n    expect(result).toEqual({ operands: [], unknown: ['-pq'] });\n    expect(program.opts()).toEqual({});\n  });\n\n  test('when program has combo known short option and required value then arg removed', () => {\n    const program = createProgram();\n    const result = program.parseOptions(['-cvalue']);\n    expect(result).toEqual({ operands: [], unknown: [] });\n    expect(program.opts()).toEqual({ ccc: 'value' });\n  });\n\n  test('when program has combo known short option and optional value then arg removed', () => {\n    const program = createProgram();\n    const result = program.parseOptions(['-dvalue']);\n    expect(result).toEqual({ operands: [], unknown: [] });\n    expect(program.opts()).toEqual({ ddd: 'value' });\n  });\n\n  test('when program has known combo short boolean flags and required value then arg removed', () => {\n    const program = createProgram();\n    const result = program.parseOptions(['-abcvalue']);\n    expect(result).toEqual({ operands: [], unknown: [] });\n    expect(program.opts()).toEqual({ aaa: true, bbb: true, ccc: 'value' });\n  });\n\n  test('when program has known combo short boolean flags and optional value then arg removed', () => {\n    const program = createProgram();\n    const result = program.parseOptions(['-abdvalue']);\n    expect(result).toEqual({ operands: [], unknown: [] });\n    expect(program.opts()).toEqual({ aaa: true, bbb: true, ddd: 'value' });\n  });\n\n  test('when program has known long flag=value then arg removed', () => {\n    const program = createProgram();\n    const result = program.parseOptions(['--ccc=value']);\n    expect(result).toEqual({ operands: [], unknown: [] });\n    expect(program.opts()).toEqual({ ccc: 'value' });\n  });\n\n  test('when program has unknown long flag=value then arg preserved', () => {\n    const program = createProgram();\n    const result = program.parseOptions(['--rrr=value']);\n    expect(result).toEqual({ operands: [], unknown: ['--rrr=value'] });\n    expect(program.opts()).toEqual({});\n  });\n\n  test('when program has combo optional and combineFlagAndOptionalValue() then treat as value', () => {\n    const program = createProgram();\n    program.combineFlagAndOptionalValue();\n    program.parseOptions(['-db']);\n    expect(program.opts()).toEqual({ ddd: 'b' });\n  });\n\n  test('when program has combo optional and combineFlagAndOptionalValue(true) then treat as value', () => {\n    const program = createProgram();\n    program.combineFlagAndOptionalValue(true);\n    program.parseOptions(['-db']);\n    expect(program.opts()).toEqual({ ddd: 'b' });\n  });\n\n  test('when program has combo optional and combineFlagAndOptionalValue(false) then treat as boolean', () => {\n    const program = createProgram();\n    program.combineFlagAndOptionalValue(false);\n    program.parseOptions(['-db']);\n    expect(program.opts()).toEqual({ ddd: true, bbb: true });\n  });\n});\n"
  },
  {
    "path": "tests/command.positionalOptions.test.js",
    "content": "const commander = require('../');\n\n// The changes to parsing for positional options are subtle, and took extra care to work with\n// implicit help and default commands. Lots of tests.\n\ndescribe('program with passThrough', () => {\n  function makeProgram() {\n    const program = new commander.Command();\n    program.passThroughOptions();\n    program.option('-d, --debug').argument('<args...>');\n    return program;\n  }\n\n  test('when option before command-argument then option parsed', () => {\n    const program = makeProgram();\n    program.parse(['--debug', 'arg'], { from: 'user' });\n    expect(program.args).toEqual(['arg']);\n    expect(program.opts().debug).toBe(true);\n  });\n\n  test('when known option after command-argument then option passed through', () => {\n    const program = makeProgram();\n    program.parse(['arg', '--debug'], { from: 'user' });\n    expect(program.args).toEqual(['arg', '--debug']);\n    expect(program.opts().debug).toBeUndefined();\n  });\n\n  test('when unknown option after command-argument then option passed through', () => {\n    const program = makeProgram();\n    program.parse(['arg', '--pass'], { from: 'user' });\n    expect(program.args).toEqual(['arg', '--pass']);\n  });\n\n  test('when action handler and unknown option after command-argument then option passed through', () => {\n    const program = makeProgram();\n    const mockAction = jest.fn();\n    program.action(mockAction);\n    program.parse(['arg', '--pass'], { from: 'user' });\n    expect(mockAction).toHaveBeenCalledWith(\n      ['arg', '--pass'],\n      program.opts(),\n      program,\n    );\n  });\n\n  test('when help option (without command-argument) then help called', () => {\n    const program = makeProgram();\n    const mockHelp = jest.fn(() => '');\n\n    program.exitOverride().configureHelp({ formatHelp: mockHelp });\n    try {\n      program.parse(['--help'], { from: 'user' });\n    } catch (err) {\n      /* empty */\n    }\n    expect(mockHelp).toHaveBeenCalled();\n  });\n\n  test('when help option after command-argument then option passed through', () => {\n    const program = makeProgram();\n    program.parse(['arg', '--help'], { from: 'user' });\n    expect(program.args).toEqual(['arg', '--help']);\n  });\n\n  test('when version option after command-argument then option passed through', () => {\n    const program = makeProgram();\n    program.version('1.2.3');\n    program.parse(['arg', '--version'], { from: 'user' });\n    expect(program.args).toEqual(['arg', '--version']);\n  });\n});\n\n// -----------------------------------------------------------\n\ndescribe('program with positionalOptions and subcommand', () => {\n  function makeProgram() {\n    const program = new commander.Command();\n    program\n      .enablePositionalOptions()\n      .option('-s, --shared <value>')\n      .argument('<args...>');\n    const sub = program\n      .command('sub')\n      .argument('[arg]')\n      .option('-s, --shared <value>')\n      .action(() => {}); // Not used, but normal to have action handler on subcommand.\n    return { program, sub };\n  }\n\n  test('when global option before subcommand then global option parsed', () => {\n    const { program } = makeProgram();\n    program.parse(['--shared', 'program', 'sub'], { from: 'user' });\n    expect(program.opts().shared).toEqual('program');\n  });\n\n  test('when shared option after subcommand then parsed by subcommand', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['sub', '--shared', 'local'], { from: 'user' });\n    expect(sub.opts().shared).toEqual('local');\n    expect(program.opts().shared).toBeUndefined();\n  });\n\n  test('when shared option after subcommand argument then parsed by subcommand', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['sub', 'arg', '--shared', 'local'], { from: 'user' });\n    expect(sub.opts().shared).toEqual('local');\n    expect(sub.args).toEqual(['arg']);\n    expect(program.opts().shared).toBeUndefined();\n  });\n\n  test('when shared option before and after subcommand then both parsed', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['--shared', 'program', 'sub', '--shared', 'local'], {\n      from: 'user',\n    });\n    expect(program.opts().shared).toEqual('program');\n    expect(sub.opts().shared).toEqual('local');\n  });\n\n  test.each([\n    [[], 1, 0],\n    [['sub'], 0, 0],\n    [['--help'], 1, 0],\n    [['sub', '--help'], 0, 1],\n    [['sub', 'foo', '--help'], 0, 1],\n    [['help'], 1, 0],\n    [['help', 'sub'], 0, 1],\n  ])(\n    'help: when user args %p then program/sub help called %p/%p',\n    (userArgs, expectProgramHelpCount, expectSubHelpCount) => {\n      const { program, sub } = makeProgram();\n      const mockProgramHelp = jest.fn();\n      program.exitOverride().configureHelp({ formatHelp: mockProgramHelp });\n      const mockSubHelp = jest.fn();\n      sub.exitOverride().configureHelp({ formatHelp: mockSubHelp });\n\n      try {\n        program.parse(userArgs, { from: 'user' });\n      } catch (err) {\n        /* empty */\n      }\n      expect(mockProgramHelp).toHaveBeenCalledTimes(expectProgramHelpCount);\n      expect(mockSubHelp).toHaveBeenCalledTimes(expectSubHelpCount);\n    },\n  );\n});\n\n// ---------------------------------------------------------------\n\ndescribe('program with positionalOptions and default subcommand (called sub)', () => {\n  function makeProgram() {\n    const program = new commander.Command();\n    program\n      .enablePositionalOptions()\n      .option('-s, --shared')\n      .option('-g, --global')\n      .argument('<args...>');\n    const sub = program\n      .command('sub', { isDefault: true })\n      .argument('[args...]')\n      .option('-s, --shared')\n      .option('-d, --default')\n      .action(() => {}); // Not used, but normal to have action handler on subcommand.\n    program.command('another'); // Not used, but normal to have more than one subcommand if have a default.\n    return { program, sub };\n  }\n\n  test('when program option before sub option then program option read by program', () => {\n    const { program } = makeProgram();\n    program.parse(['--global', '--default'], { from: 'user' });\n    expect(program.opts().global).toBe(true);\n  });\n\n  test('when program option before sub option then sub option read by sub', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['--global', '--default'], { from: 'user' });\n    expect(sub.opts().default).toBe(true);\n  });\n\n  test('when shared option before sub argument then option read by program', () => {\n    const { program } = makeProgram();\n    program.parse(['--shared', 'foo'], { from: 'user' });\n    expect(program.opts().shared).toBe(true);\n  });\n\n  test('when shared option after sub argument then option read by sub', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['foo', '--shared'], { from: 'user' });\n    expect(sub.opts().shared).toBe(true);\n  });\n\n  test.each([\n    [[], 0, 0],\n    [['--help'], 1, 0],\n    [['help'], 1, 0],\n  ])(\n    'help: when user args %p then program/sub help called %p/%p',\n    (userArgs, expectProgramHelpCount, expectSubHelpCount) => {\n      const { program, sub } = makeProgram();\n      const mockProgramHelp = jest.fn();\n      program.exitOverride().configureHelp({ formatHelp: mockProgramHelp });\n      const mockSubHelp = jest.fn();\n      sub.exitOverride().configureHelp({ formatHelp: mockSubHelp });\n\n      try {\n        program.parse(userArgs, { from: 'user' });\n      } catch (err) {\n        /* empty */\n      }\n      expect(mockProgramHelp).toHaveBeenCalledTimes(expectProgramHelpCount);\n      expect(mockSubHelp).toHaveBeenCalledTimes(expectSubHelpCount);\n    },\n  );\n});\n\n// ------------------------------------------------------------------------------\n\ndescribe('subcommand with passThrough', () => {\n  function makeProgram() {\n    const program = new commander.Command();\n    program\n      .enablePositionalOptions()\n      .option('-s, --shared <value>')\n      .argument('<args...>');\n    const sub = program\n      .command('sub')\n      .passThroughOptions()\n      .argument('[args...]')\n      .option('-s, --shared <value>')\n      .option('-d, --debug')\n      .action(() => {}); // Not used, but normal to have action handler on subcommand.\n    return { program, sub };\n  }\n\n  test('when option before command-argument then option parsed', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['sub', '--debug', 'arg'], { from: 'user' });\n    expect(sub.args).toEqual(['arg']);\n    expect(sub.opts().debug).toBe(true);\n  });\n\n  test('when known option after command-argument then option passed through', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['sub', 'arg', '--debug'], { from: 'user' });\n    expect(sub.args).toEqual(['arg', '--debug']);\n    expect(sub.opts().debug).toBeUndefined();\n  });\n\n  test('when unknown option after command-argument then option passed through', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['sub', 'arg', '--pass'], { from: 'user' });\n    expect(sub.args).toEqual(['arg', '--pass']);\n  });\n\n  test('when action handler and unknown option after command-argument then option passed through', () => {\n    const { program, sub } = makeProgram();\n    const mockAction = jest.fn();\n    sub.action(mockAction);\n    program.parse(['sub', 'arg', '--pass'], { from: 'user' });\n    expect(mockAction).toHaveBeenCalledWith(['arg', '--pass'], sub.opts(), sub);\n  });\n\n  test('when help option after command-argument then option passed through', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['sub', 'arg', '--help'], { from: 'user' });\n    expect(sub.args).toEqual(['arg', '--help']);\n  });\n\n  test('when version option after command-argument then option passed through', () => {\n    const { program, sub } = makeProgram();\n    program.version('1.2.3');\n    program.parse(['sub', 'arg', '--version'], { from: 'user' });\n    expect(sub.args).toEqual(['arg', '--version']);\n  });\n\n  test('when shared option before sub and after sub and after sub parameter then all three parsed', () => {\n    const { program, sub } = makeProgram();\n    program.parse(\n      ['--shared=global', 'sub', '--shared=local', 'arg', '--shared'],\n      { from: 'user' },\n    );\n    expect(program.opts().shared).toEqual('global');\n    expect(sub.opts().shared).toEqual('local');\n    expect(sub.args).toEqual(['arg', '--shared']);\n  });\n});\n\n// ------------------------------------------------------------------------------\n\ndescribe('default command with passThrough', () => {\n  function makeProgram() {\n    const program = new commander.Command();\n    program.enablePositionalOptions();\n    const sub = program\n      .command('sub', { isDefault: true })\n      .passThroughOptions()\n      .argument('[args...]')\n      .option('-d, --debug')\n      .action(() => {}); // Not used, but normal to have action handler on subcommand.\n    return { program, sub };\n  }\n\n  test('when option before command-argument then option parsed', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['--debug', 'arg'], { from: 'user' });\n    expect(sub.args).toEqual(['arg']);\n    expect(sub.opts().debug).toBe(true);\n  });\n\n  test('when known option after command-argument then option passed through', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['arg', '--debug'], { from: 'user' });\n    expect(sub.args).toEqual(['arg', '--debug']);\n    expect(sub.opts().debug).toBeUndefined();\n  });\n\n  test('when unknown option after command-argument then option passed through', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['arg', '--pass'], { from: 'user' });\n    expect(sub.args).toEqual(['arg', '--pass']);\n  });\n\n  test('when action handler and unknown option after command-argument then option passed through', () => {\n    const { program, sub } = makeProgram();\n    const mockAction = jest.fn();\n    sub.action(mockAction);\n    program.parse(['arg', '--pass'], { from: 'user' });\n    expect(mockAction).toHaveBeenCalledWith(['arg', '--pass'], sub.opts(), sub);\n  });\n});\n\n// ------------------------------------------------------------------------------\n\ndescribe('program with action handler and positionalOptions and subcommand', () => {\n  function makeProgram() {\n    const program = new commander.Command();\n    program\n      .enablePositionalOptions()\n      .option('-g, --global')\n      .argument('<args...>')\n      .action(() => {});\n    const sub = program\n      .command('sub')\n      .argument('[arg]')\n      .action(() => {});\n    return { program, sub };\n  }\n\n  test('when global option before parameter then global option parsed', () => {\n    const { program } = makeProgram();\n    program.parse(['--global', 'foo'], { from: 'user' });\n    expect(program.opts().global).toBe(true);\n  });\n\n  test('when global option after parameter then global option parsed', () => {\n    const { program } = makeProgram();\n    program.parse(['foo', '--global'], { from: 'user' });\n    expect(program.opts().global).toBe(true);\n  });\n\n  test('when global option after parameter with same name as subcommand then global option parsed', () => {\n    const { program } = makeProgram();\n    program.parse(['foo', 'sub', '--global'], { from: 'user' });\n    expect(program.opts().global).toBe(true);\n  });\n});\n\n// ------------------------------------------------------------------------------\n\ndescribe('broken passThrough', () => {\n  test('when program not positional and turn on passThroughOptions in subcommand then error', () => {\n    const program = new commander.Command();\n    const sub = program.command('sub');\n\n    expect(() => {\n      sub.passThroughOptions();\n    }).toThrow();\n  });\n\n  test('when program not positional and add subcommand with passThroughOptions then error', () => {\n    const program = new commander.Command();\n    const sub = new commander.Command('sub').passThroughOptions();\n\n    expect(() => {\n      program.addCommand(sub);\n    }).toThrow();\n  });\n});\n\n// ------------------------------------------------------------------------------\n\ndescribe('program with action handler and passThrough and subcommand', () => {\n  function makeProgram() {\n    const program = new commander.Command();\n    program\n      .passThroughOptions()\n      .option('-g, --global')\n      .argument('<args...>')\n      .action(() => {});\n    const sub = program\n      .command('sub')\n      .argument('[arg]')\n      .option('-g, --group')\n      .option('-d, --debug')\n      .action(() => {});\n    return { program, sub };\n  }\n\n  test('when global option before parameter then global option parsed', () => {\n    const { program } = makeProgram();\n    program.parse(['--global', 'foo'], { from: 'user' });\n    expect(program.opts().global).toBe(true);\n  });\n\n  test('when global option after parameter then passed through', () => {\n    const { program } = makeProgram();\n    program.parse(['foo', '--global'], { from: 'user' });\n    expect(program.args).toEqual(['foo', '--global']);\n  });\n\n  test('when subcommand option after subcommand then option parsed', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['sub', '--debug'], { from: 'user' });\n    expect(sub.opts().debug).toBe(true);\n  });\n\n  // This is somewhat of a side-effect of supporting previous test.\n  test('when shared option after subcommand then parsed by subcommand', () => {\n    const { program, sub } = makeProgram();\n    program.parse(['sub', '-g'], { from: 'user' });\n    expect(sub.opts().group).toBe(true);\n    expect(program.opts().global).toBeUndefined();\n  });\n});\n\n// ------------------------------------------------------------------------------\n\ndescribe('program with allowUnknownOption', () => {\n  test('when passThroughOptions and unknown option then arguments from unknown passed through', () => {\n    const program = new commander.Command();\n    program.passThroughOptions().allowUnknownOption().option('--debug');\n    program.argument('[args...]');\n\n    program.parse(['--unknown', '--debug'], { from: 'user' });\n    expect(program.args).toEqual(['--unknown', '--debug']);\n  });\n\n  test('when positionalOptions and unknown option then known options then known option parsed', () => {\n    const program = new commander.Command();\n    program.enablePositionalOptions().allowUnknownOption().option('--debug');\n    program.argument('[args...]');\n\n    program.parse(['--unknown', '--debug'], { from: 'user' });\n    expect(program.opts().debug).toBe(true);\n    expect(program.args).toEqual(['--unknown']);\n  });\n});\n\n// ------------------------------------------------------------------------------\n\ndescribe('passThroughOptions(xxx) and option after command-argument', () => {\n  function makeProgram() {\n    const program = new commander.Command();\n    program.option('-d, --debug').argument('<args...>');\n    return program;\n  }\n\n  test('when passThroughOptions() then option passed through', () => {\n    const program = makeProgram();\n    program.passThroughOptions();\n    program.parse(['foo', '--debug'], { from: 'user' });\n    expect(program.args).toEqual(['foo', '--debug']);\n  });\n\n  test('when passThroughOptions(true) then option passed through', () => {\n    const program = makeProgram();\n    program.passThroughOptions(true);\n    program.parse(['foo', '--debug'], { from: 'user' });\n    expect(program.args).toEqual(['foo', '--debug']);\n  });\n\n  test('when passThroughOptions(false) then option parsed', () => {\n    const program = makeProgram();\n    program.passThroughOptions(false);\n    program.parse(['foo', '--debug'], { from: 'user' });\n    expect(program.args).toEqual(['foo']);\n    expect(program.opts().debug).toEqual(true);\n  });\n});\n\n// ------------------------------------------------------------------------------\n\ndescribe('enablePositionalOptions(xxx) and shared option after subcommand', () => {\n  function makeProgram() {\n    const program = new commander.Command();\n    program.option('-d, --debug');\n    const sub = program.command('sub').option('-d, --debug');\n    return { program, sub };\n  }\n\n  test('when enablePositionalOptions() then option parsed by subcommand', () => {\n    const { program, sub } = makeProgram();\n    program.enablePositionalOptions();\n    program.parse(['sub', '--debug'], { from: 'user' });\n    expect(sub.opts().debug).toEqual(true);\n  });\n\n  test('when enablePositionalOptions(true) then option parsed by subcommand', () => {\n    const { program, sub } = makeProgram();\n    program.enablePositionalOptions(true);\n    program.parse(['sub', '--debug'], { from: 'user' });\n    expect(sub.opts().debug).toEqual(true);\n  });\n\n  test('when enablePositionalOptions(false) then option parsed by program', () => {\n    const { program, sub } = makeProgram();\n    program.enablePositionalOptions(false);\n    program.parse(['sub', '--debug'], { from: 'user' });\n    expect(sub.opts().debug).toBeUndefined();\n    expect(program.opts().debug).toEqual(true);\n  });\n});\n"
  },
  {
    "path": "tests/command.registerClash.test.js",
    "content": "const { Command } = require('../');\n\ntest('when command name conflicts with existing name then throw', () => {\n  expect(() => {\n    const program = new Command();\n    program.command('one');\n    program.command('one');\n  }).toThrow('cannot add command');\n});\n\ntest('when command name conflicts with existing alias then throw', () => {\n  expect(() => {\n    const program = new Command();\n    program.command('one').alias('1');\n    program.command('1');\n  }).toThrow('cannot add command');\n});\n\ntest('when command alias conflicts with existing name then throw', () => {\n  expect(() => {\n    const program = new Command();\n    program.command('one');\n    program.command('1').alias('one');\n  }).toThrow('cannot add alias');\n});\n\ntest('when command alias conflicts with existing alias then throw', () => {\n  expect(() => {\n    const program = new Command();\n    program.command('one').alias('1');\n    program.command('unity').alias('1');\n  }).toThrow('cannot add alias');\n});\n\ntest('when .addCommand name conflicts with existing name then throw', () => {\n  expect(() => {\n    const program = new Command();\n    program.command('one');\n    program.addCommand(new Command('one'));\n  }).toThrow('cannot add command');\n});\n\ntest('when .addCommand alias conflicts with existing name then throw', () => {\n  expect(() => {\n    const program = new Command();\n    program.command('one');\n    program.addCommand(new Command('unity').alias('one'));\n  }).toThrow('cannot add command');\n});\n"
  },
  {
    "path": "tests/command.showHelpAfterError.test.js",
    "content": "const commander = require('../');\n\ndescribe('showHelpAfterError with message', () => {\n  const customHelpMessage = 'See --help';\n\n  function makeProgram() {\n    const writeMock = jest.fn();\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .showHelpAfterError(customHelpMessage)\n      .configureOutput({ writeErr: writeMock });\n\n    return { program, writeMock };\n  }\n\n  test('when missing command-argument then shows help', () => {\n    const { program, writeMock } = makeProgram();\n    program.argument('<file>');\n    let caughtErr;\n    try {\n      program.parse([], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.missingArgument');\n    expect(writeMock).toHaveBeenLastCalledWith(`${customHelpMessage}\\n`);\n  });\n\n  test('when missing option-argument then shows help', () => {\n    const { program, writeMock } = makeProgram();\n    program.option('--output <file>');\n    let caughtErr;\n    try {\n      program.parse(['--output'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.optionMissingArgument');\n    expect(writeMock).toHaveBeenLastCalledWith(`${customHelpMessage}\\n`);\n  });\n\n  test('when missing mandatory option then shows help', () => {\n    const { program, writeMock } = makeProgram();\n    program.requiredOption('--password <cipher>');\n    let caughtErr;\n    try {\n      program.parse([], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.missingMandatoryOptionValue');\n    expect(writeMock).toHaveBeenLastCalledWith(`${customHelpMessage}\\n`);\n  });\n\n  test('when unknown option then shows help', () => {\n    const { program, writeMock } = makeProgram();\n    let caughtErr;\n    try {\n      program.parse(['--unknown-option'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.unknownOption');\n    expect(writeMock).toHaveBeenLastCalledWith(`${customHelpMessage}\\n`);\n  });\n\n  test('when too many command-arguments then shows help', () => {\n    const { program, writeMock } = makeProgram();\n    program.allowExcessArguments(false);\n    let caughtErr;\n    try {\n      program.parse(['surprise'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.excessArguments');\n    expect(writeMock).toHaveBeenLastCalledWith(`${customHelpMessage}\\n`);\n  });\n\n  test('when unknown command then shows help', () => {\n    const { program, writeMock } = makeProgram();\n    program.command('sub1');\n    let caughtErr;\n    try {\n      program.parse(['sub2'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.unknownCommand');\n    expect(writeMock).toHaveBeenLastCalledWith(`${customHelpMessage}\\n`);\n  });\n\n  test('when invalid option choice then shows help', () => {\n    const { program, writeMock } = makeProgram();\n    program.addOption(new commander.Option('--color').choices(['red', 'blue']));\n    let caughtErr;\n    try {\n      program.parse(['--color', 'pink'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.invalidArgument');\n    expect(writeMock).toHaveBeenLastCalledWith(`${customHelpMessage}\\n`);\n  });\n});\n\ntest('when showHelpAfterError() and error and then shows full help', () => {\n  const writeMock = jest.fn();\n  const program = new commander.Command();\n  program\n    .exitOverride()\n    .showHelpAfterError()\n    .configureOutput({ writeErr: writeMock });\n\n  try {\n    program.parse(['--unknown-option'], { from: 'user' });\n  } catch (err) {\n    /* empty */\n  }\n  expect(writeMock).toHaveBeenLastCalledWith(program.helpInformation());\n});\n"
  },
  {
    "path": "tests/command.showSuggestionAfterError.test.js",
    "content": "const { Command } = require('../');\n\nfunction getSuggestion(program, arg) {\n  let message = '';\n  program.exitOverride().configureOutput({\n    writeErr: (str) => {\n      message = str;\n    },\n  });\n\n  try {\n    program.parse([arg], { from: 'user' });\n  } catch (err) {\n    /* empty */\n  }\n\n  const match = message.match(/Did you mean (one of )?(.*)\\?/);\n  return match ? match[2] : null;\n}\n\ntest('when unknown command and showSuggestionAfterError() then show suggestion', () => {\n  const program = new Command();\n  program.showSuggestionAfterError();\n  program.command('example');\n  const suggestion = getSuggestion(program, 'exampel');\n  expect(suggestion).toBe('example');\n});\n\ntest('when unknown command and showSuggestionAfterError(false) then do not show suggestion', () => {\n  const program = new Command();\n  program.showSuggestionAfterError(false);\n  program.command('example');\n  const suggestion = getSuggestion(program, 'exampel');\n  expect(suggestion).toBe(null);\n});\n\ntest('when unknown option and showSuggestionAfterError() then show suggestion', () => {\n  const program = new Command();\n  program.showSuggestionAfterError();\n  program.option('--example');\n  const suggestion = getSuggestion(program, '--exampel');\n  expect(suggestion).toBe('--example');\n});\n\ntest('when unknown option and showSuggestionAfterError(false) then do not show suggestion', () => {\n  const program = new Command();\n  program.showSuggestionAfterError(false);\n  program.option('--example');\n  const suggestion = getSuggestion(program, '--exampel');\n  expect(suggestion).toBe(null);\n});\n"
  },
  {
    "path": "tests/command.summary.test.js",
    "content": "const commander = require('../');\n\ntest('when set summary then get summary', () => {\n  const program = new commander.Command();\n  const summary = 'abcdef';\n  program.summary(summary);\n  expect(program.summary()).toMatch(summary);\n});\n"
  },
  {
    "path": "tests/command.unknownCommand.test.js",
    "content": "const commander = require('../');\n\ndescribe('unknownCommand', () => {\n  // Optional. Use internal knowledge to suppress output to keep test output clean.\n  let writeErrorSpy;\n\n  beforeAll(() => {\n    writeErrorSpy = jest\n      .spyOn(process.stderr, 'write')\n      .mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    writeErrorSpy.mockClear();\n  });\n\n  afterAll(() => {\n    writeErrorSpy.mockRestore();\n  });\n\n  test('when unknown argument in simple program then error', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n    expect(() => {\n      program.parse('node test.js unknown'.split(' '));\n    }).toThrow();\n  });\n\n  test('when unknown command but action handler taking arg then no error', () => {\n    const program = new commander.Command();\n    program.exitOverride().command('sub');\n    program.argument('[args...]').action(() => {});\n    expect(() => {\n      program.parse('node test.js unknown'.split(' '));\n    }).not.toThrow();\n  });\n\n  test('when unknown command but listener then no error', () => {\n    const program = new commander.Command();\n    program.exitOverride().command('sub');\n    program.on('command:*', () => {});\n    expect(() => {\n      program.parse('node test.js unknown'.split(' '));\n    }).not.toThrow();\n  });\n\n  test('when unknown command then error', () => {\n    const program = new commander.Command();\n    program.exitOverride().command('sub');\n    let caughtErr;\n    try {\n      program.parse('node test.js unknown'.split(' '));\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.unknownCommand');\n  });\n\n  test('when unknown command and unknown option then error is for unknown command', () => {\n    //  The unknown command is more useful since the option is for an unknown command (and might be\n    // ok if the command had been correctly spelled, say).\n    const program = new commander.Command();\n    program.exitOverride().command('sub');\n    let caughtErr;\n    try {\n      program.parse('node test.js sbu --silly'.split(' '));\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.unknownCommand');\n  });\n});\n"
  },
  {
    "path": "tests/command.unknownOption.test.js",
    "content": "const commander = require('../');\n\n// Checking for detection of unknown options, including regression tests for some past issues.\n\ndescribe('unknownOption', () => {\n  // Optional. Use internal knowledge to suppress output to keep test output clean.\n  let writeErrorSpy;\n\n  beforeAll(() => {\n    writeErrorSpy = jest\n      .spyOn(process.stderr, 'write')\n      .mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    writeErrorSpy.mockClear();\n  });\n\n  afterAll(() => {\n    writeErrorSpy.mockRestore();\n  });\n\n  test('when specify unknown option with subcommand and action handler then error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .command('info')\n      .action(() => {});\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', 'info', '--NONSENSE']);\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.unknownOption');\n  });\n\n  test('when specify unknown option with subcommand argument and action handler then error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .command('info <file>')\n      .action(() => {});\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', 'info', 'a', '--NONSENSE']);\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.unknownOption');\n  });\n\n  test('when specify unknown option with program and action handler then error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .argument('[file]')\n      .action(() => {});\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', '--NONSENSE']);\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.unknownOption');\n  });\n\n  test('when specify unknown option with program argument and action handler then error', () => {\n    // Regression test from #965\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .argument('[file]')\n      .action(() => {});\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', 'info', 'a', '--NONSENSE']);\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.unknownOption');\n  });\n\n  test('when specify unknown option with simple program then error', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', '--NONSENSE']);\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.unknownOption');\n  });\n\n  test('when specify unknown global option before subcommand then error', () => {\n    const program = new commander.Command();\n    program.exitOverride();\n    program.command('sub');\n\n    let caughtErr;\n    try {\n      program.parse(['--NONSENSE', 'sub'], { from: 'user' });\n    } catch (err) {\n      caughtErr = err;\n    }\n    expect(caughtErr.code).toBe('commander.unknownOption');\n  });\n});\n"
  },
  {
    "path": "tests/command.usage.test.js",
    "content": "const commander = require('../');\n\ntest('when default usage and check program help then starts with default usage', () => {\n  const program = new commander.Command();\n\n  program.name('test');\n  const helpInformation = program.helpInformation();\n\n  expect(helpInformation).toMatch(/^Usage: test \\[options\\]/);\n});\n\ntest('when custom usage and check program help then starts with custom usage', () => {\n  const myUsage = 'custom';\n  const program = new commander.Command();\n  program.usage(myUsage);\n\n  program.name('test');\n  const helpInformation = program.helpInformation();\n\n  expect(helpInformation).toMatch(new RegExp(`^Usage: test ${myUsage}`));\n});\n\ntest('when default usage and check subcommand help then starts with default usage including program name', () => {\n  const program = new commander.Command();\n  const subCommand = program.command('info');\n\n  program.name('test');\n  const helpInformation = subCommand.helpInformation();\n\n  expect(helpInformation).toMatch(/^Usage: test info \\[options\\]/);\n});\n\ntest('when custom usage and check subcommand help then starts with custom usage including program name', () => {\n  const myUsage = 'custom';\n  const program = new commander.Command();\n  const subCommand = program.command('info').usage(myUsage);\n\n  program.name('test');\n  const helpInformation = subCommand.helpInformation();\n\n  expect(helpInformation).toMatch(new RegExp(`^Usage: test info ${myUsage}`));\n});\n\ntest('when has option then [options] included in usage', () => {\n  const program = new commander.Command();\n\n  program.option('--foo');\n\n  expect(program.usage()).toMatch('[options]');\n});\n\ntest('when no options then [options] not included in usage', () => {\n  const program = new commander.Command();\n\n  program.helpOption(false);\n\n  expect(program.usage()).not.toMatch('[options]');\n});\n\ntest('when has command then [command] included in usage', () => {\n  const program = new commander.Command();\n\n  program.command('foo');\n\n  expect(program.usage()).toMatch('[command]');\n});\n\ntest('when no commands then [command] not included in usage', () => {\n  const program = new commander.Command();\n\n  expect(program.usage()).not.toMatch('[command]');\n});\n\ntest('when argument then argument included in usage', () => {\n  const program = new commander.Command();\n\n  program.argument('<file>');\n\n  expect(program.usage()).toMatch('<file>');\n});\n\ntest('when options and command and argument then all three included in usage', () => {\n  const program = new commander.Command();\n\n  program.argument('<file>').option('--alpha').command('beta');\n\n  expect(program.usage()).toEqual('[options] [command] <file>');\n});\n"
  },
  {
    "path": "tests/commander.configureCommand.test.js",
    "content": "const commander = require('../');\n\n// Mostly testing direct on program, limited check that (sub)command working same.\n\n// Default behaviours\n\ntest('when default then options not stored on command', () => {\n  const program = new commander.Command();\n  program.option('--foo <value>', 'description');\n  program.parse(['node', 'test', '--foo', 'bar']);\n  expect(program.foo).toBeUndefined();\n  expect(program.opts().foo).toBe('bar');\n});\n\ntest('when default then options+command passed to action', () => {\n  const program = new commander.Command();\n  const callback = jest.fn();\n  program.argument('<value>').action(callback);\n  program.parse(['node', 'test', 'value']);\n  expect(callback).toHaveBeenCalledWith('value', program.opts(), program);\n});\n\n// storeOptionsAsProperties\n\ntest('when storeOptionsAsProperties() then options stored on command', () => {\n  const program = new commander.Command();\n  program.storeOptionsAsProperties().option('--foo <value>', 'description');\n  program.parse(['node', 'test', '--foo', 'bar']);\n  expect(program.foo).toBe('bar');\n  expect(program.opts().foo).toBe('bar');\n});\n\ntest('when storeOptionsAsProperties(true) then options stored on command', () => {\n  const program = new commander.Command();\n  program.storeOptionsAsProperties(true).option('--foo <value>', 'description');\n  program.parse(['node', 'test', '--foo', 'bar']);\n  expect(program.foo).toBe('bar');\n  expect(program.opts().foo).toBe('bar');\n});\n\ntest('when storeOptionsAsProperties(false) then options not stored on command', () => {\n  const program = new commander.Command();\n  program\n    .storeOptionsAsProperties(false)\n    .option('--foo <value>', 'description');\n  program.parse(['node', 'test', '--foo', 'bar']);\n  expect(program.foo).toBeUndefined();\n  expect(program.opts().foo).toBe('bar');\n});\n\ntest('when storeOptionsAsProperties() then command+command passed to action', () => {\n  const program = new commander.Command();\n  const callback = jest.fn();\n  program.storeOptionsAsProperties().argument('<value>').action(callback);\n  program.parse(['node', 'test', 'value']);\n  expect(callback).toHaveBeenCalledWith('value', program, program);\n});\n\ntest('when storeOptionsAsProperties(false) then opts+command passed to action', () => {\n  const program = new commander.Command();\n  const callback = jest.fn();\n  program.storeOptionsAsProperties(false).argument('<value>').action(callback);\n  program.parse(['node', 'test', 'value']);\n  expect(callback).toHaveBeenCalledWith('value', program.opts(), program);\n});\n\ntest('when storeOptionsAsProperties() after adding option then throw', () => {\n  const program = new commander.Command();\n  program.option('--port <number>', 'port number', '80');\n  expect(() => {\n    program.storeOptionsAsProperties();\n  }).toThrow();\n});\n\ntest('when storeOptionsAsProperties() after setting option value then throw', () => {\n  const program = new commander.Command();\n  program.setOptionValue('foo', 'bar');\n  expect(() => {\n    program.storeOptionsAsProperties();\n  }).toThrow();\n});\n"
  },
  {
    "path": "tests/createCommand.test.js",
    "content": "const commander = require('../');\n\ntest('when createCommand then unattached', () => {\n  const program = new commander.Command();\n  const cmd = program.createCommand();\n  expect(program.commands.length).toBe(0);\n  expect(cmd.parent).toBeFalsy(); // (actually null, but use weaker test for unattached)\n});\n\ntest('when subclass overrides createCommand then subcommand is subclass', () => {\n  class MyClass extends commander.Command {\n    constructor(name) {\n      super();\n      this.myProperty = 'myClass';\n    }\n\n    createCommand(name) {\n      return new MyClass(name);\n    }\n  }\n  const program = new MyClass();\n  const sub = program.command('sub');\n  expect(sub.myProperty).toEqual('myClass');\n});\n\ntest('when override createCommand then subcommand is custom', () => {\n  function createCustom(name) {\n    const cmd = new commander.Command();\n    cmd.myProperty = 'custom';\n    return cmd;\n  }\n  const program = createCustom();\n  program.createCommand = createCustom;\n  const sub = program.command('sub');\n  expect(sub.myProperty).toEqual('custom');\n});\n"
  },
  {
    "path": "tests/deprecated.test.js",
    "content": "const commander = require('../');\n\n// Test for backwards compatible behaviour of deprecated features that don't fit in elsewhere.\n// We keep deprecated features working (when not too difficult) to avoid breaking existing code\n// and reduce barriers to updating to latest version of Commander.\n\ndescribe('option with regular expression instead of custom processing function', () => {\n  test('when option not given then value is default', () => {\n    const program = new commander.Command();\n    program.option('--cheese <type>', 'cheese type', /mild|tasty/, 'mild');\n    program.parse([], { from: 'user' });\n    expect(program.opts().cheese).toEqual('mild');\n  });\n\n  test('when argument matches regexp then value is as specified', () => {\n    const program = new commander.Command();\n    program.option('--cheese <type>', 'cheese type', /mild|tasty/, 'mild');\n    program.parse(['--cheese', 'tasty'], { from: 'user' });\n    expect(program.opts().cheese).toEqual('tasty');\n  });\n\n  test('when argument does not match regexp then value is default', () => {\n    const program = new commander.Command();\n    program.option('--cheese <type>', 'cheese type', /mild|tasty/, 'mild');\n    program.parse(['--cheese', 'other'], { from: 'user' });\n    expect(program.opts().cheese).toEqual('mild');\n  });\n});\n"
  },
  {
    "path": "tests/esm-imports-test.mjs",
    "content": "import {\n  program,\n  Command,\n  Option,\n  Argument,\n  CommanderError,\n  InvalidArgumentError,\n  InvalidOptionArgumentError,\n  Help,\n  createCommand,\n  createArgument,\n  createOption,\n} from '../esm.mjs';\n\n// Do some simple checks that expected imports are available at runtime.\n// Run using `npm run test-esm`.\n// Similar tests to test-imports.test.ts\n\nfunction check(condition, explanation) {\n  if (!condition) {\n    console.log(`Failed assertion: ${explanation}`);\n    process.exit(2);\n  }\n}\n\nfunction checkClass(obj, name) {\n  console.log(`Checking ${name}`);\n  check(typeof obj === 'object', `new ${name}() produces object`);\n  check(obj.constructor.name === name, `object constructor is ${name}`);\n}\n\nconsole.log('Checking program');\ncheck(typeof program === 'object', 'program is object');\ncheck(program.constructor.name === 'Command', 'program is class Command');\n\ncheckClass(new Command(), 'Command');\ncheckClass(new Option('-e, --example'), 'Option');\ncheckClass(new CommanderError(1, 'code', 'failed'), 'CommanderError');\ncheckClass(new InvalidArgumentError('failed'), 'InvalidArgumentError');\ncheckClass(new InvalidOptionArgumentError('failed'), 'InvalidArgumentError');\ncheckClass(new Help(), 'Help');\ncheckClass(new Argument('<file>'), 'Argument');\n\nconsole.log('Checking createCommand');\ncheck(typeof createCommand === 'function', 'createCommand is function');\nconsole.log('Checking createArgument');\ncheck(typeof createArgument === 'function', 'createArgument is function');\nconsole.log('Checking createOption');\ncheck(typeof createOption === 'function', 'createOption is function');\n\nconsole.log('No problems');\n"
  },
  {
    "path": "tests/fixtures/inspect-sub.js",
    "content": "console.log(process.execArgv);\n"
  },
  {
    "path": "tests/fixtures/inspect.js",
    "content": "#!/usr/bin/env node\n\nconst { program } = require('../../');\n\nprocess.env.FORCE_COLOR = 0; // work-around bug in Jest: https://github.com/jestjs/jest/issues/14391\n\nprogram.command('sub', 'install one or more packages').parse(process.argv);\n"
  },
  {
    "path": "tests/fixtures/pm",
    "content": "#!/usr/bin/env node\n\nconst path = require('node:path');\nconst { program } = require('../../');\n\nprocess.env.FORCE_COLOR = 0; // work-around bug in Jest: https://github.com/jestjs/jest/issues/14391\n\nprogram\n  .version('0.0.1')\n  .command('install [name]', 'install one or more packages')\n  .alias('i')\n  .command('search [query]', 'search with optional query')\n  .alias('s')\n  .command('cache', 'actions dealing with the cache')\n  .alias('c')\n  .command('echo', 'echo arguments')\n  .command('list', 'list packages installed')\n  .alias('lst')\n  .command('listen', 'listen for supported signal events')\n  .alias('l')\n  .command('publish', 'publish or update package')\n  .alias('p')\n  .command('default', 'default command', { hidden: true, isDefault: true })\n  .command('specifyInstall', 'specify install subcommand', {\n    executableFile: 'pm-install',\n  })\n  .command('specifyPublish', 'specify publish subcommand', {\n    executableFile: 'pm-publish',\n  })\n  .command('silent', 'silently succeed')\n  .command('fail', 'exit with non-zero status code')\n  .command('terminate', 'terminate due to signal');\n\nprogram\n  .command('exit-override')\n  .exitOverride((err) => {\n    process.exit(err.exitCode);\n  })\n  .command('fail', 'exit with non-zero status code', {\n    executableFile: path.join(__dirname, 'pm-fail.js'),\n  })\n  .command('terminate', 'terminate due to signal', {\n    executableFile: path.join(__dirname, 'pm-terminate.js'),\n  });\n\nprogram.parse(process.argv);\n"
  },
  {
    "path": "tests/fixtures/pm-cache-clear.js",
    "content": "console.log('cache-clear');\n"
  },
  {
    "path": "tests/fixtures/pm-cache-validate.js",
    "content": "console.log('cache-validate');\n"
  },
  {
    "path": "tests/fixtures/pm-cache.js",
    "content": "const { program } = require('../../');\n\nprogram\n  .command('clear', 'clear the cache')\n  .command('validate', 'validate the cache', { isDefault: true })\n  .parse(process.argv);\n"
  },
  {
    "path": "tests/fixtures/pm-default",
    "content": "#!/usr/bin/env node\nconsole.log('default');\nif (process.argv.length > 2) {\n  console.log(process.argv.slice(2));\n}\n"
  },
  {
    "path": "tests/fixtures/pm-echo.js",
    "content": "console.log(process.argv.slice(2));\n"
  },
  {
    "path": "tests/fixtures/pm-fail.js",
    "content": "process.exit(42);\n"
  },
  {
    "path": "tests/fixtures/pm-install",
    "content": "#!/usr/bin/env node\nconsole.log('install');\n"
  },
  {
    "path": "tests/fixtures/pm-listen",
    "content": "#!/usr/bin/env node\n\nprocess.on('SIGUSR1', function () {\n  process.stdout.write('SIGUSR1');\n  process.exit();\n});\n\nprocess.on('SIGUSR2', function () {\n  process.stdout.write('SIGUSR2');\n  process.exit();\n});\n\nprocess.on('SIGTERM', function () {\n  process.stdout.write('SIGTERM');\n  process.exit();\n});\n\nprocess.on('SIGINT', function () {\n  process.stdout.write('SIGINT');\n  process.exit();\n});\n\nprocess.on('SIGHUP', function () {\n  process.stdout.write('SIGHUP');\n  process.exit();\n});\n\nprocess.stdout.write('Listening for signal...');\nsetInterval(function () {}, 1000); // Stay running\n"
  },
  {
    "path": "tests/fixtures/pm-publish.js",
    "content": "console.log('publish');\n"
  },
  {
    "path": "tests/fixtures/pm-search",
    "content": "#!/usr/bin/env node\nconsole.log('search');\n"
  },
  {
    "path": "tests/fixtures/pm-silent",
    "content": "#!/usr/bin/env node\n\n// This is a subcommand which succeeds and does not write any output, for using from unit test\n"
  },
  {
    "path": "tests/fixtures/pm-terminate.js",
    "content": "process.kill(process.pid, 'SIGINT');\n"
  },
  {
    "path": "tests/fixtures/pmlink-install",
    "content": "#!/usr/bin/env node\nconsole.log('install');\n"
  },
  {
    "path": "tests/fixtures-extensions/pm-try-cjs.cjs",
    "content": "console.log('found .cjs');\n"
  },
  {
    "path": "tests/fixtures-extensions/pm-try-mjs.mjs",
    "content": "console.log('found .mjs');\n"
  },
  {
    "path": "tests/fixtures-extensions/pm-try-ts.ts",
    "content": "console.log('found .ts');\n"
  },
  {
    "path": "tests/fixtures-extensions/pm.js",
    "content": "#!/usr/bin/env node\n\nconst { program } = require('../../');\n\nprogram\n  .command('try-ts', 'test file extension lookup')\n  .command('try-cjs', 'test file extension lookup')\n  .command('try-mjs', 'test file extension lookup')\n  .parse(process.argv);\n"
  },
  {
    "path": "tests/help.argumentDescription.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n\ndescribe('argumentDescription', () => {\n  test('when argument has no description then empty string', () => {\n    const argument = new commander.Argument('[n]');\n    const helper = new commander.Help();\n    expect(helper.argumentDescription(argument)).toEqual('');\n  });\n\n  test('when argument has description then return description', () => {\n    const description = 'description';\n    const argument = new commander.Argument('[n]', description);\n    const helper = new commander.Help();\n    expect(helper.argumentDescription(argument)).toEqual(description);\n  });\n\n  test('when argument has default value then return description and default value', () => {\n    const argument = new commander.Argument('[n]', 'description').default(\n      'default',\n    );\n    const helper = new commander.Help();\n    expect(helper.argumentDescription(argument)).toEqual(\n      'description (default: \"default\")',\n    );\n  });\n\n  test('when argument has default value description then return description and custom default description', () => {\n    const argument = new commander.Argument('[n]', 'description').default(\n      'default value',\n      'custom',\n    );\n    const helper = new commander.Help();\n    expect(helper.argumentDescription(argument)).toEqual(\n      'description (default: custom)',\n    );\n  });\n\n  test('when an argument has default value and no description then still return default value', () => {\n    const argument = new commander.Argument('[n]').default('default');\n    const helper = new commander.Help();\n    expect(helper.argumentDescription(argument)).toEqual(\n      '(default: \"default\")',\n    );\n  });\n});\n"
  },
  {
    "path": "tests/help.boxWrap.test.js",
    "content": "const commander = require('../');\n\ntest('when empty string then return empty string', () => {\n  const helper = new commander.Help();\n  const text = '';\n  const wrapped = helper.boxWrap(text, 50);\n  expect(wrapped).toEqual(text);\n});\n\ntest('when string contains unix line breaks then return (unix) empty lines', () => {\n  const helper = new commander.Help();\n  const text = '\\n\\n\\n';\n  const wrapped = helper.boxWrap(text, 50);\n  expect(wrapped).toEqual(text);\n});\n\ntest('when string contains Windows line breaks then return (unix)) empty lines', () => {\n  const helper = new commander.Help();\n  const text = '\\r\\n\\r\\n\\r\\n';\n  const wrapped = helper.boxWrap(text, 50);\n  expect(wrapped).toEqual('\\n\\n\\n');\n});\n\ntest('when string contains only whitespace then returns empty string (trim right)', () => {\n  const helper = new commander.Help();\n  const text = ' \\t  ';\n  const wrapped = helper.boxWrap(text, 50);\n  expect(wrapped).toEqual('');\n});\n\ntest('when string contains leading whitespace then returns string with leading whitespace', () => {\n  const helper = new commander.Help();\n  const text = '  abc';\n  const wrapped = helper.boxWrap(text, 50);\n  expect(wrapped).toEqual('  abc');\n});\n\ntest('when string contains intermediate whitespace then returns string with intermediate whitespace', () => {\n  const helper = new commander.Help();\n  const text = '123   456';\n  const wrapped = helper.boxWrap(text, 50);\n  expect(wrapped).toEqual('123   456');\n});\n\ntest('when string contains trailing whitespace then returns string without trailing whitespace (trim right)', () => {\n  const helper = new commander.Help();\n  const text = '123   456   ';\n  const wrapped = helper.boxWrap(text, 50);\n  expect(wrapped).toEqual('123   456');\n});\n\ntest('when string contains escape sequences then returns string with escape sequences', () => {\n  const helper = new commander.Help();\n  const text = '123   456   ';\n  const wrapped = helper.boxWrap(text, 50);\n  expect(wrapped).toEqual('123   456');\n});\n\ntest('when string has enough words to wrap then returns two wrapped lines', () => {\n  const helper = new commander.Help();\n  const text = '123 567 901 345 789 123 567 901 345 789 123 567 901';\n  const wrapped = helper.boxWrap(text, 45);\n  expect(wrapped).toEqual(\n    '123 567 901 345 789 123 567 901 345 789 123\\n567 901',\n  );\n});\n\ntest('when string has enough words and escape sequences to wrap then returns wrapped line with break ignoring escape sequences', () => {\n  const helper = new commander.Help();\n  const CSI = '\\u001b[';\n  const underlinedText = `${CSI}4mXYZ${CSI}24m`;\n  const text = `${underlinedText}${' ABC'.repeat(19)}`;\n  const wrapped = helper.boxWrap(text, 44);\n  expect(wrapped).toEqual(`${underlinedText} ${'ABC '.repeat(9)}ABC\n${'ABC '.repeat(8)}ABC`);\n});\n\ntest('when first word longer than width then soft wrap', () => {\n  const helper = new commander.Help();\n  const text = 'abc'.repeat(20);\n  const wrapped = helper.boxWrap(text, 40);\n  expect(wrapped).toEqual(text);\n});\n\ntest('when second word longer than width then wrap and soft wrap', () => {\n  const helper = new commander.Help();\n  const text = 'xyz ' + 'abc'.repeat(20);\n  const wrapped = helper.boxWrap(text, 40);\n  expect(wrapped).toEqual(`xyz\\n${'abc'.repeat(20)}`);\n});\n\ntest('when set width 41 then wrap at 41', () => {\n  const helper = new commander.Help();\n  const text = 'X'.repeat(39) + ' 1 2 3';\n  let wrapped = helper.boxWrap(text, 40);\n  expect(wrapped).toEqual('X'.repeat(39) + '\\n1 2 3');\n  wrapped = helper.boxWrap(text, 41);\n  expect(wrapped).toEqual('X'.repeat(39) + ' 1\\n2 3');\n});\n\ntest('when set width 12 (too small) then skip wrap', () => {\n  const helper = new commander.Help();\n  const text = ' x'.repeat(8) + ' yy'.repeat(6);\n  let wrapped = helper.boxWrap(text, 14);\n  expect(wrapped).toEqual(text);\n});\n\ntest('when set width 12 (and set minWrapWidth) then skip wrap', () => {\n  const helper = new commander.Help();\n  helper.minWidthToWrap = 1;\n  const text = ' x'.repeat(8) + ' yy'.repeat(6);\n  let wrapped = helper.boxWrap(text, 14);\n  expect(wrapped).toEqual(' x x x x x x x\\nx yy yy yy yy\\nyy yy');\n});\n"
  },
  {
    "path": "tests/help.commandTerm.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\n// subcommandTerm does not currently respect helpOption or ignore hidden options, so not testing those.\ndescribe('subcommandTerm', () => {\n  test('when plain command then returns name', () => {\n    const command = new commander.Command('program');\n    const helper = new commander.Help();\n    expect(helper.subcommandTerm(command)).toEqual('program');\n  });\n\n  test('when command has alias then returns name|alias', () => {\n    const command = new commander.Command('program').alias('alias');\n    const helper = new commander.Help();\n    expect(helper.subcommandTerm(command)).toEqual('program|alias');\n  });\n\n  test('when command has options then returns name [options]', () => {\n    const command = new commander.Command('program').option('-a,--all');\n    const helper = new commander.Help();\n    expect(helper.subcommandTerm(command)).toEqual('program [options]');\n  });\n\n  test('when command has <argument> then returns name <argument>', () => {\n    const command = new commander.Command('program').argument('<argument>');\n    const helper = new commander.Help();\n    expect(helper.subcommandTerm(command)).toEqual('program <argument>');\n  });\n\n  test('when command has everything then returns name|alias [options] <argument>', () => {\n    const command = new commander.Command('program')\n      .alias('alias')\n      .option('-a,--all')\n      .argument('<argument>');\n    const helper = new commander.Help();\n    expect(helper.subcommandTerm(command)).toEqual(\n      'program|alias [options] <argument>',\n    );\n  });\n});\n"
  },
  {
    "path": "tests/help.commandUsage.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('commandUsage', () => {\n  test('when single program then \"program [options]\"', () => {\n    const program = new commander.Command();\n    program.name('program');\n    const helper = new commander.Help();\n    expect(helper.commandUsage(program)).toEqual('program [options]');\n  });\n\n  test('when multi program then \"program [options] [command]\"', () => {\n    const program = new commander.Command();\n    program.name('program');\n    program.command('sub');\n    const helper = new commander.Help();\n    expect(helper.commandUsage(program)).toEqual('program [options] [command]');\n  });\n\n  test('when program has alias then usage includes alias', () => {\n    const program = new commander.Command();\n    program.name('program').alias('alias');\n    const helper = new commander.Help();\n    expect(helper.commandUsage(program)).toEqual('program|alias [options]');\n  });\n\n  test('when help for subcommand then usage includes hierarchy', () => {\n    const program = new commander.Command();\n    program.name('program');\n    const sub = program.command('sub').name('sub');\n    const helper = new commander.Help();\n    expect(helper.commandUsage(sub)).toEqual('program sub [options]');\n  });\n\n  test('when program has argument then usage includes argument', () => {\n    const program = new commander.Command();\n    program.name('program').argument('<file>');\n    const helper = new commander.Help();\n    expect(helper.commandUsage(program)).toEqual('program [options] <file>');\n  });\n});\n"
  },
  {
    "path": "tests/help.longestArgumentTermLength.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('longestArgumentTermLength', () => {\n  test('when no arguments then returns zero', () => {\n    const program = new commander.Command();\n    const helper = new commander.Help();\n    expect(helper.longestArgumentTermLength(program, helper)).toEqual(0);\n  });\n\n  test('when has argument description then returns argument length', () => {\n    const program = new commander.Command();\n    program.argument('<wonder>', 'wonder description');\n    const helper = new commander.Help();\n    expect(helper.longestArgumentTermLength(program, helper)).toEqual(\n      'wonder'.length,\n    );\n  });\n\n  test('when has multiple argument descriptions then returns longest', () => {\n    const program = new commander.Command();\n    program.argument('<alpha>', 'x');\n    program.argument('<longest>', 'x');\n    program.argument('<beta>', 'x');\n    const helper = new commander.Help();\n    expect(helper.longestArgumentTermLength(program, helper)).toEqual(\n      'longest'.length,\n    );\n  });\n});\n"
  },
  {
    "path": "tests/help.longestCommandTermLength.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('longestSubcommandTermLength', () => {\n  test('when no commands then returns zero', () => {\n    const program = new commander.Command();\n    const helper = new commander.Help();\n    expect(helper.longestSubcommandTermLength(program, helper)).toEqual(0);\n  });\n\n  test('when command and no help then returns length of term', () => {\n    const sub = new commander.Command('sub');\n    const program = new commander.Command();\n    program.addHelpCommand(false).addCommand(sub);\n    const helper = new commander.Help();\n    expect(helper.longestSubcommandTermLength(program, helper)).toEqual(\n      helper.subcommandTerm(sub).length,\n    );\n  });\n\n  test('when command with arg and no help then returns length of term', () => {\n    const sub = new commander.Command('sub <file)');\n    const program = new commander.Command();\n    program.addHelpCommand(false).addCommand(sub);\n    const helper = new commander.Help();\n    expect(helper.longestSubcommandTermLength(program, helper)).toEqual(\n      helper.subcommandTerm(sub).length,\n    );\n  });\n\n  test('when multiple commands then returns longest length', () => {\n    const longestCommandName = 'alphabet-soup <longer_than_help>';\n    const program = new commander.Command();\n    program\n      .addHelpCommand(false)\n      .command('before', 'desc')\n      .command(longestCommandName, 'desc')\n      .command('after', 'desc');\n    const helper = new commander.Help();\n    expect(helper.longestSubcommandTermLength(program, helper)).toEqual(\n      longestCommandName.length,\n    );\n  });\n\n  test('when just help command then returns length of help term', () => {\n    const program = new commander.Command();\n    program.addHelpCommand(true);\n    const helper = new commander.Help();\n    expect(helper.longestSubcommandTermLength(program, helper)).toEqual(\n      'help [command]'.length,\n    );\n  });\n});\n"
  },
  {
    "path": "tests/help.longestOptionTermLength.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('longestOptionTermLength', () => {\n  test('when no option then returns zero', () => {\n    const program = new commander.Command();\n    program.helpOption(false);\n    const helper = new commander.Help();\n    expect(helper.longestOptionTermLength(program, helper)).toEqual(0);\n  });\n\n  test('when just implicit help option returns length of help flags', () => {\n    const program = new commander.Command();\n    const helper = new commander.Help();\n    expect(helper.longestOptionTermLength(program, helper)).toEqual(\n      '-h, --help'.length,\n    );\n  });\n\n  test('when multiple option then returns longest length', () => {\n    const longestOptionFlags = '-l, --longest <value>';\n    const program = new commander.Command();\n    program\n      .option('--before', 'optional description of flags')\n      .option(longestOptionFlags)\n      .option('--after');\n    const helper = new commander.Help();\n    expect(helper.longestOptionTermLength(program, helper)).toEqual(\n      longestOptionFlags.length,\n    );\n  });\n});\n"
  },
  {
    "path": "tests/help.minWidthToWrap.test.js",
    "content": "const commander = require('../');\n\ndescribe('Help.minWidthToWrap', () => {\n  test('when enough width then wrap', () => {\n    const program = new commander.Command('program');\n    program.description('x '.repeat(110));\n    program.configureOutput({\n      getOutHelpWidth: () => 100, // lots of room to wrap\n    });\n    const helpText = program.helpInformation();\n    const wrappedescription =\n      'x '.repeat(50).trim() +\n      '\\n' +\n      'x '.repeat(50).trim() +\n      '\\n' +\n      'x '.repeat(10).trim();\n    expect(helpText).toMatch(wrappedescription);\n  });\n\n  test('when not enough width then no wrap', () => {\n    const program = new commander.Command('program');\n    program.description('x '.repeat(50));\n    program.configureOutput({\n      getOutHelpWidth: () => 30, // too narrow to wrap\n    });\n    const helpText = program.helpInformation();\n    const wrappedescription = 'x '.repeat(50);\n    expect(helpText).toMatch(wrappedescription);\n  });\n\n  test('when make minWidthToWrap small then wrap', () => {\n    const program = new commander.Command('program');\n    program.description('x '.repeat(40));\n    program.configureOutput({\n      getOutHelpWidth: () => 30,\n    });\n    program.configureHelp({ minWidthToWrap: 20 });\n    const helpText = program.helpInformation();\n    const wrappedescription =\n      'x '.repeat(15).trimEnd() +\n      '\\n' +\n      'x '.repeat(15).trimEnd() +\n      '\\n' +\n      'x '.repeat(10).trimEnd();\n    expect(helpText).toMatch(wrappedescription);\n  });\n});\n"
  },
  {
    "path": "tests/help.optionDescription.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('optionDescription', () => {\n  test('when option has no description then empty string', () => {\n    const option = new commander.Option('-a');\n    const helper = new commander.Help();\n    expect(helper.optionDescription(option)).toEqual('');\n  });\n\n  test('when option has description then return description', () => {\n    const description = 'description';\n    const option = new commander.Option('-a', description);\n    const helper = new commander.Help();\n    expect(helper.optionDescription(option)).toEqual(description);\n  });\n\n  test('when boolean option has default value true then return description and default value', () => {\n    const description = 'description';\n    const option = new commander.Option('-a', description).default(true);\n    const helper = new commander.Help();\n    expect(helper.optionDescription(option)).toEqual(\n      'description (default: true)',\n    );\n  });\n\n  test('when boolean option has default value string then return description without default', () => {\n    const description = 'description';\n    const option = new commander.Option('-a', description).default('foo');\n    const helper = new commander.Help();\n    expect(helper.optionDescription(option)).toEqual('description');\n  });\n\n  test('when optional option has preset value then return description and default value', () => {\n    const description = 'description';\n    const option = new commander.Option('--aa [value]', description).preset(\n      'abc',\n    );\n    const helper = new commander.Help();\n    expect(helper.optionDescription(option)).toEqual(\n      'description (preset: \"abc\")',\n    );\n  });\n\n  test('when boolean option has preset value then return description without default', () => {\n    const description = 'description';\n    const option = new commander.Option('--bb', description).preset('abc');\n    const helper = new commander.Help();\n    expect(helper.optionDescription(option)).toEqual('description');\n  });\n  test('when option has env then return description and env name', () => {\n    const description = 'description';\n    const option = new commander.Option('-a', description).env('ENV');\n    const helper = new commander.Help();\n    expect(helper.optionDescription(option)).toEqual('description (env: ENV)');\n  });\n\n  test('when option has default value description then return description and custom default description', () => {\n    const description = 'description';\n    const defaultValueDescription = 'custom';\n    const option = new commander.Option('-a <value>', description).default(\n      'default value',\n      defaultValueDescription,\n    );\n    const helper = new commander.Help();\n    expect(helper.optionDescription(option)).toEqual(\n      `description (default: ${defaultValueDescription})`,\n    );\n  });\n\n  test('when option has default value but not description then return custom default', () => {\n    const defaultValueDescription = 'custom';\n    const option = new commander.Option('-a <value>').default(\n      'default value',\n      defaultValueDescription,\n    );\n    const helper = new commander.Help();\n    expect(helper.optionDescription(option)).toEqual(\n      `(default: ${defaultValueDescription})`,\n    );\n  });\n\n  test('when option has choices then return description and choices', () => {\n    const description = 'description';\n    const choices = ['one', 'two'];\n    const option = new commander.Option('-a <value>', description).choices(\n      choices,\n    );\n    const helper = new commander.Help();\n    expect(helper.optionDescription(option)).toEqual(\n      'description (choices: \"one\", \"two\")',\n    );\n  });\n});\n"
  },
  {
    "path": "tests/help.optionTerm.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('optionTerm', () => {\n  test('when -s flags then returns flags', () => {\n    const flags = '-s';\n    const option = new commander.Option(flags);\n    const helper = new commander.Help();\n    expect(helper.optionTerm(option)).toEqual(flags);\n  });\n\n  test('when --short flags then returns flags', () => {\n    const flags = '--short';\n    const option = new commander.Option(flags);\n    const helper = new commander.Help();\n    expect(helper.optionTerm(option)).toEqual(flags);\n  });\n\n  test('when -s,--short flags then returns flags', () => {\n    const flags = '-s,--short';\n    const option = new commander.Option(flags);\n    const helper = new commander.Help();\n    expect(helper.optionTerm(option)).toEqual(flags);\n  });\n\n  test('when -s|--short flags then returns flags', () => {\n    const flags = '-s|--short';\n    const option = new commander.Option(flags);\n    const helper = new commander.Help();\n    expect(helper.optionTerm(option)).toEqual(flags);\n  });\n});\n"
  },
  {
    "path": "tests/help.padWidth.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('padWidth', () => {\n  test('when argument term longest return argument length', () => {\n    const longestThing = 'veryLongThingBiggerThanOthers';\n    const program = new commander.Command();\n    program.argument(`<${longestThing}>`, 'description').option('-o');\n    program.command('sub');\n    const helper = new commander.Help();\n    expect(helper.padWidth(program, helper)).toEqual(longestThing.length);\n  });\n\n  test('when option term longest return option length', () => {\n    const longestThing = '--very-long-thing-bigger-than-others';\n    const program = new commander.Command();\n    program.argument('<file>', 'desc').option(longestThing);\n    program.command('sub');\n    const helper = new commander.Help();\n    expect(helper.padWidth(program, helper)).toEqual(longestThing.length);\n  });\n\n  test('when global option term longest return global option length', () => {\n    const longestThing = '--very-long-thing-bigger-than-others';\n    const program = new commander.Command();\n    program\n      .argument('<file>', 'desc')\n      .option(longestThing)\n      .configureHelp({ showGlobalOptions: true });\n    const sub = program.command('sub');\n    const helper = sub.createHelp();\n    expect(helper.padWidth(sub, helper)).toEqual(longestThing.length);\n  });\n\n  test('when command term longest return command length', () => {\n    const longestThing = 'very-long-thing-bigger-than-others';\n    const program = new commander.Command();\n    program.argument('<file>', 'desc').option('-o');\n    program.command(longestThing);\n    const helper = new commander.Help();\n    expect(helper.padWidth(program, helper)).toEqual(longestThing.length);\n  });\n});\n"
  },
  {
    "path": "tests/help.preformatted.test.js",
    "content": "const { Help, Command } = require('../');\n\ndescribe('preformatted', () => {\n  test('when single line then false', () => {\n    const helper = new Help();\n    expect(helper.preformatted('a b c')).toBe(false);\n  });\n\n  test('when single line with leading whitespace then false', () => {\n    const helper = new Help();\n    expect(helper.preformatted(' a b c')).toBe(false);\n  });\n\n  test('when unix line break not followed by whitespace then false', () => {\n    const helper = new Help();\n    expect(helper.preformatted('a\\nb\\nc')).toBe(false);\n  });\n\n  test('when Windows line break not followed by whitespace then false', () => {\n    const helper = new Help();\n    expect(helper.preformatted('a\\r\\nb\\r\\nc')).toBe(false);\n  });\n\n  test('when unix line followed by whitespace then true', () => {\n    const helper = new Help();\n    expect(helper.preformatted('a\\n  b')).toBe(true);\n  });\n\n  test('when Windows line break followed by whitespace then true', () => {\n    const helper = new Help();\n    expect(helper.preformatted('a\\r\\n  b')).toBe(true);\n  });\n\n  test('when empty unix lines then false', () => {\n    const helper = new Help();\n    expect(helper.preformatted('a\\n\\n')).toBe(false);\n  });\n\n  test('when empty Windows lines then false', () => {\n    const helper = new Help();\n    expect(helper.preformatted('a\\r\\n\\r\\n')).toBe(false);\n  });\n});\n\ntest('end-to-end: when option description is preformatted then manual format is preserved', () => {\n  // #396: leave custom format alone, apart from space-space indent\n  const optionSpec = '-t, --time <HH:MM>';\n  const program = new Command();\n  program.configureHelp({ helpWidth: 80 }).option(\n    optionSpec,\n    `select time\n\nTime can also be specified using special values:\n  \"dawn\" - From night to sunrise.\n`,\n  );\n\n  const expectedOutput = `Usage:  [options]\n\nOptions:\n  ${optionSpec}  select time\n  \n  Time can also be specified using special values:\n    \"dawn\" - From night to sunrise.\n  \n  -h, --help          display help for command\n`;\n\n  expect(program.helpInformation()).toBe(expectedOutput);\n});\n"
  },
  {
    "path": "tests/help.showGlobalOptions.test.js",
    "content": "const commander = require('../');\n\ntest('when default configuration then global options hidden', () => {\n  const program = new commander.Command();\n  program.option('--global');\n  const sub = program.command('sub');\n  expect(sub.helpInformation()).not.toContain('global');\n});\n\ntest('when showGlobalOptions:true then program options shown', () => {\n  const program = new commander.Command();\n  program.option('--global').configureHelp({ showGlobalOptions: true });\n  const sub = program.command('sub');\n  expect(sub.helpInformation()).toContain('global');\n});\n\ntest('when showGlobalOptions:true and no global options then global options header not shown', () => {\n  const program = new commander.Command();\n  program.configureHelp({ showGlobalOptions: true });\n  const sub = program.command('sub');\n  expect(sub.helpInformation()).not.toContain('Global');\n});\n\ntest('when showGlobalOptions:true and nested commands then combined nested options shown program last', () => {\n  const program = new commander.Command();\n  program.option('--global').configureHelp({ showGlobalOptions: true });\n  const sub1 = program.command('sub1').option('--sub1');\n  const sub2 = sub1.command('sub2');\n  expect(sub2.helpInformation()).toContain(`Global Options:\n  --sub1\n  --global\n`);\n});\n\ntest('when showGlobalOptions:true and sortOptions: true then global options sorted', () => {\n  const program = new commander.Command();\n  program\n    .option('-3')\n    .option('-4')\n    .option('-2')\n    .configureHelp({ showGlobalOptions: true, sortOptions: true });\n  const sub1 = program.command('sub1').option('-6').option('-1').option('-5');\n  const sub2 = sub1.command('sub2');\n  expect(sub2.helpInformation()).toContain(`Global Options:\n  -1\n  -2\n  -3\n  -4\n  -5\n  -6\n`);\n});\n"
  },
  {
    "path": "tests/help.sortCommands.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('sortSubcommands', () => {\n  test('when unsorted then commands in order added', () => {\n    const program = new commander.Command();\n    program\n      .command('ccc', 'desc')\n      .command('aaa', 'desc')\n      .command('bbb', 'desc');\n    const helper = program.createHelp();\n    const visibleCommandNames = helper\n      .visibleCommands(program)\n      .map((cmd) => cmd.name());\n    expect(visibleCommandNames).toEqual(['ccc', 'aaa', 'bbb', 'help']);\n  });\n\n  test('when sortSubcommands:true then commands sorted', () => {\n    const program = new commander.Command();\n    program\n      .configureHelp({ sortSubcommands: true })\n      .command('ccc', 'desc')\n      .command('aaa', 'desc')\n      .command('bbb', 'desc');\n    const helper = program.createHelp();\n    const visibleCommandNames = helper\n      .visibleCommands(program)\n      .map((cmd) => cmd.name());\n    expect(visibleCommandNames).toEqual(['aaa', 'bbb', 'ccc', 'help']);\n  });\n});\n"
  },
  {
    "path": "tests/help.sortOptions.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('sortOptions', () => {\n  test('when unsorted then options in order added', () => {\n    const program = new commander.Command();\n    program\n      .option('--zzz', 'desc')\n      .option('--aaa', 'desc')\n      .option('--bbb', 'desc');\n    const helper = program.createHelp();\n    const visibleOptionNames = helper\n      .visibleOptions(program)\n      .map((option) => option.name());\n    expect(visibleOptionNames).toEqual(['zzz', 'aaa', 'bbb', 'help']);\n  });\n\n  test('when sortOptions:true then options sorted alphabetically', () => {\n    const program = new commander.Command();\n    program\n      .configureHelp({ sortOptions: true })\n      .option('--zzz', 'desc')\n      .option('--aaa', 'desc')\n      .option('--bbb', 'desc');\n    const helper = program.createHelp();\n    const visibleOptionNames = helper\n      .visibleOptions(program)\n      .map((cmd) => cmd.name());\n    expect(visibleOptionNames).toEqual(['aaa', 'bbb', 'help', 'zzz']);\n  });\n\n  test('when both short and long flags then sort on short flag', () => {\n    const program = new commander.Command();\n    program\n      .configureHelp({ sortOptions: true })\n      .option('-m,--zzz', 'desc')\n      .option('-n,--aaa', 'desc')\n      .option('-o,--bbb', 'desc');\n    const helper = program.createHelp();\n    const visibleOptionNames = helper\n      .visibleOptions(program)\n      .map((cmd) => cmd.name());\n    expect(visibleOptionNames).toEqual(['help', 'zzz', 'aaa', 'bbb']);\n  });\n\n  test('when lone short and long flags then sort on lone flag', () => {\n    const program = new commander.Command();\n    program\n      .configureHelp({ sortOptions: true })\n      .option('--zzz', 'desc')\n      .option('--aaa', 'desc')\n      .option('-b', 'desc');\n    const helper = program.createHelp();\n    const visibleOptionNames = helper\n      .visibleOptions(program)\n      .map((cmd) => cmd.name());\n    expect(visibleOptionNames).toEqual(['aaa', 'b', 'help', 'zzz']);\n  });\n\n  test('when mixed case flags then sort is case insensitive', () => {\n    const program = new commander.Command();\n    program\n      .configureHelp({ sortOptions: true })\n      .option('-B', 'desc')\n      .option('-a', 'desc')\n      .option('-c', 'desc');\n    const helper = program.createHelp();\n    const visibleOptionNames = helper\n      .visibleOptions(program)\n      .map((cmd) => cmd.name());\n    expect(visibleOptionNames).toEqual(['a', 'B', 'c', 'help']);\n  });\n\n  test('when negated option then sort negated option separately', () => {\n    const program = new commander.Command();\n    program\n      .configureHelp({ sortOptions: true })\n      .option('--bbb', 'desc')\n      .option('--ccc', 'desc')\n      .option('--no-bbb', 'desc')\n      .option('--aaa', 'desc');\n    const helper = program.createHelp();\n    const visibleOptionNames = helper\n      .visibleOptions(program)\n      .map((cmd) => cmd.name());\n    expect(visibleOptionNames).toEqual(['aaa', 'bbb', 'ccc', 'help', 'no-bbb']);\n  });\n});\n"
  },
  {
    "path": "tests/help.stripAnsi.test.js",
    "content": "const { stripColor } = require('../lib/help');\n\n// https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters\n\n// Test the lowest level routine being used for SGR support.\n\nconst ESC = '\\u001b';\nconst CSI = ESC + '[';\n\ntest('SGR only', () => {\n  const str = `${CSI}4m`;\n  expect(stripColor(str)).toEqual('');\n});\n\ntest('SGR at start', () => {\n  const str = `${CSI}4mX`;\n  expect(stripColor(str)).toEqual('X');\n});\n\ntest('SGR in middle', () => {\n  const str = `X${CSI}4mY`;\n  expect(stripColor(str)).toEqual('XY');\n});\n\ntest('SGR at end', () => {\n  const str = `${CSI}4mY`;\n  expect(stripColor(str)).toEqual('Y');\n});\n\ntest('SGR pair', () => {\n  // underline and not underlined\n  const str = `${CSI}4mABC${CSI}24m`;\n  expect(stripColor(str)).toEqual('ABC');\n});\n\ntest('explicit reset with zero', () => {\n  const str = `${CSI}0m`;\n  expect(stripColor(str)).toEqual('');\n});\n\ntest('implicit reset without zero', () => {\n  const str = `${CSI}m`;\n  expect(stripColor(str)).toEqual('');\n});\n\ntest('multiple params: select foreground colour', () => {\n  const str = `${CSI}38;5;4m`;\n  expect(stripColor(str)).toEqual('');\n});\n\ntest('multiple params: general', () => {\n  const str = `${CSI}2;3;4m`;\n  expect(stripColor(str)).toEqual('');\n});\n\ntest('multiple params: missing param', () => {\n  // CSI sequences can omit number (which is then treated as 0)\n  const str = `${CSI};;m`;\n  expect(stripColor(str)).toEqual('');\n});\n\ntest('incomplete SGR sequence', () => {\n  const str = `${CSI}14X`;\n  expect(stripColor(str)).toEqual(`${CSI}14X`);\n});\n"
  },
  {
    "path": "tests/help.style.test.js",
    "content": "const { Command } = require('../');\n\nfunction red(str) {\n  // Use plain characters so not stripped in Jest failure messages. (Means displayWidth is bogus though.)\n  return `RED ${str} DER`;\n}\nfunction stripRed(str) {\n  return str.replace(/RED /g, '').replace(/ DER/g, '');\n}\nfunction displayWidth(str) {\n  // Not really zero width for the \"color\", but pretend so spacing matches no-color output.\n  return stripRed(str).length;\n}\n\ndescribe('override style methods and check help information', () => {\n  function makeProgram() {\n    const program = new Command('program')\n      .description('program description')\n      .argument('<file>', 'arg description')\n      .configureOutput({\n        getOutHasColors: () => true, // avoid interactions with testing environment\n      });\n    program\n      .command('subcommand')\n      .description('sub description')\n      .option('--suboption')\n      .argument('[subarg]');\n\n    return program;\n  }\n\n  const plainHelpInformation = makeProgram().helpInformation();\n\n  test('styleTitle', () => {\n    const program = makeProgram();\n    program.configureHelp({ styleTitle: (str) => red(str) }, displayWidth);\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation\n        .replace('Usage:', red('Usage:'))\n        .replace('Arguments:', red('Arguments:'))\n        .replace('Options:', red('Options:'))\n        .replace('Commands:', red('Commands:')),\n    );\n  });\n\n  test('styleUsage', () => {\n    const program = makeProgram();\n    program.configureHelp({ styleUsage: (str) => red(str), displayWidth });\n    const helpText = program.helpInformation();\n    const usageString = program.createHelp().commandUsage(program);\n    expect(helpText).toEqual(\n      plainHelpInformation.replace(usageString, red(usageString)),\n    );\n  });\n\n  test('styleCommandDescription', () => {\n    const program = makeProgram();\n    program.configureHelp({\n      styleCommandDescription: (str) => red(str),\n      displayWidth,\n    });\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation.replace(\n        'program description',\n        red('program description'),\n      ),\n    );\n  });\n\n  test('styleOptionDescription', () => {\n    const program = makeProgram();\n    program.configureHelp({\n      styleOptionDescription: (str) => red(str),\n      displayWidth,\n    });\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation.replace(\n        /(-h, --help *)(display help for command)/,\n        (match, p1, p2) => p1 + red(p2),\n      ),\n    );\n  });\n\n  test('styleSubcommandDescription', () => {\n    const program = makeProgram();\n    program.configureHelp({\n      styleSubcommandDescription: (str) => red(str),\n      displayWidth,\n    });\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation\n        .replace(\n          /(\\[subarg\\] *)(sub description)/,\n          (match, p1, p2) => p1 + red(p2),\n        )\n        .replace(\n          /(help \\[command\\] *)(display help for command)/,\n          (match, p1, p2) => p1 + red(p2),\n        ),\n    );\n  });\n\n  test('styleArgumentDescription', () => {\n    const program = makeProgram();\n    program.configureHelp({\n      styleArgumentDescription: (str) => red(str),\n      displayWidth,\n    });\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation.replace('arg description', red('arg description')),\n    );\n  });\n\n  test('styleDescriptionText', () => {\n    const program = makeProgram();\n    program.configureHelp({\n      styleDescriptionText: (str) => red(str),\n      displayWidth,\n    });\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation\n        .replace('program description', red('program description'))\n        .replace('arg description', red('arg description'))\n        .replace('sub description', red('sub description'))\n        .replace(/display help for command/g, red('display help for command')),\n    );\n  });\n\n  test('styleOptionTerm', () => {\n    const program = makeProgram();\n    program.configureHelp({ styleOptionTerm: (str) => red(str), displayWidth });\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation.replace('-h, --help', red('-h, --help')),\n    );\n  });\n\n  test('styleSubcommandTerm', () => {\n    const program = makeProgram();\n    program.configureHelp({\n      styleSubcommandTerm: (str) => red(str),\n      displayWidth,\n    });\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation\n        .replace('help [command]', red('help [command]'))\n        .replace(\n          'subcommand [options] [subarg]',\n          red('subcommand [options] [subarg]'),\n        ),\n    );\n  });\n\n  test('styleArgumentTerm', () => {\n    const program = makeProgram();\n    program.configureHelp({\n      styleArgumentTerm: (str) => red(str),\n      displayWidth,\n    });\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation.replace(' file ', ` ${red('file')} `),\n    );\n  });\n\n  test('styleOptionText', () => {\n    const program = makeProgram();\n    program.configureHelp({\n      styleOptionText: (str) => red(str),\n      displayWidth,\n    });\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation\n        .replace(/\\[options\\]/g, red('[options]'))\n        .replace('-h, --help', red('-h, --help')),\n    );\n  });\n\n  test('styleArgumentText', () => {\n    const program = makeProgram();\n    program.configureHelp({\n      styleArgumentText: (str) => red(str),\n      displayWidth,\n    });\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation\n        .replace('<file>', red('<file>'))\n        .replace(' file ', ` ${red('file')} `)\n        .replace('[subarg]', red('[subarg]'))\n        .replace('help [command]', `help ${red('[command]')}`),\n    );\n  });\n\n  test('styleSubcommandText', () => {\n    const program = makeProgram();\n    program.configureHelp({\n      styleSubcommandText: (str) => red(str),\n      displayWidth,\n    });\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation\n        .replace('[command] <file>', `${red('[command]')} <file>`)\n        .replace('help [command]', `${red('help')} [command]`)\n        .replace('subcommand', red('subcommand')),\n    );\n  });\n\n  test('styleCommandText', () => {\n    const program = makeProgram();\n    program.configureHelp({\n      styleCommandText: (str) => red(str),\n      displayWidth,\n    });\n    const helpText = program.helpInformation();\n    expect(helpText).toEqual(\n      plainHelpInformation.replace('program', red('program')),\n    );\n  });\n});\n\ndescribe('check styles with configureOutput overrides for color', () => {\n  function makeProgram(hasColors) {\n    const program = new Command('program');\n    program.myHelpText = [];\n    program\n      .description('program description')\n      .argument('<file>', 'arg description')\n      .configureOutput({\n        getOutHasColors: () => hasColors,\n        stripColor: (str) => stripRed(str),\n        writeOut: (str) => {\n          program.myHelpText.push(str);\n        },\n      });\n    program.configureHelp({\n      styleCommandText: (str) => red(str),\n      displayWidth,\n    });\n\n    return program;\n  }\n\n  test('when getOutHasColors returns true then help has color', () => {\n    const program = makeProgram(true);\n    program.outputHelp();\n    const helpText = program.myHelpText.join('');\n    expect(helpText).toMatch(red('program'));\n  });\n\n  test('when getOutHasColors returns false then help does not have color', () => {\n    const program = makeProgram(false);\n    program.outputHelp();\n    const helpText = program.myHelpText.join('');\n    expect(helpText).not.toMatch(red('program'));\n  });\n\n  test('when getOutHasColors returns false then style still called', () => {\n    const program = makeProgram(true);\n    // Overwrite styleCommandText so we can track whether called.\n    let styleCalled = false;\n    const config = program.configureHelp();\n    config.styleCommandText = (str) => {\n      styleCalled = true;\n      return red(str);\n    };\n    program.configureHelp(config);\n    program.outputHelp();\n    expect(styleCalled).toBe(true);\n  });\n});\n"
  },
  {
    "path": "tests/help.subcommandDescription.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('subcommandDescription', () => {\n  test('when program has no summary or description then empty string', () => {\n    const program = new commander.Command();\n    const helper = new commander.Help();\n    expect(helper.subcommandDescription(program)).toEqual('');\n  });\n\n  test('when program has summary then return summary', () => {\n    const summary = 'summary';\n    const program = new commander.Command();\n    program.summary(summary);\n    const helper = new commander.Help();\n    expect(helper.subcommandDescription(program)).toEqual(summary);\n  });\n\n  test('when program has description then return description', () => {\n    const description = 'description';\n    const program = new commander.Command();\n    program.description(description);\n    const helper = new commander.Help();\n    expect(helper.subcommandDescription(program)).toEqual(description);\n  });\n\n  test('when program has summary and description then return summary', () => {\n    const summary = 'summary';\n    const program = new commander.Command();\n    program.summary(summary);\n    program.description('description');\n    const helper = new commander.Help();\n    expect(helper.subcommandDescription(program)).toEqual(summary);\n  });\n});\n"
  },
  {
    "path": "tests/help.suggestion.test.js",
    "content": "const { Command, Option } = require('../');\n\n// Note: setting up shared command configuration in getSuggestion,\n// and looking for possible subcommand 'sub'.\n\nfunction getSuggestion(program, arg) {\n  let message = '';\n  program\n    .showSuggestionAfterError() // make sure on\n    .exitOverride()\n    .configureOutput({\n      writeErr: (str) => {\n        message = str;\n      },\n    });\n  // Do the same setup for subcommand.\n  const sub = program._findCommand('sub');\n  if (sub) sub.copyInheritedSettings(program);\n\n  try {\n    // Passing in an array for a few of the tests.\n    const args = Array.isArray(arg) ? arg : [arg];\n    program.parse(args, { from: 'user' });\n  } catch (err) {\n    /* empty */\n  }\n\n  const match = message.match(/Did you mean (one of )?(.*)\\?/);\n  return match ? match[2] : null;\n}\n\ntest.each([\n  ['yyy', ['zzz'], null, 'none similar'],\n  ['a', ['b'], null, 'one edit away but not similar'],\n  ['a', ['ab'], 'ab', 'one edit away'],\n  ['ab', ['a'], null, 'one edit away'],\n  ['at', ['cat'], 'cat', '1 insertion'],\n  ['cat', ['at'], 'at', '1 deletion'],\n  ['bat', ['cat'], 'cat', '1 substitution'],\n  ['act', ['cat'], 'cat', '1 transposition'],\n  ['cxx', ['cat'], null, '2 edits away and short string'],\n  ['caxx', ['cart'], 'cart', '2 edits away and longer string'],\n  [\n    '1234567',\n    ['1234567890'],\n    '1234567890',\n    '3 edits away is similar for long string',\n  ],\n  ['123456', ['1234567890'], null, '4 edits is too far'],\n  ['xat', ['rat', 'cat', 'bat'], 'bat, cat, rat', 'sorted possibles'],\n  [\n    'cart',\n    ['camb', 'cant', 'bard'],\n    'cant',\n    'only closest of different edit distances',\n  ],\n])(\n  'when cli of %s and commands %j then suggest %s because %s',\n  (arg, commandNames, expected) => {\n    const program = new Command();\n    commandNames.forEach((name) => {\n      program.command(name);\n    });\n    const suggestion = getSuggestion(program, arg);\n    expect(suggestion).toBe(expected);\n  },\n);\n\ntest('when similar alias then suggest alias', () => {\n  const program = new Command();\n  program.command('xyz').alias('car');\n  const suggestion = getSuggestion(program, 'bar');\n  expect(suggestion).toBe('car');\n});\n\ntest('when similar hidden alias then not suggested', () => {\n  const program = new Command();\n  program.command('xyz').alias('visible').alias('silent');\n  const suggestion = getSuggestion(program, 'slent');\n  expect(suggestion).toBe(null);\n});\n\ntest('when similar command and alias then suggest both', () => {\n  const program = new Command();\n  program.command('aaaaa').alias('cat');\n  program.command('bat');\n  program.command('ccccc');\n  const suggestion = getSuggestion(program, 'mat');\n  expect(suggestion).toBe('bat, cat');\n});\n\ntest('when implicit help command then help is candidate for suggestion', () => {\n  const program = new Command();\n  program.command('sub');\n  const suggestion = getSuggestion(program, 'hepl');\n  expect(suggestion).toBe('help');\n});\n\ntest('when help command disabled then not candidate for suggestion', () => {\n  const program = new Command();\n  program.addHelpCommand(false);\n  program.command('sub');\n  const suggestion = getSuggestion(program, 'hepl');\n  expect(suggestion).toBe(null);\n});\n\ntest('when default help option then --help is candidate for suggestion', () => {\n  const program = new Command();\n  const suggestion = getSuggestion(program, '--hepl');\n  expect(suggestion).toBe('--help');\n});\n\ntest('when custom help option then --custom-help is candidate for suggestion', () => {\n  const program = new Command();\n  program.helpOption('-H, --custom-help');\n  const suggestion = getSuggestion(program, '--custom-hepl');\n  expect(suggestion).toBe('--custom-help');\n});\n\ntest('when help option disabled then not candidate for suggestion', () => {\n  const program = new Command();\n  program.helpOption(false);\n  const suggestion = getSuggestion(program, '--hepl');\n  expect(suggestion).toBe(null);\n});\n\ntest('when command:* listener and unknown command then no suggestion', () => {\n  // Because one use for command:* was to handle unknown commands.\n  // Listener actually stops error being thrown, but we just care about affect on suggestion in this test.\n  const program = new Command();\n  program.on('command:*', () => {});\n  program.command('rat');\n  const suggestion = getSuggestion(program, 'cat');\n  expect(suggestion).toBe(null);\n});\n\n// Easy to just run same tests as for commands with cut and paste!\n// Note: length calculations disregard the leading --\ntest.each([\n  ['--yyy', ['--zzz'], null, 'none similar'],\n  ['--a', ['--b'], null, 'one edit away but not similar'],\n  ['--a', ['--ab'], '--ab', 'one edit away'],\n  ['--ab', ['--a'], null, 'one edit away'],\n  ['--at', ['--cat'], '--cat', '1 insertion'],\n  ['--cat', ['--at'], '--at', '1 deletion'],\n  ['--bat', ['--cat'], '--cat', '1 substitution'],\n  ['--act', ['--cat'], '--cat', '1 transposition'],\n  ['--cxx', ['--cat'], null, '2 edits away and short string'],\n  ['--caxx', ['--cart'], '--cart', '2 edits away and longer string'],\n  [\n    '--1234567',\n    ['--1234567890'],\n    '--1234567890',\n    '3 edits away is similar for long string',\n  ],\n  ['--123456', ['--1234567890'], null, '4 edits is too far'],\n  [\n    '--xat',\n    ['--rat', '--cat', '--bat'],\n    '--bat, --cat, --rat',\n    'sorted possibles',\n  ],\n  [\n    '--cart',\n    ['--camb', '--cant', '--bard'],\n    '--cant',\n    'only closest of different edit distances',\n  ],\n])(\n  'when cli of %s and options %j then suggest %s because %s',\n  (arg, commandNames, expected) => {\n    const program = new Command();\n    commandNames.forEach((name) => {\n      program.option(name);\n    });\n    const suggestion = getSuggestion(program, arg);\n    expect(suggestion).toBe(expected);\n  },\n);\n\ntest('when no options then no suggestion', () => {\n  // Checking nothing blows up as much as no suggestion!\n  const program = new Command();\n  program.helpOption(false);\n  const suggestion = getSuggestion(program, '--option');\n  expect(suggestion).toBe(null);\n});\n\ntest('when subcommand option then candidate for subcommand option suggestion', () => {\n  const program = new Command();\n  program.command('sub').option('-l,--local');\n  const suggestion = getSuggestion(program, ['sub', '--loca']);\n  expect(suggestion).toBe('--local');\n});\n\ntest('when global option then candidate for subcommand option suggestion', () => {\n  const program = new Command();\n  program.option('-g, --global');\n  program.command('sub');\n  const suggestion = getSuggestion(program, ['sub', '--globla']);\n  expect(suggestion).toBe('--global');\n});\n\ntest('when global option but positionalOptions then not candidate for subcommand suggestion', () => {\n  const program = new Command();\n  program.enablePositionalOptions();\n  program.option('-g, --global');\n  program.command('sub');\n  const suggestion = getSuggestion(program, ['sub', '--globla']);\n  expect(suggestion).toBe(null);\n});\n\ntest('when global and local options then both candidates', () => {\n  const program = new Command();\n  program.option('--cat');\n  program.command('sub').option('--rat');\n  const suggestion = getSuggestion(program, ['sub', '--bat']);\n  expect(suggestion).toBe('--cat, --rat');\n});\n\ntest('when command hidden then not suggested as candidate', () => {\n  const program = new Command();\n  program.command('secret', { hidden: true });\n  const suggestion = getSuggestion(program, 'secrt');\n  expect(suggestion).toBe(null);\n});\n\ntest('when option hidden then not suggested as candidate', () => {\n  const program = new Command();\n  program.addOption(new Option('--secret').hideHelp());\n  const suggestion = getSuggestion(program, '--secrt');\n  expect(suggestion).toBe(null);\n});\n\ntest('when may be duplicate identical candidates then only return one', () => {\n  const program = new Command();\n  program.command('sub');\n  const suggestion = getSuggestion(program, ['sub', '--hepl']);\n  expect(suggestion).toBe('--help');\n});\n"
  },
  {
    "path": "tests/help.visibleArguments.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('visibleArguments', () => {\n  test('when no arguments then empty array', () => {\n    const program = new commander.Command();\n    const helper = new commander.Help();\n    expect(helper.visibleArguments(program)).toEqual([]);\n  });\n\n  test('when argument but no argument description then empty array', () => {\n    const program = new commander.Command();\n    program.argument('<file>');\n    const helper = new commander.Help();\n    expect(helper.visibleArguments(program)).toEqual([]);\n  });\n\n  test('when argument and argument description then returned', () => {\n    const program = new commander.Command();\n    program.argument('<file>', 'file description');\n    const helper = new commander.Help();\n    const visibleArguments = helper.visibleArguments(program);\n    expect(visibleArguments.length).toEqual(1);\n    expect(visibleArguments[0]).toEqual(\n      new commander.Argument('<file>', 'file description'),\n    );\n  });\n\n  test('when argument and legacy argument description then returned', () => {\n    const program = new commander.Command();\n    program.argument('<file>');\n    program.description('', {\n      file: 'file description',\n    });\n    const helper = new commander.Help();\n    const visibleArguments = helper.visibleArguments(program);\n    expect(visibleArguments.length).toEqual(1);\n    expect(visibleArguments[0]).toEqual(\n      new commander.Argument('<file>', 'file description'),\n    );\n  });\n\n  test('when arguments and some described then all returned', () => {\n    const program = new commander.Command();\n    program.argument('<file1>', 'file1 description');\n    program.argument('<file2>');\n    const helper = new commander.Help();\n    const visibleArguments = helper.visibleArguments(program);\n    expect(visibleArguments.length).toEqual(2);\n    expect(visibleArguments[0]).toEqual(\n      new commander.Argument('<file1>', 'file1 description'),\n    );\n    expect(visibleArguments[1]).toEqual(new commander.Argument('<file2>'));\n  });\n\n  test('when arguments and some legacy described then all returned', () => {\n    const program = new commander.Command();\n    program.argument('<file1>');\n    program.argument('<file2>');\n    program.description('', {\n      file1: 'file1 description',\n    });\n    const helper = new commander.Help();\n    const visibleArguments = helper.visibleArguments(program);\n    expect(visibleArguments.length).toEqual(2);\n    expect(visibleArguments[0]).toEqual(\n      new commander.Argument('<file1>', 'file1 description'),\n    );\n    expect(visibleArguments[1]).toEqual(new commander.Argument('<file2>'));\n  });\n});\n"
  },
  {
    "path": "tests/help.visibleCommands.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('visibleCommands', () => {\n  test('when no subcommands then empty array', () => {\n    const program = new commander.Command();\n    const helper = new commander.Help();\n    expect(helper.visibleCommands(program)).toEqual([]);\n  });\n\n  test('when add command then visible (with help)', () => {\n    const program = new commander.Command();\n    program.command('sub');\n    const helper = new commander.Help();\n    const visibleCommandNames = helper\n      .visibleCommands(program)\n      .map((cmd) => cmd.name());\n    expect(visibleCommandNames).toEqual(['sub', 'help']);\n  });\n\n  test('when commands hidden then not visible', () => {\n    const program = new commander.Command();\n    program\n      .command('visible', 'desc')\n      .command('invisible-executable', 'desc', { hidden: true });\n    program.command('invisible-action', { hidden: true });\n    const helper = new commander.Help();\n    const visibleCommandNames = helper\n      .visibleCommands(program)\n      .map((cmd) => cmd.name());\n    expect(visibleCommandNames).toEqual(['visible', 'help']);\n  });\n});\n"
  },
  {
    "path": "tests/help.visibleGlobalOptions.test.js",
    "content": "const commander = require('../');\n\ntest('when default configuration then return empty array', () => {\n  const program = new commander.Command();\n  program.option('--global');\n  const sub = program.command('sub');\n  const helper = sub.createHelp();\n  expect(helper.visibleGlobalOptions(program)).toEqual([]);\n});\n\ntest('when showGlobalOptions:true then return program options', () => {\n  const program = new commander.Command();\n  program.option('--global').configureHelp({ showGlobalOptions: true });\n  const sub = program.command('sub');\n  const helper = sub.createHelp();\n  const visibleOptionNames = helper\n    .visibleGlobalOptions(sub)\n    .map((option) => option.name());\n  expect(visibleOptionNames).toEqual(['global']);\n});\n\ntest('when showGlobalOptions:true and program has version then return version', () => {\n  const program = new commander.Command();\n  program.configureHelp({ showGlobalOptions: true }).version('1.2.3');\n  const sub = program.command('sub');\n  const helper = sub.createHelp();\n  const visibleOptionNames = helper\n    .visibleGlobalOptions(sub)\n    .map((option) => option.name());\n  expect(visibleOptionNames).toEqual(['version']);\n});\n\ntest('when showGlobalOptions:true and nested commands then return combined global options', () => {\n  const program = new commander.Command();\n  program.configureHelp({ showGlobalOptions: true }).option('--global');\n  const sub1 = program.command('sub1').option('--sub1');\n  const sub2 = sub1.command('sub2');\n  const helper = sub2.createHelp();\n  const visibleOptionNames = helper\n    .visibleGlobalOptions(sub2)\n    .map((option) => option.name());\n  expect(visibleOptionNames).toEqual(['sub1', 'global']);\n});\n"
  },
  {
    "path": "tests/help.visibleOptions.test.js",
    "content": "const commander = require('../');\n\n// These are tests of the Help class, not of the Command help.\n// There is some overlap with the higher level Command tests (which predate Help).\n\ndescribe('visibleOptions', () => {\n  test('when no options then just help visible', () => {\n    const program = new commander.Command();\n    const helper = new commander.Help();\n    const visibleOptionNames = helper\n      .visibleOptions(program)\n      .map((option) => option.name());\n    expect(visibleOptionNames).toEqual(['help']);\n  });\n\n  test('when no options and no help option then empty array', () => {\n    const program = new commander.Command();\n    program.helpOption(false);\n    const helper = new commander.Help();\n    expect(helper.visibleOptions(program)).toEqual([]);\n  });\n\n  test('when add option then visible (with help)', () => {\n    const program = new commander.Command();\n    program.option('-v,--visible');\n    const helper = new commander.Help();\n    const visibleOptionNames = helper\n      .visibleOptions(program)\n      .map((option) => option.name());\n    expect(visibleOptionNames).toEqual(['visible', 'help']);\n  });\n\n  test('when option hidden then not visible', () => {\n    const program = new commander.Command();\n    program\n      .option('-v,--visible')\n      .addOption(new commander.Option('--invisible').hideHelp());\n    const helper = new commander.Help();\n    const visibleOptionNames = helper\n      .visibleOptions(program)\n      .map((option) => option.name());\n    expect(visibleOptionNames).toEqual(['visible', 'help']);\n  });\n});\n\ndescribe('implicit help', () => {\n  test('when default then help term is -h, --help', () => {\n    const program = new commander.Command();\n    const helper = new commander.Help();\n    const implicitHelp = helper.visibleOptions(program)[0];\n    expect(helper.optionTerm(implicitHelp)).toEqual('-h, --help');\n  });\n\n  test('when short flag obscured then help term is --help', () => {\n    const program = new commander.Command();\n    program.addOption(new commander.Option('-h, --huge').hideHelp());\n    const helper = new commander.Help();\n    const implicitHelp = helper.visibleOptions(program)[0];\n    expect(helper.optionTerm(implicitHelp)).toEqual('--help');\n  });\n\n  test('when long flag obscured then help term is --h', () => {\n    const program = new commander.Command();\n    program.addOption(new commander.Option('-H, --help').hideHelp());\n    const helper = new commander.Help();\n    const implicitHelp = helper.visibleOptions(program)[0];\n    expect(helper.optionTerm(implicitHelp)).toEqual('-h');\n  });\n\n  test('when help flags obscured then implicit help hidden', () => {\n    const program = new commander.Command();\n    program.addOption(new commander.Option('-h, --help').hideHelp());\n    const helper = new commander.Help();\n    expect(helper.visibleOptions(program)).toEqual([]);\n  });\n});\n"
  },
  {
    "path": "tests/helpGroup.test.js",
    "content": "const { Command, Option } = require('../');\n\n// Similar tests for Option.helpGroup() and Command.helpGroup(),\n// and for Command.optionsGroup() and Command.commandsGroup().\n\ndescribe('Option.helpGroup', () => {\n  test('when add one option with helpGroup then help contains group', () => {\n    const program = new Command();\n    program.addOption(new Option('--alpha').helpGroup('Greek:'));\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *--alpha/);\n  });\n\n  test('when add two options with helpGroup then help contains group', () => {\n    const program = new Command();\n    program.addOption(new Option('--alpha').helpGroup('Greek:'));\n    program.addOption(new Option('--beta').helpGroup('Greek:'));\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *--alpha\\n *--beta/);\n  });\n});\n\ndescribe('Command.helpGroup', () => {\n  test('when add one command with helpGroup then help contains group', () => {\n    const program = new Command();\n    program.command('alpha').helpGroup('Greek:');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *alpha/);\n  });\n\n  test('when add two commands with helpGroup then help contains group', () => {\n    const program = new Command();\n    program.command('alpha').helpGroup('Greek:');\n    program.command('beta').helpGroup('Greek:');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *alpha\\n *beta/);\n  });\n});\n\ndescribe('.optionsGroup', () => {\n  test('when add one option then help contains group', () => {\n    const program = new Command();\n    program.optionsGroup('Greek:');\n    program.option('--alpha');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *--alpha/);\n  });\n\n  test('when add two options then help contains group with two options', () => {\n    const program = new Command();\n    program.optionsGroup('Greek:');\n    program.option('--alpha');\n    program.option('--beta');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *--alpha\\n *--beta/);\n  });\n\n  test('when add options with different groups then help contains two groups', () => {\n    const program = new Command();\n    program.optionsGroup('Greek:');\n    program.option('--alpha');\n    program.optionsGroup('Latin:');\n    program.option('--unus');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *--alpha/);\n    expect(helpInfo).toMatch(/Latin:\\n *--unus/);\n  });\n\n  test('when implicit help option then help option not affected', () => {\n    const program = new Command();\n    program.optionsGroup('Greek:');\n    program.option('--alpha');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Options:\\n *-h, --help/);\n  });\n\n  test('when option with helpGroup then helpGroup wins', () => {\n    const program = new Command();\n    program.optionsGroup('Greek:');\n    program.addOption(new Option('--unus').helpGroup('Latin:'));\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Latin:\\n *--unus/);\n  });\n\n  test('when add no options with heading then heading does not appear', () => {\n    const program = new Command();\n    program.optionsGroup('Greek:');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).not.toMatch(/Greek/);\n  });\n\n  test('when add no visible options with heading then heading does not appear', () => {\n    const program = new Command();\n    program.optionsGroup('Greek:');\n    program.addOption(new Option('--alpha').hideHelp());\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).not.toMatch(/Greek/);\n  });\n\n  test('when .helpOption(flags) then help option in group', () => {\n    const program = new Command();\n    program.optionsGroup('Greek:');\n    program.helpOption('--assist');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *--assist/);\n  });\n\n  test('when .helpOption(true) then help option in group', () => {\n    const program = new Command();\n    program.optionsGroup('Greek:');\n    program.helpOption(true);\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *-h, --help/);\n  });\n\n  test('when .version(str) then version option in group', () => {\n    const program = new Command();\n    program.optionsGroup('Greek:');\n    program.version('1.2.3');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *-V, --version/);\n  });\n\n  test('when set sortOptions then options are sorted within groups', () => {\n    const program = new Command();\n    program.configureHelp({ sortOptions: true });\n    program.optionsGroup('Latin:');\n    program.option('--unus');\n    program.option('--duo');\n    program.optionsGroup('Greek:');\n    program.option('--beta');\n    program.option('--alpha');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Latin:\\n *--duo\\n *--unus/);\n    expect(helpInfo).toMatch(/Greek:\\n *--alpha\\n *--beta/);\n  });\n\n  test('when set sortOptions then groups are in order added not sorted', () => {\n    const program = new Command();\n    program.configureHelp({ sortOptions: true });\n    program.addOption(new Option('--bbb').helpGroup('BBB:'));\n    program.addOption(new Option('--ccc').helpGroup('CCC:'));\n    program.addOption(new Option('--aaa').helpGroup('AAA:'));\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(\n      /BBB:\\n *--bbb.*\\n\\nCCC:\\n *--ccc.*\\n\\nAAA:\\n *--aaa/,\n    );\n  });\n});\n\ndescribe('.commandsGroup', () => {\n  test('when add one command then help contains group', () => {\n    const program = new Command();\n    program.commandsGroup('Greek:');\n    program.command('alpha');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *alpha/);\n  });\n\n  test('when add two commands then help contains group with two commands', () => {\n    const program = new Command();\n    program.commandsGroup('Greek:');\n    program.command('alpha');\n    program.command('beta');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *alpha\\n *beta/);\n  });\n\n  test('when add commands with different groups then help contains two groups', () => {\n    const program = new Command();\n    program.commandsGroup('Greek:');\n    program.command('alpha');\n    program.commandsGroup('Latin:');\n    program.command('unus');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *alpha/);\n    expect(helpInfo).toMatch(/Latin:\\n *unus/);\n  });\n\n  test('when implicit help command then help command not affected', () => {\n    const program = new Command();\n    program.commandsGroup('Greek:');\n    program.command('alpha');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Commands:\\n *help/);\n  });\n\n  test('when command with custom helpGroup then helpGroup wins', () => {\n    const program = new Command();\n    program.commandsGroup('Greek:');\n    program.command('unus').helpGroup('Latin:');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Latin:\\n *unus/);\n  });\n\n  test('when add no commands with heading then heading does not appear', () => {\n    const program = new Command();\n    program.commandsGroup('Greek:');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).not.toMatch(/Greek/);\n  });\n\n  test('when add no visible command with heading then heading does not appear', () => {\n    const program = new Command();\n    program.commandsGroup('Greek:');\n    program.command('alpha', { hidden: true });\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).not.toMatch(/Greek/);\n  });\n\n  test('when .helpCommand(name) then help command in group', () => {\n    const program = new Command();\n    program.command('foo');\n    program.commandsGroup('Greek:');\n    program.helpCommand('assist');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *assist/);\n  });\n\n  test('when .helpCommand(true) then help command in group', () => {\n    const program = new Command();\n    program.command('foo');\n    program.commandsGroup('Greek:');\n    program.helpCommand(true);\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Greek:\\n *help/);\n  });\n\n  test('when set sortCommands then commands are sorted within groups', () => {\n    const program = new Command();\n    program.configureHelp({ sortSubcommands: true });\n    program.commandsGroup('Latin:');\n    program.command('unus');\n    program.command('duo');\n    program.commandsGroup('Greek:');\n    program.command('beta');\n    program.command('alpha');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/Latin:\\n *duo\\n *unus/);\n    expect(helpInfo).toMatch(/Greek:\\n *alpha\\n *beta/);\n  });\n\n  test('when set sortOptions then groups are in order added not sorted', () => {\n    const program = new Command();\n    program.configureHelp({ sortSubcommands: true });\n    program.command('bbb').helpGroup('BBB:');\n    program.command('ccc').helpGroup('CCC:');\n    program.command('aaa').helpGroup('AAA:');\n    const helpInfo = program.helpInformation();\n    expect(helpInfo).toMatch(/BBB:\\n *bbb.*\\n\\nCCC:\\n *ccc.*\\n\\nAAA:\\n *aaa/);\n  });\n});\n"
  },
  {
    "path": "tests/incrementNodeInspectorPort.test.js",
    "content": "const childProcess = require('child_process');\nconst path = require('path');\nconst commander = require('../');\n\ndescribe('incrementNodeInspectorPort', () => {\n  let spawnSpy;\n  let signalSpy;\n  const oldExecArgv = process.execArgv;\n\n  beforeAll(() => {\n    spawnSpy = jest.spyOn(childProcess, 'spawn').mockImplementation(() => {\n      return {\n        on: () => {},\n      };\n    });\n    signalSpy = jest.spyOn(process, 'on').mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    spawnSpy.mockClear();\n  });\n\n  afterAll(() => {\n    spawnSpy.mockRestore();\n    signalSpy.mockRestore();\n    process.execArgv = oldExecArgv;\n  });\n\n  function makeProgram() {\n    const program = new commander.Command();\n    const fileWhichExists = path.join(__dirname, './fixtures/pm-cache.js');\n    program.command('cache', 'stand-alone command', {\n      executableFile: fileWhichExists,\n    });\n    return program;\n  }\n\n  function extractMockExecArgs(mock) {\n    return mock.mock.calls[0][1].slice(0, -1);\n  }\n\n  test('when --inspect then bump port', () => {\n    const program = makeProgram();\n    process.execArgv = ['--inspect'];\n    program.parse(['node', 'test', 'cache']);\n    const execArgs = extractMockExecArgs(spawnSpy);\n    expect(execArgs).toEqual(['--inspect=127.0.0.1:9230']);\n  });\n\n  test('when --inspect=100 then bump port', () => {\n    const program = makeProgram();\n    process.execArgv = ['--inspect=100'];\n    program.parse(['node', 'test', 'cache']);\n    const execArgs = extractMockExecArgs(spawnSpy);\n    expect(execArgs).toEqual(['--inspect=127.0.0.1:101']);\n  });\n\n  test('when --inspect=1.2.3.4:100 then bump port', () => {\n    const program = makeProgram();\n    process.execArgv = ['--inspect=1.2.3.4:100'];\n    program.parse(['node', 'test', 'cache']);\n    const execArgs = extractMockExecArgs(spawnSpy);\n    expect(execArgs).toEqual(['--inspect=1.2.3.4:101']);\n  });\n\n  test('when --inspect=1.2.3.4 then bump port', () => {\n    const program = makeProgram();\n    process.execArgv = ['--inspect=1.2.3.4'];\n    program.parse(['node', 'test', 'cache']);\n    const execArgs = extractMockExecArgs(spawnSpy);\n    expect(execArgs).toEqual(['--inspect=1.2.3.4:9230']);\n  });\n\n  test('when --inspect-brk then bump port', () => {\n    const program = makeProgram();\n    process.execArgv = ['--inspect-brk'];\n    program.parse(['node', 'test', 'cache']);\n    const execArgs = extractMockExecArgs(spawnSpy);\n    expect(execArgs).toEqual(['--inspect-brk=127.0.0.1:9230']);\n  });\n\n  test('when --inspect-brk=100 then bump port', () => {\n    const program = makeProgram();\n    process.execArgv = ['--inspect-brk=100'];\n    program.parse(['node', 'test', 'cache']);\n    const execArgs = extractMockExecArgs(spawnSpy);\n    expect(execArgs).toEqual(['--inspect-brk=127.0.0.1:101']);\n  });\n\n  test('when --inspect-brk=1.2.3.4 then bump port', () => {\n    const program = makeProgram();\n    process.execArgv = ['--inspect-brk=1.2.3.4'];\n    program.parse(['node', 'test', 'cache']);\n    const execArgs = extractMockExecArgs(spawnSpy);\n    expect(execArgs).toEqual(['--inspect-brk=1.2.3.4:9230']);\n  });\n\n  test('when --inspect-brk=1.2.3.4:100 then bump port', () => {\n    const program = makeProgram();\n    process.execArgv = ['--inspect-brk=1.2.3.4:100'];\n    program.parse(['node', 'test', 'cache']);\n    const execArgs = extractMockExecArgs(spawnSpy);\n    expect(execArgs).toEqual(['--inspect-brk=1.2.3.4:101']);\n  });\n\n  test('when --inspect-port=100 then bump port', () => {\n    const program = makeProgram();\n    process.execArgv = ['--inspect-port=100'];\n    program.parse(['node', 'test', 'cache']);\n    const execArgs = extractMockExecArgs(spawnSpy);\n    expect(execArgs).toEqual(['--inspect-port=127.0.0.1:101']);\n  });\n\n  test('when --inspect-port=1.2.3.4:100 then bump port', () => {\n    const program = makeProgram();\n    process.execArgv = ['--inspect-port=1.2.3.4:100'];\n    program.parse(['node', 'test', 'cache']);\n    const execArgs = extractMockExecArgs(spawnSpy);\n    expect(execArgs).toEqual(['--inspect-port=1.2.3.4:101']);\n  });\n\n  test('when --inspect-unexpected then unchanged', () => {\n    const program = makeProgram();\n    process.execArgv = ['--inspect-unexpected'];\n    program.parse(['node', 'test', 'cache']);\n    const execArgs = extractMockExecArgs(spawnSpy);\n    expect(execArgs).toEqual(['--inspect-unexpected']);\n  });\n\n  test('when --frozen-intrinsics  then unchanged', () => {\n    const program = makeProgram();\n    process.execArgv = ['--frozen-intrinsics '];\n    program.parse(['node', 'test', 'cache']);\n    const execArgs = extractMockExecArgs(spawnSpy);\n    expect(execArgs).toEqual(['--frozen-intrinsics ']);\n  });\n});\n"
  },
  {
    "path": "tests/negatives.test.js",
    "content": "const { Command } = require('../');\n\n// boolean is whether is a consumable argument when negative numbers allowed\nconst negativeNumbers = [\n  ['-.1', true],\n  ['-123', true],\n  ['-123.45', true],\n  ['-1e3', true],\n  ['-1e+3', true],\n  ['-1e-3', true],\n  ['-1.2e3', true],\n  ['-1.2e+3', true],\n  ['-1.2e-3', true],\n  ['-1e-3.0', false], // invalid number format\n  ['--1 ', false], // invalid number format\n  ['-0', true],\n  ['1', true],\n  ['-1x', false], // whole string is not a number\n  ['-x-1 ', false], // whole string is not a number\n  ['', true],\n  ['-0x1234', false], // not a plain number\n];\n\ntest.each(negativeNumbers)(\n  `when option-argument for short optional is %s then consumed=%s`,\n  (value, consume) => {\n    const program = new Command();\n    program.exitOverride().configureOutput({ writeErr: () => {} });\n    program.option('-o, --optional [value]', 'optional option');\n    const args = ['-o', value];\n    let thrown = '';\n    try {\n      program.parse(args, { from: 'user' });\n    } catch (err) {\n      thrown = err.code;\n    }\n\n    expect(thrown).toEqual(consume ? '' : 'commander.unknownOption');\n    // throws after setting optional to true\n    expect(program.opts()['optional']).toBe(consume ? value : true);\n  },\n);\n\ntest.each(negativeNumbers)(\n  `when option-argument for long optional is %s then consumed=%s`,\n  (value, consume) => {\n    const program = new Command();\n    program.exitOverride().configureOutput({ writeErr: () => {} });\n    program.option('-o, --optional [value]', 'optional option');\n    const args = ['--optional', value];\n    let thrown = '';\n    try {\n      program.parse(args, { from: 'user' });\n    } catch (err) {\n      thrown = err.code;\n    }\n\n    expect(thrown).toEqual(consume ? '' : 'commander.unknownOption');\n    // throws after setting optional to true\n    expect(program.opts()['optional']).toBe(consume ? value : true);\n  },\n);\n\ntest.each(negativeNumbers)(\n  `when option-argument for short optional... is %s then consumed=%s`,\n  (value, consume) => {\n    const program = new Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeErr: () => {} })\n      .option('-o, --optional [value...]', 'optional option');\n    const args = ['-o', 'first', value];\n    let thrown = '';\n    try {\n      program.parse(args, { from: 'user' });\n    } catch (err) {\n      thrown = err.code;\n    }\n\n    expect(thrown).toEqual(consume ? '' : 'commander.unknownOption');\n    // throws after consuming 'first'\n    expect(program.opts()['optional']).toEqual(\n      consume ? ['first', value] : ['first'],\n    );\n  },\n);\n\ntest.each(negativeNumbers)(\n  `when option-argument for long optional... is %s then consumed=%s`,\n  (value, consume) => {\n    const program = new Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeErr: () => {} })\n      .option('-o, --optional [value...]', 'optional option');\n    const args = ['--optional', 'first', value];\n    let thrown = '';\n    try {\n      program.parse(args, { from: 'user' });\n    } catch (err) {\n      thrown = err.code;\n    }\n\n    expect(thrown).toEqual(consume ? '' : 'commander.unknownOption');\n    // throws after consuming 'first'\n    expect(program.opts()['optional']).toEqual(\n      consume ? ['first', value] : ['first'],\n    );\n  },\n);\n\ntest.each(negativeNumbers)(\n  `when command-argument is %s then consumed=%s`,\n  (value, consume) => {\n    const program = new Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeErr: () => {} })\n      .argument('<value>', 'argument');\n    const args = [value];\n    let thrown = '';\n    try {\n      program.parse(args, { from: 'user' });\n    } catch (err) {\n      thrown = err.code;\n    }\n\n    expect(thrown).toEqual(consume ? '' : 'commander.unknownOption');\n    expect(consume ? program.args : undefined).toEqual(\n      consume ? [value] : undefined,\n    );\n  },\n);\n\ntest.each(negativeNumbers)(\n  `when digit option defined and option-argument is %s then negative not consumed`,\n  (value, _ignore) => {\n    const program = new Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeErr: () => {} })\n      .option('-o, --optional [value]', 'optional option')\n      .option('-9', 'register option using digit');\n    const args = ['-o', value];\n    let thrown = '';\n    try {\n      program.parse(args, { from: 'user' });\n    } catch (err) {\n      thrown = err.code;\n    }\n\n    let consume = value[0] !== '-';\n    expect(thrown).toEqual(consume ? '' : 'commander.unknownOption');\n    expect(program.opts()['optional']).toBe(consume ? value : true);\n  },\n);\n\ntest.each(negativeNumbers)(\n  `when digit option defined and command-argument is %s then negative not consumed`,\n  (value, _ignore) => {\n    const program = new Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeErr: () => {} })\n      .argument('[value]')\n      .option('-9', 'register option using digit');\n    const args = [value];\n    let thrown = '';\n    try {\n      program.parse(args, { from: 'user' });\n    } catch (err) {\n      thrown = err.code;\n    }\n\n    let consume = value[0] !== '-';\n    expect(thrown).toEqual(consume ? '' : 'commander.unknownOption');\n    expect(consume ? program.args : undefined).toEqual(\n      consume ? [value] : undefined,\n    );\n  },\n);\n\ntest('when complex example with negative numbers then all consumed', () => {\n  const program = new Command();\n  program\n    .option('-o [value]', 'optional')\n    .option('-m <value>', 'required option-argument')\n    .option('-O [value...]', 'optional')\n    .option('-M <value...>', 'required option-argument')\n    .argument('[value...]', 'argument');\n  const args = [\n    '-10',\n    '-O',\n    '-40',\n    '-41',\n    '-M',\n    '-50',\n    '-51',\n    '-o',\n    '-20',\n    '-m',\n    '-30',\n    '-11',\n  ];\n  program.parse(args, { from: 'user' });\n  expect(program.opts()).toEqual({\n    o: '-20',\n    m: '-30',\n    O: ['-40', '-41'],\n    M: ['-50', '-51'],\n  });\n  expect(program.args).toEqual(['-10', '-11']);\n});\n\ntest('when program has digit option then negatives not allowed in leaf command', () => {\n  const program = new Command();\n  program\n    .exitOverride()\n    .configureOutput({ writeErr: () => {} })\n    .option('-2', 'double option');\n  let leafArgs;\n  program\n    .command('leaf')\n    .argument('[value...]')\n    .action((args) => {\n      leafArgs = args;\n    });\n  const args = ['leaf', '-1'];\n  expect(() => program.parse(args, { from: 'user' })).toThrow();\n});\n\ntest('when default command without digit option then negatives accepted', () => {\n  const program = new Command();\n  let leafArgs;\n  program\n    .command('leaf', { isDefault: true })\n    .argument('[value...]')\n    .action((args) => {\n      leafArgs = args;\n    });\n  program.parse(['-1'], { from: 'user' });\n  expect(leafArgs).toEqual(['-1']);\n});\n\ntest('when default command with digit option then negative throws', () => {\n  const program = new Command();\n  program.exitOverride().configureOutput({ writeErr: () => {} });\n  program\n    .command('leaf', { isDefault: true })\n    .option('-2')\n    .argument('[value...]')\n    .action(() => {});\n  expect(() => program.parse(['-1'], { from: 'user' })).toThrow();\n});\n\ntest('when program has subcommand and action handler then negative command-argument unsupported', () => {\n  // Known limitation in parsing. Only allowed negative command-arguments in leaf commands\n  // to minimise changes to parsing when added support for negative numbers.\n  const program = new Command();\n  program\n    .exitOverride()\n    .configureOutput({ writeErr: () => {} })\n    .argument('[value...]')\n    .action(() => {});\n  program.command('leaf').action(() => {});\n  expect(() => program.parse(['-1'], { from: 'user' })).toThrow();\n});\n"
  },
  {
    "path": "tests/option.bad-flags.test.js",
    "content": "const { Option } = require('../');\n\n// Check that unsupported flags throw.\ntest.each([\n  { flags: '-a, -b' }, // too many short flags\n  { flags: '-a, -b <value>' },\n  { flags: '-a, -b, --long' },\n  { flags: '--one, --two, --three' }, // too many long flags\n  { flags: '-ws' }, // short flag with more than one character\n  { flags: '---triple' }, // double dash not followed by a non-dash\n  { flags: 'sdkjhskjh' }, // oops, no flags\n  { flags: '-a,-b' }, // try all the separators\n  { flags: '-a|-b' },\n  { flags: '-a -b' },\n])('when construct Option with flags %p then throw', ({ flags }) => {\n  expect(() => {\n    new Option(flags);\n  }).toThrow(/^option creation failed/);\n});\n\n// Check that supported flags do not throw.\ntest.each([\n  { flags: '-s' }, // single short\n  { flags: '--long' }, // single long\n  { flags: '-b, --both' }, // short and long\n  { flags: '--both, -b' }, // long and short\n  { flags: '--ws, --workspace' }, // two long (morally shortish and long)\n  { flags: '-b,--both <comma>' },\n  { flags: '-b|--both <bar>' },\n  { flags: '-b --both [space]' },\n  { flags: '-v, --variadic <files...>' },\n])('when construct Option with flags %p then do not throw', ({ flags }) => {\n  expect(() => {\n    new Option(flags);\n  }).not.toThrow();\n});\n"
  },
  {
    "path": "tests/option.chain.test.js",
    "content": "const { Option } = require('../');\n\ndescribe('Option methods that should return this for chaining', () => {\n  test('when call .default() then returns this', () => {\n    const option = new Option('-e,--example <value>');\n    const result = option.default(3);\n    expect(result).toBe(option);\n  });\n\n  test('when call .argParser() then returns this', () => {\n    const option = new Option('-e,--example <value>');\n    const result = option.argParser(() => {});\n    expect(result).toBe(option);\n  });\n\n  test('when call .makeOptionMandatory() then returns this', () => {\n    const option = new Option('-e,--example <value>');\n    const result = option.makeOptionMandatory();\n    expect(result).toBe(option);\n  });\n\n  test('when call .hideHelp() then returns this', () => {\n    const option = new Option('-e,--example <value>');\n    const result = option.hideHelp();\n    expect(result).toBe(option);\n  });\n\n  test('when call .choices() then returns this', () => {\n    const option = new Option('-e,--example <value>');\n    const result = option.choices(['a']);\n    expect(result).toBe(option);\n  });\n\n  test('when call .env() then returns this', () => {\n    const option = new Option('-e,--example <value>');\n    const result = option.env('e');\n    expect(result).toBe(option);\n  });\n\n  test('when call .conflicts() then returns this', () => {\n    const option = new Option('-e,--example <value>');\n    const result = option.conflicts(['a']);\n    expect(result).toBe(option);\n  });\n\n  test('when call .helpGroup(heading) then returns this', () => {\n    const option = new Option('-e,--example <value>');\n    const result = option.helpGroup('Options:');\n    expect(result).toBe(option);\n  });\n});\n"
  },
  {
    "path": "tests/options.bool.combo.test.js",
    "content": "const commander = require('../');\n\n// Test combination of flag and --no-flag\n// (single flags tested in options.bool.test.js)\n\n// boolean option combo with no default\ndescribe('boolean option combo with no default', () => {\n  function createPepperProgram() {\n    const program = new commander.Command();\n    program\n      .option('-p, --pepper', 'add pepper')\n      .option('-P, --no-pepper', 'remove pepper');\n    return program;\n  }\n\n  test('when boolean combo not specified then value is undefined', () => {\n    const program = createPepperProgram();\n    program.parse(['node', 'test']);\n    expect(program.opts().pepper).toBeUndefined();\n  });\n\n  test('when boolean combo positive then value is true', () => {\n    const program = createPepperProgram();\n    program.parse(['node', 'test', '--pepper']);\n    expect(program.opts().pepper).toBe(true);\n  });\n\n  test('when boolean combo negative then value is false', () => {\n    const program = createPepperProgram();\n    program.parse(['node', 'test', '--no-pepper']);\n    expect(program.opts().pepper).toBe(false);\n  });\n\n  test('when boolean combo last is positive then value is true', () => {\n    const program = createPepperProgram();\n    program.parse(['node', 'test', '--no-pepper', '--pepper']);\n    expect(program.opts().pepper).toBe(true);\n  });\n\n  test('when boolean combo last is negative then value is false', () => {\n    const program = createPepperProgram();\n    program.parse(['node', 'test', '--pepper', '--no-pepper']);\n    expect(program.opts().pepper).toBe(false);\n  });\n});\n\n// Flag with default, say from an environment variable.\n\nfunction createPepperProgramWithDefault(defaultValue) {\n  const program = new commander.Command();\n  program\n    .option('-p, --pepper', 'add pepper', defaultValue)\n    .option('-P, --no-pepper', 'remove pepper');\n  return program;\n}\n\n// boolean option combo, default true, long flags\ndescribe('boolean option combo, default true, long flags', () => {\n  test('when boolean combo not specified then value is true', () => {\n    const program = createPepperProgramWithDefault(true);\n    program.parse(['node', 'test']);\n    expect(program.opts().pepper).toBe(true);\n  });\n\n  test('when boolean combo positive then value is true', () => {\n    const program = createPepperProgramWithDefault(true);\n    program.parse(['node', 'test', '--pepper']);\n    expect(program.opts().pepper).toBe(true);\n  });\n\n  test('when boolean combo negative then value is false', () => {\n    const program = createPepperProgramWithDefault(true);\n    program.parse(['node', 'test', '--no-pepper']);\n    expect(program.opts().pepper).toBe(false);\n  });\n});\n\n// boolean option combo, default false, short flags\ndescribe('boolean option combo, default false, short flags', () => {\n  test('when boolean combo not specified then value is false', () => {\n    const program = createPepperProgramWithDefault(false);\n    program.parse(['node', 'test']);\n    expect(program.opts().pepper).toBe(false);\n  });\n\n  test('when boolean combo positive then value is true', () => {\n    const program = createPepperProgramWithDefault(false);\n    program.parse(['node', 'test', '-p']);\n    expect(program.opts().pepper).toBe(true);\n  });\n\n  test('when boolean combo negative then value is false', () => {\n    const program = createPepperProgramWithDefault(false);\n    program.parse(['node', 'test', '-P']);\n    expect(program.opts().pepper).toBe(false);\n  });\n});\n\n// boolean option combo with non-boolean default.\n// Changed behaviour to normal default in Commander 9.\ndescribe('boolean option combo with non-boolean default', () => {\n  test('when boolean combo not specified then value is default', () => {\n    const program = createPepperProgramWithDefault('default');\n    program.parse(['node', 'test']);\n    expect(program.opts().pepper).toBe('default');\n  });\n\n  test('when boolean combo positive then value is true', () => {\n    const program = createPepperProgramWithDefault('default');\n    program.parse(['node', 'test', '--pepper']);\n    expect(program.opts().pepper).toBe(true);\n  });\n\n  test('when boolean combo negative then value is false', () => {\n    const program = createPepperProgramWithDefault('default');\n    program.parse(['node', 'test', '--no-pepper']);\n    expect(program.opts().pepper).toBe(false);\n  });\n});\n\ndescribe('boolean option combo with non-boolean default and preset', () => {\n  function createPepperProgramWithDefaultAndPreset() {\n    const program = new commander.Command();\n    program\n      .addOption(\n        new commander.Option('-p, --pepper')\n          .default('default')\n          .preset('preset'),\n      )\n      .option('-P, --no-pepper', 'remove pepper');\n    return program;\n  }\n\n  test('when boolean combo not specified then value is default', () => {\n    const program = createPepperProgramWithDefaultAndPreset();\n    program.parse(['node', 'test']);\n    expect(program.opts().pepper).toBe('default');\n  });\n\n  test('when boolean combo positive then value is preset', () => {\n    const program = createPepperProgramWithDefaultAndPreset();\n    program.parse(['node', 'test', '--pepper']);\n    expect(program.opts().pepper).toBe('preset');\n  });\n\n  test('when boolean combo negative then value is false', () => {\n    const program = createPepperProgramWithDefaultAndPreset();\n    program.parse(['node', 'test', '--no-pepper']);\n    expect(program.opts().pepper).toBe(false);\n  });\n});\n"
  },
  {
    "path": "tests/options.bool.small.combined.test.js",
    "content": "const commander = require('../');\n\ntest('when when multiple short flags specified then all values are true', () => {\n  const program = new commander.Command();\n  program\n    .option('-p, --pepper', 'add pepper')\n    .option('-c, --cheese', 'add cheese');\n\n  program.parse(['node', 'test', '-pc']);\n\n  expect(program.opts().pepper).toBe(true);\n  expect(program.opts().cheese).toBe(true);\n});\n"
  },
  {
    "path": "tests/options.bool.test.js",
    "content": "const commander = require('../');\n\n// Test simple flag and negatable flag\n\n// boolean flag on program\ndescribe('boolean flag on program', () => {\n  test('when boolean flag not specified then value is undefined', () => {\n    const program = new commander.Command();\n    program.option('--pepper', 'add pepper');\n    program.parse(['node', 'test']);\n    expect(program.opts().pepper).toBeUndefined();\n  });\n\n  test('when boolean flag specified then value is true', () => {\n    const program = new commander.Command();\n    program.option('--pepper', 'add pepper');\n    program.parse(['node', 'test', '--pepper']);\n    expect(program.opts().pepper).toBe(true);\n  });\n\n  test('when negatable boolean flag not specified then value is true', () => {\n    const program = new commander.Command();\n    program.option('--no-cheese', 'remove cheese');\n    program.parse(['node', 'test']);\n    expect(program.opts().cheese).toBe(true);\n  });\n\n  test('when negatable boolean flag specified then value is false', () => {\n    const program = new commander.Command();\n    program.option('--no-cheese', 'remove cheese');\n    program.parse(['node', 'test', '--no-cheese']);\n    expect(program.opts().cheese).toBe(false);\n  });\n});\n\n// boolean flag on command\ndescribe('boolean flag on command', () => {\n  test('when boolean flag not specified then value is undefined', () => {\n    let subCommandOptions;\n    const program = new commander.Command();\n    program\n      .command('sub')\n      .option('--pepper', 'add pepper')\n      .action((options) => {\n        subCommandOptions = options;\n      });\n    program.parse(['node', 'test', 'sub']);\n    expect(subCommandOptions.pepper).toBeUndefined();\n  });\n\n  test('when boolean flag specified then value is true', () => {\n    let subCommandOptions;\n    const program = new commander.Command();\n    program\n      .command('sub')\n      .option('--pepper', 'add pepper')\n      .action((options) => {\n        subCommandOptions = options;\n      });\n    program.parse(['node', 'test', 'sub', '--pepper']);\n    expect(subCommandOptions.pepper).toBe(true);\n  });\n\n  test('when negatable boolean flag not specified then value is true', () => {\n    let subCommandOptions;\n    const program = new commander.Command();\n    program\n      .command('sub')\n      .option('--no-cheese', 'remove cheese')\n      .action((options) => {\n        subCommandOptions = options;\n      });\n    program.parse(['node', 'test', 'sub']);\n    expect(subCommandOptions.cheese).toBe(true);\n  });\n\n  test('when negatable boolean flag specified then value is false', () => {\n    let subCommandOptions;\n    const program = new commander.Command();\n    program\n      .command('sub')\n      .option('--no-cheese', 'remove cheese')\n      .action((options) => {\n        subCommandOptions = options;\n      });\n    program.parse(['node', 'test', 'sub', '--no-cheese']);\n    expect(subCommandOptions.cheese).toBe(false);\n  });\n});\n\n// boolean flag with non-boolean default\n// NB: behaviour changed in Commander v9 to have default be default.\n// These tests no longer match likely uses, but retained and updated to match current behaviour.\ndescribe('boolean flag with non-boolean default', () => {\n  test('when flag not specified then value is \"default\"', () => {\n    const flagValue = 'black';\n    const program = new commander.Command();\n    program.option('--olives', 'Add green olives?', flagValue);\n    program.parse(['node', 'test']);\n    expect(program.opts().olives).toBe(flagValue);\n  });\n\n  test('when flag specified then value is true', () => {\n    const flagValue = 'black';\n    const program = new commander.Command();\n    program.option('-v, --olives', 'Add green olives?', flagValue);\n    program.parse(['node', 'test', '--olives']);\n    expect(program.opts().olives).toBe(true);\n  });\n\n  test('when combo flag and negated then value is false', () => {\n    const flagValue = 'black';\n    const program = new commander.Command();\n    program\n      .option('-v, --olives', 'Add green olives?', flagValue)\n      .option('--no-olives');\n    program.parse(['node', 'test', '--olives', '--no-olives']);\n    expect(program.opts().olives).toBe(false);\n  });\n});\n\n// Regression test for #1301 with `-no-` in middle of option\ndescribe('regression test for -no- in middle of option flag', () => {\n  test('when flag not specified then value is undefined', () => {\n    const program = new commander.Command();\n    program.option('--module-no-parse');\n    program.parse(['node', 'test']);\n    expect(program.opts().moduleNoParse).toBeUndefined();\n  });\n\n  test('when flag specified then value is true', () => {\n    const program = new commander.Command();\n    program.option('--module-no-parse');\n    program.parse(['node', 'test', '--module-no-parse']);\n    expect(program.opts().moduleNoParse).toEqual(true);\n  });\n});\n"
  },
  {
    "path": "tests/options.camelcase.test.js",
    "content": "const commander = require('../');\n\n// Capitalise the letters of words after dashes, but otherwise preserve case\n\ntest('when option defined with --word-word then option property is wordWord', () => {\n  const program = new commander.Command();\n  program.option('--my-option', 'description');\n  program.parse(['node', 'test', '--my-option']);\n  expect(program.opts().myOption).toBe(true);\n});\n\ntest('when option defined with --word-wORD then option property is wordWORD', () => {\n  const program = new commander.Command();\n  program.option('--my-oPTION', 'description');\n  program.parse(['node', 'test', '--my-oPTION']);\n  expect(program.opts().myOPTION).toBe(true);\n});\n\ntest('when option defined with --word-WORD then option property is wordWORD', () => {\n  const program = new commander.Command();\n  program.option('--my-OPTION', 'description');\n  program.parse(['node', 'test', '--my-OPTION']);\n  expect(program.opts().myOPTION).toBe(true);\n});\n\ntest('when option defined with --word-word-word then option property is wordWordWord', () => {\n  const program = new commander.Command();\n  program.option('--my-special-option', 'description');\n  program.parse(['node', 'test', '--my-special-option']);\n  expect(program.opts().mySpecialOption).toBe(true);\n});\n\ntest('when option defined with --word-WORD-word then option property is wordWORDWord', () => {\n  const program = new commander.Command();\n  program.option('--my-SPECIAL-option', 'description');\n  program.parse(['node', 'test', '--my-SPECIAL-option']);\n  expect(program.opts().mySPECIALOption).toBe(true);\n});\n\ntest('when option defined with --Word then option property is Word', () => {\n  const program = new commander.Command();\n  program.option('--Myoption', 'description');\n  program.parse(['node', 'test', '--Myoption']);\n  expect(program.opts().Myoption).toBe(true);\n});\n"
  },
  {
    "path": "tests/options.choices.test.js",
    "content": "const commander = require('../');\n\ntest('when option argument in choices then option set', () => {\n  const program = new commander.Command();\n  program\n    .exitOverride()\n    .addOption(\n      new commander.Option('--colour <shade>').choices(['red', 'blue']),\n    );\n  program.parse(['--colour', 'red'], { from: 'user' });\n  expect(program.opts().colour).toBe('red');\n});\n\ntest('when option argument is not in choices then error', () => {\n  // Lightweight check, more detailed testing of behaviour in command.exitOverride.test.js\n  const program = new commander.Command();\n  program\n    .exitOverride()\n    .configureOutput({\n      writeErr: () => {},\n    })\n    .addOption(\n      new commander.Option('--colour <shade>').choices(['red', 'blue']),\n    );\n  expect(() => {\n    program.parse(['--colour', 'orange'], { from: 'user' });\n  }).toThrow();\n});\n\ndescribe('choices parameter is treated as readonly, per TypeScript declaration', () => {\n  test('when choices called then parameter does not change', () => {\n    // Unlikely this could break, but check the API we are declaring in TypeScript.\n    const original = ['red', 'blue', 'green'];\n    const param = original.slice();\n    new commander.Option('--colour <shade>').choices(param);\n    expect(param).toEqual(original);\n  });\n\n  test('when choices called and argChoices later changed then parameter does not change', () => {\n    const original = ['red', 'blue', 'green'];\n    const param = original.slice();\n    const option = new commander.Option('--colour <shade>').choices(param);\n    option.argChoices.push('purple');\n    expect(param).toEqual(original);\n  });\n\n  test('when choices called and parameter changed the choices does not change', () => {\n    const program = new commander.Command();\n    const param = ['red', 'blue'];\n    program\n      .exitOverride()\n      .configureOutput({\n        writeErr: () => {},\n      })\n      .addOption(new commander.Option('--colour <shade>').choices(param));\n    param.push('orange');\n    expect(() => {\n      program.parse(['--colour', 'orange'], { from: 'user' });\n    }).toThrow();\n  });\n});\n"
  },
  {
    "path": "tests/options.conflicts.test.js",
    "content": "const path = require('path');\nconst commander = require('../');\n\ndescribe('command with conflicting options', () => {\n  function makeProgram() {\n    const actionMock = jest.fn();\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .configureOutput({\n        writeErr: () => {},\n        writeOut: () => {},\n      })\n      .command('foo')\n      .addOption(\n        new commander.Option('-s, --silent', \"Don't print anything\").env(\n          'SILENT',\n        ),\n      )\n      .addOption(\n        new commander.Option('-j, --json', 'Format output as json')\n          .env('JSON')\n          .conflicts(['silent']),\n      )\n      .action(actionMock);\n\n    return { program, actionMock };\n  }\n\n  beforeEach(() => {\n    delete process.env.SILENT;\n    delete process.env.JSON;\n    delete process.env.DUAL;\n    delete process.env.NO_DUAL;\n  });\n\n  test('should call action if there are no explicit conflicting options set', () => {\n    const { program, actionMock } = makeProgram();\n    program.parse('node test.js foo --json'.split(' '));\n    expect(actionMock).toHaveBeenCalledTimes(1);\n    expect(actionMock).toHaveBeenCalledWith({ json: true }, expect.any(Object));\n  });\n\n  test('should call action when there are no implicit conflicting options set', () => {\n    const { program, actionMock } = makeProgram();\n    program.parse('node test.js foo --silent'.split(' '));\n    expect(actionMock).toHaveBeenCalledTimes(1);\n    expect(actionMock).toHaveBeenCalledWith(\n      { silent: true },\n      expect.any(Object),\n    );\n  });\n\n  test('should exit with error if conflicting options were set', () => {\n    const { program } = makeProgram();\n\n    expect(() => {\n      program.parse('node test.js foo --silent --json'.split(' '));\n    }).toThrow(\n      \"error: option '-j, --json' cannot be used with option '-s, --silent'\",\n    );\n  });\n\n  test('should report the env variable as the conflicting option source, when conflicting option is set', () => {\n    const { program } = makeProgram();\n\n    process.env.SILENT = true;\n\n    expect(() => {\n      program.parse('node test.js foo --json'.split(' '));\n    }).toThrow(\n      \"error: option '-j, --json' cannot be used with environment variable 'SILENT'\",\n    );\n  });\n\n  test('should report the env variable as the configured option source, when configured option is set', () => {\n    const { program } = makeProgram();\n\n    process.env.JSON = true;\n\n    expect(() => {\n      program.parse('node test.js foo --silent'.split(' '));\n    }).toThrow(\n      \"error: environment variable 'JSON' cannot be used with option '-s, --silent'\",\n    );\n  });\n\n  test('should report both env variables as sources, when configured option and conflicting option are set', () => {\n    const { program } = makeProgram();\n\n    process.env.SILENT = true;\n    process.env.JSON = true;\n\n    expect(() => {\n      program.parse('node test.js foo'.split(' '));\n    }).toThrow(\n      \"error: environment variable 'JSON' cannot be used with environment variable 'SILENT'\",\n    );\n  });\n\n  test('should allow default value with a conflicting option', () => {\n    const { program, actionMock } = makeProgram();\n\n    program.commands[0].addOption(\n      new commander.Option('-d, --debug', 'print debug logs')\n        .default(true)\n        .conflicts(['silent']),\n    );\n\n    program.parse('node test.js foo --silent'.split(' '));\n\n    expect(actionMock).toHaveBeenCalledTimes(1);\n    expect(actionMock).toHaveBeenCalledWith(\n      { debug: true, silent: true },\n      expect.any(Object),\n    );\n  });\n\n  test('should report conflict on negated option flag', () => {\n    const { program } = makeProgram();\n\n    program\n      .command('bar')\n      .addOption(new commander.Option('--red').conflicts(['color']))\n      .addOption(new commander.Option('--color'))\n      .addOption(new commander.Option('-N, --no-color'));\n\n    expect(() => {\n      program.parse('node test.js bar --red -N'.split(' '));\n    }).toThrow(\n      \"error: option '--red' cannot be used with option '-N, --no-color'\",\n    );\n  });\n\n  test('should report conflict on negated option env variable', () => {\n    const { program } = makeProgram();\n\n    process.env.NO_COLOR = true;\n\n    program\n      .command('bar')\n      .addOption(new commander.Option('--red').conflicts(['color']))\n      .addOption(new commander.Option('--color'))\n      .addOption(new commander.Option('-N, --no-color').env('NO_COLOR'));\n\n    expect(() => {\n      program.parse('node test.js bar --red'.split(' '));\n    }).toThrow(\n      \"error: option '--red' cannot be used with environment variable 'NO_COLOR'\",\n    );\n  });\n\n  test('should report correct error for shorthand negated option', () => {\n    const { program } = makeProgram();\n\n    program\n      .command('bar')\n      .addOption(new commander.Option('--red'))\n      .addOption(new commander.Option('-N, --no-color').conflicts(['red']));\n\n    expect(() => {\n      program.parse('node test.js bar --red -N'.split(' '));\n    }).toThrow(\n      \"error: option '-N, --no-color' cannot be used with option '--red'\",\n    );\n  });\n\n  test('should report correct error for positive option when negated is configured', () => {\n    const { program } = makeProgram();\n\n    program\n      .command('bar')\n      .addOption(new commander.Option('--red'))\n      .addOption(new commander.Option('--dual').env('DUAL').conflicts(['red']))\n      .addOption(new commander.Option('--no-dual').env('NO_DUAL'));\n\n    expect(() => {\n      program.parse('node test.js bar --red --dual'.split(' '));\n    }).toThrow(\"error: option '--dual' cannot be used with option '--red'\");\n  });\n\n  test('should report correct error for negated option when positive is configured', () => {\n    const { program } = makeProgram();\n\n    program\n      .command('bar')\n      .addOption(new commander.Option('--red'))\n      .addOption(new commander.Option('--dual').env('DUAL').conflicts(['red']))\n      .addOption(new commander.Option('--no-dual').env('NO_DUAL'));\n\n    expect(() => {\n      program.parse('node test.js bar --red --no-dual'.split(' '));\n    }).toThrow(\"error: option '--no-dual' cannot be used with option '--red'\");\n  });\n\n  test('should report correct error for positive env variable when negated is configured', () => {\n    const { program } = makeProgram();\n\n    program\n      .command('bar')\n      .addOption(new commander.Option('--red'))\n      .addOption(new commander.Option('--dual').env('DUAL').conflicts(['red']))\n      .addOption(new commander.Option('--no-dual').env('NO_DUAL'));\n\n    process.env.DUAL = 'true';\n    expect(() => {\n      program.parse('node test.js bar --red'.split(' '));\n    }).toThrow(\n      \"error: environment variable 'DUAL' cannot be used with option '--red'\",\n    );\n  });\n\n  test('should report correct error for negated env variable when positive is configured', () => {\n    const { program } = makeProgram();\n\n    program\n      .command('bar')\n      .addOption(new commander.Option('--red'))\n      .addOption(new commander.Option('--dual').env('DUAL').conflicts(['red']))\n      .addOption(new commander.Option('--no-dual').env('NO_DUAL'));\n\n    process.env.NO_DUAL = 'true';\n    expect(() => {\n      program.parse('node test.js bar --red'.split(' '));\n    }).toThrow(\n      \"error: environment variable 'NO_DUAL' cannot be used with option '--red'\",\n    );\n  });\n\n  test('should report correct error for positive option with string value when negated is configured', () => {\n    const { program } = makeProgram();\n\n    program\n      .command('bar')\n      .addOption(new commander.Option('--red'))\n      .addOption(new commander.Option('--dual2 <str>').conflicts(['red']))\n      .addOption(new commander.Option('--no-dual2').preset('BAD'));\n\n    expect(() => {\n      program.parse('node test.js bar --red --dual2 foo'.split(' '));\n    }).toThrow(\n      \"error: option '--dual2 <str>' cannot be used with option '--red'\",\n    );\n  });\n\n  test('should report correct error for negated option with preset when negated is configured', () => {\n    const { program } = makeProgram();\n\n    program\n      .command('bar')\n      .addOption(new commander.Option('--red'))\n      .addOption(new commander.Option('--dual2 <str>').conflicts(['red']))\n      .addOption(new commander.Option('--no-dual2').preset('BAD'));\n\n    expect(() => {\n      program.parse('node test.js bar --red --no-dual2'.split(' '));\n    }).toThrow(\"error: option '--no-dual2' cannot be used with option '--red'\");\n  });\n\n  test('should not throw error when conflicts is invoked with a single string that includes another option', () => {\n    const { program } = makeProgram();\n\n    const actionMock = jest.fn();\n\n    program\n      .command('bar')\n      .addOption(new commander.Option('--a'))\n      .addOption(new commander.Option('--b').conflicts('aa'))\n      .action(actionMock);\n\n    program.parse('node test.js bar --a --b'.split(' '));\n\n    expect(actionMock).toHaveBeenCalledTimes(1);\n    expect(actionMock).toHaveBeenCalledWith(\n      { a: true, b: true },\n      expect.any(Object),\n    );\n  });\n\n  test('should throw error when conflicts is invoked with a single string that equals another option', () => {\n    const { program } = makeProgram();\n\n    program\n      .command('bar')\n      .addOption(new commander.Option('--a'))\n      .addOption(new commander.Option('--b').conflicts('a'));\n\n    expect(() => {\n      program.parse('node test.js bar --a --b'.split(' '));\n    }).toThrow(\"error: option '--b' cannot be used with option '--a'\");\n  });\n\n  test('when conflict on program calling action subcommand then throw conflict', () => {\n    const { program } = makeProgram();\n    let exception;\n\n    program\n      .addOption(new commander.Option('--black'))\n      .addOption(new commander.Option('--white').conflicts('black'));\n\n    try {\n      program.parse('--white --black foo'.split(' '), { from: 'user' });\n    } catch (err) {\n      exception = err;\n    }\n    expect(exception).not.toBeUndefined();\n    expect(exception.code).toBe('commander.conflictingOption');\n  });\n\n  test('when conflict on program calling action subcommand with help then show help', () => {\n    const { program } = makeProgram();\n    let exception;\n\n    program\n      .addOption(new commander.Option('--black'))\n      .addOption(new commander.Option('--white').conflicts('black'));\n\n    try {\n      program.parse('--white --black foo --help'.split(' '), { from: 'user' });\n    } catch (err) {\n      exception = err;\n    }\n    expect(exception).not.toBeUndefined();\n    expect(exception.code).toBe('commander.helpDisplayed');\n  });\n\n  test('when conflict on program calling external subcommand then throw conflict', () => {\n    const { program } = makeProgram();\n    let exception;\n\n    program\n      .addOption(new commander.Option('--black'))\n      .addOption(new commander.Option('--white').conflicts('black'));\n    const pm = path.join(__dirname, './fixtures/pm');\n    program.command('ext', 'external command', { executableFile: pm });\n\n    try {\n      program.parse('--white --black ext'.split(' '), { from: 'user' });\n    } catch (err) {\n      exception = err;\n    }\n    expect(exception).not.toBeUndefined();\n    expect(exception.code).toBe('commander.conflictingOption');\n  });\n});\n"
  },
  {
    "path": "tests/options.custom-processing.test.js",
    "content": "const commander = require('../');\n\nfunction myParseInt(value, dummyPrevious) {\n  // parseInt takes a string and a radix\n  return parseInt(value, 10);\n}\n\nfunction increaseVerbosity(dummyValue, previous) {\n  return previous + 1;\n}\n\nfunction collect(value, previous) {\n  return previous.concat([value]);\n}\n\nfunction commaSeparatedList(value, dummyPrevious) {\n  return value.split(',');\n}\n\ntest('when option not specified then callback not called', () => {\n  const mockCoercion = jest.fn();\n  const program = new commander.Command();\n  program.option('-i, --integer <n>', 'number', mockCoercion);\n  program.parse(['node', 'test']);\n  expect(mockCoercion).not.toHaveBeenCalled();\n});\n\ntest('when option not specified then value is undefined', () => {\n  const program = new commander.Command();\n  program.option('-i, --integer <n>', 'number', myParseInt);\n  program.parse(['node', 'test']);\n  expect(program.opts().integer).toBeUndefined();\n});\n\ntest('when starting value is defined and option not specified then callback not called', () => {\n  const mockCoercion = jest.fn();\n  const program = new commander.Command();\n  program.option('-i, --integer <n>', 'number', mockCoercion, 1);\n  program.parse(['node', 'test']);\n  expect(mockCoercion).not.toHaveBeenCalled();\n});\n\ntest('when starting value is defined and option not specified then value is starting value', () => {\n  // NB: Can not specify a starting value for a boolean flag! Discovered when writing this test...\n  const startingValue = 1;\n  const program = new commander.Command();\n  program.option('-i, --integer <n>', 'number', myParseInt, startingValue);\n  program.parse(['node', 'test']);\n  expect(program.opts().integer).toBe(startingValue);\n});\n\ntest('when option specified then callback called with value', () => {\n  const mockCoercion = jest.fn();\n  const value = '1';\n  const program = new commander.Command();\n  program.option('-i, --integer <n>', 'number', mockCoercion);\n  program.parse(['node', 'test', '-i', value]);\n  expect(mockCoercion).toHaveBeenCalledWith(value, undefined);\n});\n\ntest('when option specified then value is as returned from callback', () => {\n  const callbackResult = 2;\n  const program = new commander.Command();\n  program.option('-i, --integer <n>', 'number', () => {\n    return callbackResult;\n  });\n  program.parse(['node', 'test', '-i', '0']);\n  expect(program.opts().integer).toBe(callbackResult);\n});\n\ntest('when starting value is defined and option specified then callback called with value and starting value', () => {\n  const mockCoercion = jest.fn();\n  const startingValue = 1;\n  const value = '2';\n  const program = new commander.Command();\n  program.option('-i, --integer <n>', 'number', mockCoercion, startingValue);\n  program.parse(['node', 'test', '-i', value]);\n  expect(mockCoercion).toHaveBeenCalledWith(value, startingValue);\n});\n\ntest('when option specified multiple times then callback called with value and previousValue', () => {\n  const mockCoercion = jest.fn().mockImplementation(() => {\n    return 'callback';\n  });\n  const program = new commander.Command();\n  program.option('-i, --integer <n>', 'number', mockCoercion);\n  program.parse(['node', 'test', '-i', '1', '-i', '2']);\n  expect(mockCoercion).toHaveBeenCalledTimes(2);\n  expect(mockCoercion).toHaveBeenNthCalledWith(1, '1', undefined);\n  expect(mockCoercion).toHaveBeenNthCalledWith(2, '2', 'callback');\n});\n\n// Now some functional tests like the examples in the README!\n\ntest('when parseFloat \"1e2\" then value is 100', () => {\n  const program = new commander.Command();\n  program.option('-f, --float <number>', 'float argument', parseFloat);\n  program.parse(['node', 'test', '-f', '1e2']);\n  expect(program.opts().float).toBe(100);\n});\n\ntest('when myParseInt \"1\" then value is 1', () => {\n  const program = new commander.Command();\n  program.option('-i, --integer <number>', 'integer argument', myParseInt);\n  program.parse(['node', 'test', '-i', '1']);\n  expect(program.opts().integer).toBe(1);\n});\n\ntest('when increaseVerbosity -v -v -v then value is 3', () => {\n  const program = new commander.Command();\n  program.option(\n    '-v, --verbose',\n    'verbosity that can be increased',\n    increaseVerbosity,\n    0,\n  );\n  program.parse(['node', 'test', '-v', '-v', '-v']);\n  expect(program.opts().verbose).toBe(3);\n});\n\ntest('when collect -c a -c b -c c then value is [a, b, c]', () => {\n  const program = new commander.Command();\n  program.option('-c, --collect <value>', 'repeatable value', collect, []);\n  program.parse(['node', 'test', '-c', 'a', '-c', 'b', '-c', 'c']);\n  expect(program.opts().collect).toEqual(['a', 'b', 'c']);\n});\n\ntest('when commaSeparatedList x,y,z then value is [x, y, z]', () => {\n  const program = new commander.Command();\n  program.option(\n    '-l, --list <items>',\n    'comma separated list',\n    commaSeparatedList,\n  );\n  program.parse(['node', 'test', '--list', 'x,y,z']);\n  expect(program.opts().list).toEqual(['x', 'y', 'z']);\n});\n"
  },
  {
    "path": "tests/options.default.test.js",
    "content": "const { Command, Option } = require('../');\n\ndescribe('.option() with default and option not specified in parse', () => {\n  test('when boolean option with boolean default then value is default', () => {\n    const program = new Command();\n    program.option('-d, --debug', 'description', false);\n    program.parse([], { from: 'user' });\n    expect(program.opts().debug).toBe(false);\n  });\n\n  test('when boolean option with number zero default then value is zero', () => {\n    const program = new Command();\n    program.option('-d, --debug', 'description', 0);\n    program.parse([], { from: 'user' });\n    expect(program.opts().debug).toBe(0);\n  });\n\n  test('when boolean option with string default then value is default', () => {\n    const program = new Command();\n    program.option('-d, --debug', 'description', 'default');\n    program.parse([], { from: 'user' });\n    expect(program.opts().debug).toBe('default');\n  });\n\n  test('when required option-argument and default number then value is default', () => {\n    const program = new Command();\n    program.option('-p, --port <port-number>', 'description', 80);\n    program.parse([], { from: 'user' });\n    expect(program.opts().port).toBe(80);\n  });\n\n  test('when required option-argument and default string then value is default', () => {\n    const program = new Command();\n    program.option('-p, --port <port-number>', 'description', 'foo');\n    program.parse([], { from: 'user' });\n    expect(program.opts().port).toBe('foo');\n  });\n\n  test('when optional option-argument and default number then value is default', () => {\n    const program = new Command();\n    program.option('-p, --port [port-number]', 'description', 80);\n    program.parse([], { from: 'user' });\n    expect(program.opts().port).toBe(80);\n  });\n\n  test('when optional option-argument and default string then value is default', () => {\n    const program = new Command();\n    program.option('-p, --port [port-number]', 'description', 'foo');\n    program.parse([], { from: 'user' });\n    expect(program.opts().port).toBe('foo');\n  });\n\n  test('when negated and default string then value is default', () => {\n    // Bit tricky thinking about what default means for a negated option, but treat as with other options.\n    const program = new Command();\n    program.option('--no-colour', 'description', 'RGB');\n    program.parse([], { from: 'user' });\n    expect(program.opts().colour).toBe('RGB');\n  });\n});\n\ndescribe('Option with default and option not specified in parse', () => {\n  test('when boolean option with boolean default then value is default', () => {\n    const program = new Command();\n    program.addOption(new Option('-d, --debug').default(false));\n    program.parse([], { from: 'user' });\n    expect(program.opts().debug).toBe(false);\n  });\n\n  test('when boolean option with number zero default then value is zero', () => {\n    const program = new Command();\n    program.addOption(new Option('-d, --debug').default(0));\n    program.parse([], { from: 'user' });\n    expect(program.opts().debug).toBe(0);\n  });\n\n  test('when boolean option with string default then value is default', () => {\n    const program = new Command();\n    program.addOption(new Option('-d, --debug').default('default'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().debug).toBe('default');\n  });\n\n  test('when required option-argument and default number then value is default', () => {\n    const program = new Command();\n    program.addOption(new Option('-p, --port <port-number>').default(80));\n    program.parse([], { from: 'user' });\n    expect(program.opts().port).toBe(80);\n  });\n\n  test('when required option-argument and default string then value is default', () => {\n    const program = new Command();\n    program.addOption(new Option('-p, --port <port-number>').default('foo'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().port).toBe('foo');\n  });\n\n  test('when optional option-argument and default number then value is default', () => {\n    const program = new Command();\n    program.addOption(new Option('-p, --port [port-number]').default(80));\n    program.parse([], { from: 'user' });\n    expect(program.opts().port).toBe(80);\n  });\n\n  test('when optional option-argument and default string then value is default', () => {\n    const program = new Command();\n    program.addOption(new Option('-p, --port [port-number]').default('foo'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().port).toBe('foo');\n  });\n\n  test('when negated and default string then value is default', () => {\n    // Bit tricky thinking about what default means for a negated option, but treat as with other options.\n    const program = new Command();\n    program.addOption(new Option('--no-colour').default('RGB'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().colour).toBe('RGB');\n  });\n});\n\n// Fairly obvious this needs to happen, but was broken for optional in past!\ndescribe('default overwritten by specified option', () => {\n  test('when boolean option with boolean default then value is true', () => {\n    const program = new Command();\n    program.option('-d, --debug', 'description', false);\n    program.parse(['-d'], { from: 'user' });\n    expect(program.opts().debug).toBe(true);\n  });\n\n  test('when boolean option with number zero default then value is true', () => {\n    const program = new Command();\n    program.option('-d, --debug', 'description', 0);\n    program.parse(['-d'], { from: 'user' });\n    expect(program.opts().debug).toBe(true);\n  });\n\n  test('when boolean option with string default then value is true', () => {\n    const program = new Command();\n    program.option('-d, --debug', 'description', 'default');\n    program.parse(['-d'], { from: 'user' });\n    expect(program.opts().debug).toBe(true);\n  });\n\n  test('when required option-argument and default number then value is from args', () => {\n    const program = new Command();\n    program.option('-p, --port <port-number>', 'description', 80);\n    program.parse(['-p', '1234'], { from: 'user' });\n    expect(program.opts().port).toBe('1234');\n  });\n\n  test('when required option-argument and default string then value is from args', () => {\n    const program = new Command();\n    program.option('-p, --port <port-number>', 'description', 'foo');\n    program.parse(['-p', '1234'], { from: 'user' });\n    expect(program.opts().port).toBe('1234');\n  });\n\n  test('when optional option-argument and default number and option-argument specified then value is from args', () => {\n    const program = new Command();\n    program.option('-p, --port [port-number]', 'description', 80);\n    program.parse(['-p', '1234'], { from: 'user' });\n    expect(program.opts().port).toBe('1234');\n  });\n\n  test('when optional option-argument and default string and option-argument specified then value is from args', () => {\n    const program = new Command();\n    program.option('-p, --port [port-number]', 'description', 'foo');\n    program.parse(['-p', '1234'], { from: 'user' });\n    expect(program.opts().port).toBe('1234');\n  });\n\n  test('when optional option-argument and default number and option-argument not specified then value is true', () => {\n    const program = new Command();\n    program.option('-p, --port [port-number]', 'description', 80);\n    program.parse(['-p'], { from: 'user' });\n    expect(program.opts().port).toBe(true);\n  });\n\n  test('when optional option-argument and default string and option-argument not specified then value is true', () => {\n    const program = new Command();\n    program.option('-p, --port [port-number]', 'description', 'foo');\n    program.parse(['-p'], { from: 'user' });\n    expect(program.opts().port).toBe(true);\n  });\n\n  test('when negated and default string then value is false', () => {\n    // Bit tricky thinking about what default means for a negated option, but treat as with other options.\n    const program = new Command();\n    program.option('--no-colour', 'description', 'RGB');\n    program.parse(['--no-colour'], { from: 'user' });\n    expect(program.opts().colour).toBe(false);\n  });\n});\n"
  },
  {
    "path": "tests/options.dual-options.test.js",
    "content": "const { Option, DualOptions } = require('../lib/option.js');\nconst { Command } = require('../');\n\n// This tests an internal helper class which is not currently exposed on the package.\n\ntest('when positive option then stored in positiveOptions', () => {\n  const program = new Command();\n  program.option('--one');\n  const helper = new DualOptions(program.options);\n  expect(helper.positiveOptions.size).toEqual(1);\n  expect(helper.negativeOptions.size).toEqual(0);\n  expect(helper.dualOptions.size).toEqual(0);\n});\n\ntest('when negative option then stored in negativeOptions', () => {\n  const program = new Command();\n  program.option('--no-one');\n  const helper = new DualOptions(program.options);\n  expect(helper.positiveOptions.size).toEqual(0);\n  expect(helper.negativeOptions.size).toEqual(1);\n  expect(helper.dualOptions.size).toEqual(0);\n});\n\ntest('when unrelated positive and negative options then no dual options', () => {\n  const program = new Command();\n  program.option('--one').option('--no-two');\n  const helper = new DualOptions(program.options);\n  expect(helper.dualOptions.size).toEqual(0);\n});\n\ntest('when related positive and negative options then stored as dual option', () => {\n  const program = new Command();\n  program.option('--one').option('--no-one');\n  const helper = new DualOptions(program.options);\n  expect(helper.dualOptions.size).toEqual(1);\n});\n\ntest('when related negative and positive options then stored as dual option', () => {\n  const program = new Command();\n  program.option('--no-one').option('--one');\n  const helper = new DualOptions(program.options);\n  expect(helper.dualOptions.size).toEqual(1);\n});\n\ndescribe('valueFromOption with boolean option', () => {\n  const positiveOption = new Option('--one');\n  const negativeOption = new Option('--no-one');\n  const options = [positiveOption, negativeOption];\n\n  test('when negativeOption with false then return true', () => {\n    const helper = new DualOptions(options);\n    expect(helper.valueFromOption(false, negativeOption)).toBe(true);\n  });\n\n  test('when negativeOption with true then return false', () => {\n    const helper = new DualOptions(options);\n    expect(helper.valueFromOption(true, negativeOption)).toBe(false);\n  });\n\n  test('when positiveOption with false then return false', () => {\n    const helper = new DualOptions(options);\n    expect(helper.valueFromOption(false, positiveOption)).toBe(false);\n  });\n\n  test('when positiveOption with true then return true', () => {\n    const helper = new DualOptions(options);\n    expect(helper.valueFromOption(true, positiveOption)).toBe(true);\n  });\n});\n\ndescribe('valueFromOption with option expecting value and negative with preset', () => {\n  const positiveOption = new Option('--one <value>');\n  const negativeOption = new Option('--no-one').preset('FALSE');\n  const options = [positiveOption, negativeOption];\n\n  test('when negativeOption with FALSE then return true', () => {\n    const helper = new DualOptions(options);\n    expect(helper.valueFromOption('FALSE', negativeOption)).toBe(true);\n  });\n\n  test('when negativeOption with string then return false', () => {\n    const helper = new DualOptions(options);\n    expect(helper.valueFromOption('foo', negativeOption)).toBe(false);\n  });\n\n  test('when positiveOption with FALSE then return false', () => {\n    const helper = new DualOptions(options);\n    expect(helper.valueFromOption('FALSE', positiveOption)).toBe(false);\n  });\n\n  test('when positiveOption with true then return true', () => {\n    const helper = new DualOptions(options);\n    expect(helper.valueFromOption('foo', positiveOption)).toBe(true);\n  });\n});\n"
  },
  {
    "path": "tests/options.env.test.js",
    "content": "const commander = require('../');\n\n// treating optional same as required, treat as option taking value rather than as boolean\ndescribe.each(['-f, --foo <required-arg>', '-f, --foo [optional-arg]'])(\n  'option declared as: %s',\n  (fooFlags) => {\n    test('when env undefined and no cli then option undefined', () => {\n      const program = new commander.Command();\n      program.addOption(new commander.Option(fooFlags).env('BAR'));\n      program.parse([], { from: 'user' });\n      expect(program.opts().foo).toBeUndefined();\n    });\n\n    test('when env defined and no cli then option from env', () => {\n      const program = new commander.Command();\n      process.env.BAR = 'env';\n      program.addOption(new commander.Option(fooFlags).env('BAR'));\n      program.parse([], { from: 'user' });\n      expect(program.opts().foo).toBe('env');\n      delete process.env.BAR;\n    });\n\n    test('when env defined and cli then option from cli', () => {\n      const program = new commander.Command();\n      process.env.BAR = 'env';\n      program.addOption(new commander.Option(fooFlags).env('BAR'));\n      program.parse(['--foo', 'cli'], { from: 'user' });\n      expect(program.opts().foo).toBe('cli');\n      delete process.env.BAR;\n    });\n\n    test('when env defined and value source is config then option from env', () => {\n      const program = new commander.Command();\n      process.env.BAR = 'env';\n      program.addOption(new commander.Option(fooFlags).env('BAR'));\n      program.setOptionValueWithSource('foo', 'config', 'config');\n      program.parse([], { from: 'user' });\n      expect(program.opts().foo).toBe('env');\n      delete process.env.BAR;\n    });\n\n    test('when env defined and value source is unspecified then option unchanged', () => {\n      const program = new commander.Command();\n      process.env.BAR = 'env';\n      program.addOption(new commander.Option(fooFlags).env('BAR'));\n      program.setOptionValue('foo', 'client');\n      program.parse([], { from: 'user' });\n      expect(program.opts().foo).toBe('client');\n      delete process.env.BAR;\n    });\n\n    test('when default and env undefined and no cli then option from default', () => {\n      const program = new commander.Command();\n      program.addOption(\n        new commander.Option(fooFlags).env('BAR').default('default'),\n      );\n      program.parse([], { from: 'user' });\n      expect(program.opts().foo).toBe('default');\n    });\n\n    test('when default and env defined and no cli then option from env', () => {\n      const program = new commander.Command();\n      process.env.BAR = 'env';\n      program.addOption(\n        new commander.Option(fooFlags).env('BAR').default('default'),\n      );\n      program.parse([], { from: 'user' });\n      expect(program.opts().foo).toBe('env');\n      delete process.env.BAR;\n    });\n\n    test('when default and env defined and cli then option from cli', () => {\n      const program = new commander.Command();\n      process.env.BAR = 'env';\n      program.addOption(\n        new commander.Option(fooFlags).env('BAR').default('default'),\n      );\n      program.parse(['--foo', 'cli'], { from: 'user' });\n      expect(program.opts().foo).toBe('cli');\n      delete process.env.BAR;\n    });\n  },\n);\n\ndescribe('boolean flag', () => {\n  test('when env undefined and no cli then option undefined', () => {\n    const program = new commander.Command();\n    program.addOption(new commander.Option('-f, --foo').env('BAR'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().foo).toBeUndefined();\n  });\n\n  test('when env defined with value and no cli then option true', () => {\n    const program = new commander.Command();\n    process.env.BAR = 'env';\n    program.addOption(new commander.Option('-f, --foo').env('BAR'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().foo).toBe(true);\n    delete process.env.BAR;\n  });\n\n  test('when env is \"\" and no cli then option true', () => {\n    // any string, including \"\"\n    const program = new commander.Command();\n    process.env.BAR = '';\n    program.addOption(new commander.Option('-f, --foo').env('BAR'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().foo).toBe(true);\n    delete process.env.BAR;\n  });\n\n  test('when env is \"0\" and no cli then option true', () => {\n    // any string, including \"0\"\n    const program = new commander.Command();\n    process.env.BAR = '0';\n    program.addOption(new commander.Option('-f, --foo').env('BAR'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().foo).toBe(true);\n    delete process.env.BAR;\n  });\n\n  test('when env is \"false\" and no cli then option true', () => {\n    // any string, including \"false\"\n    const program = new commander.Command();\n    process.env.BAR = 'false';\n    program.addOption(new commander.Option('-f, --foo').env('BAR'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().foo).toBe(true);\n    delete process.env.BAR;\n  });\n});\n\ndescribe('boolean no-flag', () => {\n  test('when env undefined and no cli then option true', () => {\n    const program = new commander.Command();\n    program.addOption(new commander.Option('-F, --no-foo').env('NO_BAR'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().foo).toBe(true);\n  });\n\n  test('when env defined and no cli then option false', () => {\n    const program = new commander.Command();\n    process.env.NO_BAR = 'env';\n    program.addOption(new commander.Option('-F, --no-foo').env('NO_BAR'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().foo).toBe(false);\n    delete process.env.NO_BAR;\n  });\n});\n\ndescribe('boolean flag and negatable', () => {\n  test('when env undefined and no cli then option undefined', () => {\n    const program = new commander.Command();\n    program\n      .addOption(new commander.Option('-f, --foo').env('BAR'))\n      .addOption(new commander.Option('-F, --no-foo').env('NO_BAR'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().foo).toBeUndefined();\n  });\n\n  test('when env defined and no cli then option true', () => {\n    const program = new commander.Command();\n    process.env.BAR = 'env';\n    program\n      .addOption(new commander.Option('-f, --foo').env('BAR'))\n      .addOption(new commander.Option('-F, --no-foo').env('NO_BAR'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().foo).toBe(true);\n    delete process.env.BAR;\n  });\n\n  test('when env defined and cli --no-foo then option false', () => {\n    const program = new commander.Command();\n    process.env.BAR = 'env';\n    program\n      .addOption(new commander.Option('-f, --foo').env('BAR'))\n      .addOption(new commander.Option('-F, --no-foo').env('NO_BAR'));\n    program.parse(['--no-foo'], { from: 'user' });\n    expect(program.opts().foo).toBe(false);\n    delete process.env.BAR;\n  });\n\n  test('when no_env defined and no cli then option false', () => {\n    const program = new commander.Command();\n    process.env.NO_BAR = 'env';\n    program\n      .addOption(new commander.Option('-f, --foo').env('BAR'))\n      .addOption(new commander.Option('-F, --no-foo').env('NO_BAR'));\n    program.parse([], { from: 'user' });\n    expect(program.opts().foo).toBe(false);\n    delete process.env.NO_BAR;\n  });\n\n  test('when no_env defined and cli --foo then option true', () => {\n    const program = new commander.Command();\n    process.env.NO_BAR = 'env';\n    program\n      .addOption(new commander.Option('-f, --foo').env('BAR'))\n      .addOption(new commander.Option('-F, --no-foo').env('NO_BAR'));\n    program.parse(['--foo'], { from: 'user' });\n    expect(program.opts().foo).toBe(true);\n    delete process.env.NO_BAR;\n  });\n});\n\ndescribe('custom argParser', () => {\n  test('when env defined and no cli then custom parse from env', () => {\n    const program = new commander.Command();\n    process.env.BAR = 'env';\n    program.addOption(\n      new commander.Option('-f, --foo <required>')\n        .env('BAR')\n        .argParser((str) => str.toUpperCase()),\n    );\n    program.parse([], { from: 'user' });\n    expect(program.opts().foo).toBe('ENV');\n    delete process.env.BAR;\n  });\n});\n\ndescribe('variadic', () => {\n  test('when env defined and no cli then array from env', () => {\n    const program = new commander.Command();\n    process.env.BAR = 'env';\n    program.addOption(\n      new commander.Option('-f, --foo <required...>').env('BAR'),\n    );\n    program.parse([], { from: 'user' });\n    expect(program.opts().foo).toEqual(['env']);\n    delete process.env.BAR;\n  });\n\n  test('when env defined and cli then array from cli', () => {\n    const program = new commander.Command();\n    process.env.BAR = 'env';\n    program.addOption(\n      new commander.Option('-f, --foo <required...>').env('BAR'),\n    );\n    program.parse(['--foo', 'cli'], { from: 'user' });\n    expect(program.opts().foo).toEqual(['cli']);\n    delete process.env.BAR;\n  });\n});\n\ndescribe('env only processed when applies', () => {\n  test('when env defined on another subcommand then env not applied', () => {\n    // Doing selective processing. Not processing env at addOption time.\n    const program = new commander.Command();\n    process.env.BAR = 'env';\n    program.command('one').action(() => {});\n    const two = program\n      .command('two')\n      .addOption(\n        new commander.Option('-f, --foo <required...>')\n          .env('BAR')\n          .default('default'),\n      )\n      .action(() => {});\n    program.parse(['one'], { from: 'user' });\n    expect(two.opts().foo).toBe('default');\n    delete process.env.BAR;\n  });\n\n  test('when env and cli defined then only emit option event for cli', () => {\n    const program = new commander.Command();\n    const optionEventMock = jest.fn();\n    const optionEnvEventMock = jest.fn();\n    program.on('option:foo', optionEventMock);\n    program.on('optionEnv:foo', optionEnvEventMock);\n    process.env.BAR = 'env';\n    program.addOption(\n      new commander.Option('-f, --foo <required...>').env('BAR'),\n    );\n    program.parse(['--foo', 'cli'], { from: 'user' });\n    expect(optionEventMock).toHaveBeenCalledWith('cli');\n    expect(optionEventMock).toHaveBeenCalledTimes(1);\n    expect(optionEnvEventMock).toHaveBeenCalledTimes(0);\n    delete process.env.BAR;\n  });\n\n  test('when env and cli defined then only parse value for cli', () => {\n    const program = new commander.Command();\n    const parseMock = jest.fn();\n    process.env.BAR = 'env';\n    program.addOption(\n      new commander.Option('-f, --foo <required...>')\n        .env('BAR')\n        .argParser(parseMock),\n    );\n    program.parse(['--foo', 'cli'], { from: 'user' });\n    expect(parseMock).toHaveBeenCalledWith('cli', undefined);\n    expect(parseMock).toHaveBeenCalledTimes(1);\n    delete process.env.BAR;\n  });\n});\n\ndescribe('events dispatched for env', () => {\n  const optionEnvEventMock = jest.fn();\n\n  afterEach(() => {\n    optionEnvEventMock.mockClear();\n    delete process.env.BAR;\n  });\n\n  test('when env defined then emit \"optionEnv\" and not \"option\"', () => {\n    // Decided to do separate events, so test stays that way.\n    const program = new commander.Command();\n    const optionEventMock = jest.fn();\n    program.on('option:foo', optionEventMock);\n    program.on('optionEnv:foo', optionEnvEventMock);\n    process.env.BAR = 'env';\n    program.addOption(new commander.Option('-f, --foo <required>').env('BAR'));\n    program.parse([], { from: 'user' });\n    expect(optionEventMock).toHaveBeenCalledTimes(0);\n    expect(optionEnvEventMock).toHaveBeenCalledTimes(1);\n  });\n\n  test('when env defined for required then emit \"optionEnv\" with value', () => {\n    const program = new commander.Command();\n    program.on('optionEnv:foo', optionEnvEventMock);\n    process.env.BAR = 'env';\n    program.addOption(new commander.Option('-f, --foo <required>').env('BAR'));\n    program.parse([], { from: 'user' });\n    expect(optionEnvEventMock).toHaveBeenCalledWith('env');\n  });\n\n  test('when env defined for optional then emit \"optionEnv\" with value', () => {\n    const program = new commander.Command();\n    program.on('optionEnv:foo', optionEnvEventMock);\n    process.env.BAR = 'env';\n    program.addOption(new commander.Option('-f, --foo [optional]').env('BAR'));\n    program.parse([], { from: 'user' });\n    expect(optionEnvEventMock).toHaveBeenCalledWith('env');\n  });\n\n  test('when env defined for boolean then emit \"optionEnv\" with no param', () => {\n    // check matches historical boolean action event\n    const program = new commander.Command();\n    program.on('optionEnv:foo', optionEnvEventMock);\n    process.env.BAR = 'anything';\n    program.addOption(new commander.Option('-f, --foo').env('BAR'));\n    program.parse([], { from: 'user' });\n    expect(optionEnvEventMock).toHaveBeenCalledWith();\n  });\n\n  test('when env defined for negated boolean then emit \"optionEnv\" with no param', () => {\n    // check matches historical boolean action event\n    const program = new commander.Command();\n    program.on('optionEnv:no-foo', optionEnvEventMock);\n    process.env.BAR = 'anything';\n    program.addOption(new commander.Option('-F, --no-foo').env('BAR'));\n    program.parse([], { from: 'user' });\n    expect(optionEnvEventMock).toHaveBeenCalledWith();\n  });\n});\n"
  },
  {
    "path": "tests/options.flags.test.js",
    "content": "const commander = require('../');\n\n// Test the various ways flags can be specified in the first parameter to `.option`\n\ntest('when only short flag defined and not specified then value is undefined', () => {\n  const program = new commander.Command();\n  program.option('-p', 'add pepper');\n  program.parse(['node', 'test']);\n  expect(program.opts().p).toBeUndefined();\n});\n\ntest('when only short flag defined and specified then value is true', () => {\n  const program = new commander.Command();\n  program.option('-p', 'add pepper');\n  program.parse(['node', 'test', '-p']);\n  expect(program.opts().p).toBe(true);\n});\n\ntest('when only long flag defined and not specified then value is undefined', () => {\n  const program = new commander.Command();\n  program.option('--pepper', 'add pepper');\n  program.parse(['node', 'test']);\n  expect(program.opts().pepper).toBeUndefined();\n});\n\ntest('when only long flag defined and specified then value is true', () => {\n  const program = new commander.Command();\n  program.option('--pepper', 'add pepper');\n  program.parse(['node', 'test', '--pepper']);\n  expect(program.opts().pepper).toBe(true);\n});\n\ntest('when \"short,long\" flags defined and short specified then value is true', () => {\n  const program = new commander.Command();\n  program.option('-p,--pepper', 'add pepper');\n  program.parse(['node', 'test', '-p']);\n  expect(program.opts().pepper).toBe(true);\n});\n\ntest('when \"short,long\" flags defined and long specified then value is true', () => {\n  const program = new commander.Command();\n  program.option('-p,--pepper', 'add pepper');\n  program.parse(['node', 'test', '--pepper']);\n  expect(program.opts().pepper).toBe(true);\n});\n\ntest('when \"short|long\" flags defined and short specified then value is true', () => {\n  const program = new commander.Command();\n  program.option('-p|--pepper', 'add pepper');\n  program.parse(['node', 'test', '-p']);\n  expect(program.opts().pepper).toBe(true);\n});\n\ntest('when \"short|long\" flags defined and long specified then value is true', () => {\n  const program = new commander.Command();\n  program.option('-p|--pepper', 'add pepper');\n  program.parse(['node', 'test', '--pepper']);\n  expect(program.opts().pepper).toBe(true);\n});\n\ntest('when \"short long\" flags defined and short specified then value is true', () => {\n  const program = new commander.Command();\n  program.option('-p --pepper', 'add pepper');\n  program.parse(['node', 'test', '-p']);\n  expect(program.opts().pepper).toBe(true);\n});\n\ntest('when \"short long\" flags defined and long specified then value is true', () => {\n  const program = new commander.Command();\n  program.option('-p --pepper', 'add pepper');\n  program.parse(['node', 'test', '--pepper']);\n  expect(program.opts().pepper).toBe(true);\n});\n"
  },
  {
    "path": "tests/options.getset.test.js",
    "content": "const commander = require('../');\n\ndescribe.each([true, false])(\n  'storeOptionsAsProperties is %s',\n  (storeOptionsAsProperties) => {\n    test('when option specified on CLI then value returned by getOptionValue', () => {\n      const program = new commander.Command();\n      program\n        .storeOptionsAsProperties(storeOptionsAsProperties)\n        .option('--cheese [type]', 'cheese type');\n      const cheeseType = 'blue';\n      program.parse(['node', 'test', '--cheese', cheeseType]);\n      expect(program.getOptionValue('cheese')).toBe(cheeseType);\n    });\n\n    test('when setOptionValue then value returned by opts', () => {\n      const program = new commander.Command();\n      const cheeseType = 'blue';\n      // Note: opts() only returns declared options when options stored as properties\n      program\n        .storeOptionsAsProperties(storeOptionsAsProperties)\n        .option('--cheese [type]', 'cheese type')\n        .setOptionValue('cheese', cheeseType);\n      expect(program.opts().cheese).toBe(cheeseType);\n    });\n  },\n);\n\ntest('when setOptionValueWithSource then value returned by opts', () => {\n  const program = new commander.Command();\n  const cheeseValue = 'blue';\n  program\n    .option('--cheese [type]', 'cheese type')\n    .setOptionValueWithSource('cheese', cheeseValue, 'cli');\n  expect(program.opts().cheese).toBe(cheeseValue);\n});\n\ntest('when setOptionValueWithSource then source returned by getOptionValueSource', () => {\n  const program = new commander.Command();\n  program\n    .option('--cheese [type]', 'cheese type')\n    .setOptionValueWithSource('cheese', 'blue', 'config');\n  expect(program.getOptionValueSource('cheese')).toBe('config');\n});\n\ntest('when option value parsed from env then option source is env', () => {\n  const program = new commander.Command();\n  process.env.BAR = 'env';\n  program.addOption(new commander.Option('-f, --foo').env('BAR'));\n  program.parse([], { from: 'user' });\n  expect(program.getOptionValueSource('foo')).toBe('env');\n  delete process.env.BAR;\n});\n\ntest('when option value parsed from cli then option source is cli', () => {\n  const program = new commander.Command();\n  program.addOption(new commander.Option('-f, --foo').env('BAR'));\n  program.parse(['--foo'], { from: 'user' });\n  expect(program.getOptionValueSource('foo')).toBe('cli');\n});\n\ntest('when setOptionValue then clears previous source', () => {\n  const program = new commander.Command();\n  program.option('--foo', 'description', 'default value');\n  expect(program.getOptionValueSource('foo')).toBe('default');\n  program.setOptionValue('foo', 'bar');\n  expect(program.getOptionValueSource('foo')).toBeUndefined();\n});\n"
  },
  {
    "path": "tests/options.implies.test.js",
    "content": "const { Command, Option } = require('../');\n\ndescribe('check priorities', () => {\n  test('when source undefined and implied undefined then implied is undefined', () => {\n    const program = new Command();\n    program\n      .addOption(new Option('--foo').implies({ bar: 'implied' }))\n      .option('--bar');\n    program.parse([], { from: 'user' });\n    expect(program.opts()).toEqual({});\n  });\n\n  test('when source default and implied undefined then implied is undefined', () => {\n    const program = new Command();\n    program\n      .addOption(\n        new Option('--foo').implies({ bar: 'implied' }).default('default'),\n      )\n      .option('--bar');\n    program.parse([], { from: 'user' });\n    expect(program.opts()).toEqual({ foo: 'default' });\n  });\n\n  test('when source from env and implied undefined then implied is implied', () => {\n    const program = new Command();\n    const envName = 'COMMANDER_TEST_DELETE_ME';\n    process.env[envName] = 'env';\n    program\n      .addOption(new Option('--foo').implies({ bar: 'implied' }).env(envName))\n      .option('--bar');\n    program.parse([], { from: 'user' });\n    expect(program.opts()).toEqual({ foo: true, bar: 'implied' });\n    delete process.env[envName];\n  });\n\n  test('when source from cli and implied undefined then implied is implied', () => {\n    const program = new Command();\n    program\n      .addOption(new Option('--foo').implies({ bar: 'implied' }))\n      .option('--bar');\n    program.parse(['--foo'], { from: 'user' });\n    expect(program.opts()).toEqual({ foo: true, bar: 'implied' });\n  });\n\n  test('when source cli and implied default then implied is implied', () => {\n    const program = new Command();\n    program\n      .addOption(new Option('--foo').implies({ bar: 'implied' }))\n      .option('--bar', '', 'default');\n    program.parse(['--foo'], { from: 'user' });\n    expect(program.opts()).toEqual({ foo: true, bar: 'implied' });\n  });\n\n  test('when source cli and env default then implied is env', () => {\n    const program = new Command();\n    const envName = 'COMMANDER_TEST_DELETE_ME';\n    process.env[envName] = 'env';\n    program\n      .addOption(new Option('--foo').implies({ bar: 'implied' }))\n      .addOption(new Option('--bar <value>').env(envName));\n    program.parse(['--foo'], { from: 'user' });\n    expect(program.opts()).toEqual({ foo: true, bar: 'env' });\n    delete process.env[envName];\n  });\n});\n\ntest('when imply non-option then ok and stored', () => {\n  const program = new Command();\n  program.addOption(new Option('--foo').implies({ bar: 'implied' }));\n  program.parse(['--foo'], { from: 'user' });\n  expect(program.opts()).toEqual({ foo: true, bar: 'implied' });\n});\n\ntest('when imply multiple values then store multiple values', () => {\n  const program = new Command();\n  program\n    .addOption(new Option('--foo').implies({ one: 'ONE', two: 'TWO' }))\n    .option('--one')\n    .option('--two');\n  program.parse(['--foo'], { from: 'user' });\n  expect(program.opts()).toEqual({ foo: true, one: 'ONE', two: 'TWO' });\n});\n\ntest('when imply multiple times then store multiple values', () => {\n  const program = new Command();\n  program\n    .addOption(\n      new Option('--foo').implies({ one: 'ONE' }).implies({ two: 'TWO' }),\n    )\n    .option('--one')\n    .option('--two');\n  program.parse(['--foo'], { from: 'user' });\n  expect(program.opts()).toEqual({ foo: true, one: 'ONE', two: 'TWO' });\n});\n\ntest('when imply from positive option then positive implied', () => {\n  const program = new Command();\n  program\n    .addOption(new Option('--foo').implies({ implied: 'POSITIVE' }))\n    .addOption(new Option('--no-foo').implies({ implied: 'NEGATIVE' }));\n  program.parse(['--foo'], { from: 'user' });\n  expect(program.opts()).toEqual({ foo: true, implied: 'POSITIVE' });\n});\n\ntest('when imply from negative option then negative implied', () => {\n  const program = new Command();\n  program\n    .addOption(new Option('--foo').implies({ implied: 'POSITIVE' }))\n    .addOption(new Option('--no-foo').implies({ implied: 'NEGATIVE' }));\n  program.parse(['--no-foo'], { from: 'user' });\n  expect(program.opts()).toEqual({ foo: false, implied: 'NEGATIVE' });\n});\n\ntest('when imply from lone negative option then negative implied', () => {\n  const program = new Command();\n  program.addOption(new Option('--no-foo').implies({ implied: 'NEGATIVE' }));\n  program.parse(['--no-foo'], { from: 'user' });\n  expect(program.opts()).toEqual({ foo: false, implied: 'NEGATIVE' });\n});\n\ntest('when imply from negative option with preset then negative implied', () => {\n  const program = new Command();\n  program\n    .addOption(new Option('--foo').implies({ implied: 'POSITIVE' }))\n    .addOption(\n      new Option('--no-foo').implies({ implied: 'NEGATIVE' }).preset('FALSE'),\n    );\n  program.parse(['--no-foo'], { from: 'user' });\n  expect(program.opts()).toEqual({ foo: 'FALSE', implied: 'NEGATIVE' });\n});\n\ntest('when chained implies then only explicitly trigger', () => {\n  const program = new Command();\n  program\n    .addOption(new Option('--one').implies({ two: true }))\n    .addOption(new Option('--two').implies({ three: true }))\n    .addOption(new Option('--three'));\n  program.parse(['--one'], { from: 'user' });\n  expect(program.opts()).toEqual({ one: true, two: true });\n});\n\ntest('when looped implies then no infinite loop', () => {\n  const program = new Command();\n  program\n    .addOption(new Option('--ying').implies({ yang: true }))\n    .addOption(new Option('--yang').implies({ ying: true }));\n  program.parse(['--ying'], { from: 'user' });\n  expect(program.opts()).toEqual({ ying: true, yang: true });\n});\n\ntest('when conflict with implied value then throw', () => {\n  const program = new Command();\n  program\n    .exitOverride()\n    .configureOutput({\n      writeErr: () => {},\n    })\n    .addOption(new Option('--unary'))\n    .addOption(new Option('--binary').conflicts('unary'))\n    .addOption(new Option('--one').implies({ unary: true }));\n\n  expect(() => {\n    program.parse(['--binary', '--one'], { from: 'user' });\n  }).toThrow();\n});\n\ntest('when requiredOption with implied value then not throw', () => {\n  const program = new Command();\n  program\n    .requiredOption('--target <target-file>')\n    .addOption(\n      new Option('--default-target').implies({ target: 'default-file' }),\n    );\n\n  expect(() => {\n    program.parse(['--default-target'], { from: 'user' });\n  }).not.toThrow();\n});\n\ntest('when implies on program and use subcommand then program updated', () => {\n  const program = new Command();\n  program.addOption(new Option('--foo').implies({ bar: 'implied' }));\n  program.command('sub').action(() => {});\n  program.parse(['--foo', 'sub'], { from: 'user' });\n  expect(program.opts().bar).toEqual('implied');\n});\n\ntest('when option with implies used multiple times then implied gets single value', () => {\n  const program = new Command();\n  program\n    .addOption(new Option('--foo').implies({ bar: 'implied' }))\n    .option('-b, --bar <value...>');\n  program.parse(['--foo', '--foo'], { from: 'user' });\n  expect(program.opts().bar).toEqual('implied');\n});\n\ntest('when implied option has custom processing then custom processing not called', () => {\n  let called = false;\n  const program = new Command();\n  program\n    .addOption(new Option('--foo').implies({ bar: true }))\n    .option('-b, --bar', 'description', () => {\n      called = true;\n    });\n  program.parse(['--foo'], { from: 'user' });\n  expect(program.opts().bar).toEqual(true);\n  expect(called).toEqual(false);\n});\n\ntest('when passed string then treat as boolean', () => {\n  // Do something sensible instead of something silly if user passes just name of option.\n  // https://github.com/tj/commander.js/issues/1852\n  const program = new Command();\n  program\n    .addOption(new Option('--foo').implies('bar'))\n    .option('-b, --bar', 'description');\n  program.parse(['--foo'], { from: 'user' });\n  expect(program.opts().bar).toEqual(true);\n});\n"
  },
  {
    "path": "tests/options.mandatory.test.js",
    "content": "const commander = require('../');\n\n// Assuming mandatory options behave as normal options apart from the mandatory aspect, not retesting all behaviour.\n// Likewise, not redoing all tests on subcommand after testing on program.\n\ndescribe('required program option with mandatory value specified', () => {\n  test('when program has required value specified then value as specified', () => {\n    const program = new commander.Command();\n    program.exitOverride().requiredOption('--cheese <type>', 'cheese type');\n    program.parse(['node', 'test', '--cheese', 'blue']);\n    expect(program.opts().cheese).toBe('blue');\n  });\n\n  test('when program has option with name different than property then still recognised', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .requiredOption('--cheese-type <type>', 'cheese type');\n    program.parse(['node', 'test', '--cheese-type', 'blue']);\n    expect(program.opts().cheeseType).toBe('blue');\n  });\n\n  test('when program has required value default then default value', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .requiredOption('--cheese <type>', 'cheese type', 'default');\n    program.parse(['node', 'test']);\n    expect(program.opts().cheese).toBe('default');\n  });\n\n  test('when program has optional value flag specified then true', () => {\n    const program = new commander.Command();\n    program.exitOverride().requiredOption('--cheese [type]', 'cheese type');\n    program.parse(['node', 'test', '--cheese']);\n    expect(program.opts().cheese).toBe(true);\n  });\n\n  test('when program has optional value default then default value', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .requiredOption('--cheese [type]', 'cheese type', 'default');\n    program.parse(['node', 'test']);\n    expect(program.opts().cheese).toBe('default');\n  });\n\n  test('when program has value/no flag specified with value then specified value', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .requiredOption('--cheese <type>', 'cheese type')\n      .requiredOption('--no-cheese', 'no cheese thanks');\n    program.parse(['node', 'test', '--cheese', 'blue']);\n    expect(program.opts().cheese).toBe('blue');\n  });\n\n  test('when program has mandatory-yes/no flag specified with flag then true', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .requiredOption('--cheese', 'cheese type')\n      .option('--no-cheese', 'no cheese thanks');\n    program.parse(['node', 'test', '--cheese']);\n    expect(program.opts().cheese).toBe(true);\n  });\n\n  test('when program has mandatory-yes/mandatory-no flag specified with flag then true', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .requiredOption('--cheese', 'cheese type')\n      .requiredOption('--no-cheese', 'no cheese thanks');\n    program.parse(['node', 'test', '--cheese']);\n    expect(program.opts().cheese).toBe(true);\n  });\n\n  test('when program has yes/no flag specified negated then false', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .requiredOption('--cheese <type>', 'cheese type')\n      .option('--no-cheese', 'no cheese thanks');\n    program.parse(['node', 'test', '--no-cheese']);\n    expect(program.opts().cheese).toBe(false);\n  });\n\n  test('when program has required value specified and subcommand then specified value', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .requiredOption('--cheese <type>', 'cheese type')\n      .command('sub')\n      .action(() => {});\n    program.parse(['node', 'test', '--cheese', 'blue', 'sub']);\n    expect(program.opts().cheese).toBe('blue');\n  });\n});\n\ndescribe('required program option with mandatory value not specified', () => {\n  // Optional. Use internal knowledge to suppress output to keep test output clean.\n  let writeErrorSpy;\n\n  beforeAll(() => {\n    writeErrorSpy = jest\n      .spyOn(process.stderr, 'write')\n      .mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    writeErrorSpy.mockClear();\n  });\n\n  afterAll(() => {\n    writeErrorSpy.mockRestore();\n  });\n\n  test('when program has required option not specified then error', () => {\n    const program = new commander.Command();\n    program.exitOverride().requiredOption('--cheese <type>', 'cheese type');\n\n    expect(() => {\n      program.parse(['node', 'test']);\n    }).toThrow();\n  });\n\n  test('when program has optional option not specified then error', () => {\n    const program = new commander.Command();\n    program.exitOverride().requiredOption('--cheese [type]', 'cheese type');\n\n    expect(() => {\n      program.parse(['node', 'test']);\n    }).toThrow();\n  });\n\n  test('when program has yes/no not specified then error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .requiredOption('--cheese', 'cheese type')\n      .option('--no-cheese', 'no cheese thanks');\n\n    expect(() => {\n      program.parse(['node', 'test']);\n    }).toThrow();\n  });\n\n  test('when program has required value not specified and subcommand then error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .requiredOption('--cheese <type>', 'cheese type')\n      .command('sub')\n      .action(() => {});\n\n    expect(() => {\n      program.parse(['node', 'test', 'sub']);\n    }).toThrow();\n  });\n});\n\ndescribe('required command option with mandatory value specified', () => {\n  test('when command has required value specified then no error and option has specified value', () => {\n    const program = new commander.Command();\n    let cmdOptions;\n    program\n      .exitOverride()\n      .command('sub')\n      .requiredOption('--subby <type>', 'description')\n      .action((options) => {\n        cmdOptions = options;\n      });\n\n    program.parse(['node', 'test', 'sub', '--subby', 'blue']);\n\n    expect(cmdOptions.subby).toBe('blue');\n  });\n\n  test('when command has required value specified using env then no error and option has specified value', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .addOption(\n        new commander.Option('-p, --port <number>', 'port number')\n          .makeOptionMandatory()\n          .env('FOO'),\n      );\n\n    process.env.FOO = 'bar';\n    program.parse([], { from: 'user' });\n    delete process.env.FOO;\n\n    expect(program.opts().port).toBe('bar');\n  });\n});\n\ndescribe('required command option with mandatory value not specified', () => {\n  // Optional. Use internal knowledge to suppress output to keep test output clean.\n  let writeErrorSpy;\n\n  beforeAll(() => {\n    writeErrorSpy = jest\n      .spyOn(process.stderr, 'write')\n      .mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    writeErrorSpy.mockClear();\n  });\n\n  afterAll(() => {\n    writeErrorSpy.mockRestore();\n  });\n\n  test('when command has required value not specified then error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .command('sub')\n      .requiredOption('--subby <type>', 'description')\n      .action(() => {});\n\n    expect(() => {\n      program.parse(['node', 'test', 'sub']);\n    }).toThrow();\n  });\n\n  test('when command has required value but not called then no error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .command('sub')\n      .requiredOption('--subby <type>', 'description')\n      .action(() => {});\n    program.command('sub2');\n\n    expect(() => {\n      program.parse(['node', 'test', 'sub2']);\n    }).not.toThrow();\n  });\n});\n\ndescribe('missing mandatory option but help requested', () => {\n  // Optional. Use internal knowledge to suppress output to keep test output clean.\n  let writeSpy;\n\n  beforeAll(() => {\n    writeSpy = jest.spyOn(process.stdout, 'write').mockImplementation(() => {});\n  });\n\n  afterEach(() => {\n    writeSpy.mockClear();\n  });\n\n  afterAll(() => {\n    writeSpy.mockRestore();\n  });\n\n  test('when program has required option not specified and --help then help', () => {\n    const program = new commander.Command();\n    program.exitOverride().requiredOption('--cheese <type>', 'cheese type');\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', '--help']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expect(caughtErr.code).toEqual('commander.helpDisplayed');\n  });\n\n  test('when program has required option not specified and subcommand --help then help', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .requiredOption('--cheese <type>', 'cheese type')\n      .command('sub')\n      .action(() => {});\n\n    let caughtErr;\n    try {\n      program.parse(['node', 'test', 'sub', '--help']);\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    expect(caughtErr.code).toEqual('commander.helpDisplayed');\n  });\n});\n"
  },
  {
    "path": "tests/options.optional.test.js",
    "content": "const commander = require('../');\n\n// option with optional value, no default\ndescribe('option with optional value, no default', () => {\n  test('when option not specified then value is undefined', () => {\n    const program = new commander.Command();\n    program.option('--cheese [type]', 'cheese type');\n    program.parse(['node', 'test']);\n    expect(program.opts().cheese).toBeUndefined();\n  });\n\n  test('when option specified then value is as specified', () => {\n    const program = new commander.Command();\n    program.option('--cheese [type]', 'cheese type');\n    const cheeseType = 'blue';\n    program.parse(['node', 'test', '--cheese', cheeseType]);\n    expect(program.opts().cheese).toBe(cheeseType);\n  });\n\n  test('when option specified without value then value is true', () => {\n    const program = new commander.Command();\n    program.option('--cheese [type]', 'cheese type');\n    program.parse(['node', 'test', '--cheese']);\n    expect(program.opts().cheese).toBe(true);\n  });\n\n  test('when option specified without value and following option then value is true', () => {\n    // optional options do not eat values with dashes\n    const program = new commander.Command();\n    program.option('--cheese [type]', 'cheese type').option('--some-option');\n    program.parse(['node', 'test', '--cheese', '--some-option']);\n    expect(program.opts().cheese).toBe(true);\n  });\n});\n\n// option with optional value, with default\ndescribe('option with optional value, with default', () => {\n  test('when option not specified then value is default', () => {\n    const defaultValue = 'default';\n    const program = new commander.Command();\n    program.option('--cheese [type]', 'cheese type', defaultValue);\n    program.parse(['node', 'test']);\n    expect(program.opts().cheese).toBe(defaultValue);\n  });\n\n  test('when option specified then value is as specified', () => {\n    const defaultValue = 'default';\n    const program = new commander.Command();\n    program.option('--cheese [type]', 'cheese type', defaultValue);\n    const cheeseType = 'blue';\n    program.parse(['node', 'test', '--cheese', cheeseType]);\n    expect(program.opts().cheese).toBe(cheeseType);\n  });\n\n  test('when option specified without value then value is true', () => {\n    const defaultValue = 'default';\n    const program = new commander.Command();\n    program.option('--cheese [type]', 'cheese type', defaultValue);\n    program.parse(['node', 'test', '--cheese']);\n    expect(program.opts().cheese).toBe(true);\n  });\n\n  test('when option specified without value and preset then value is preset', () => {\n    const program = new commander.Command();\n    program.addOption(new commander.Option('--cheese [type]').preset('preset'));\n    program.parse(['node', 'test', '--cheese']);\n    expect(program.opts().cheese).toBe('preset');\n  });\n});\n"
  },
  {
    "path": "tests/options.opts.test.js",
    "content": "const commander = require('../');\n\n// Test the `.opts()` way of accessing option values.\n// Basic coverage of the main option types (leaving out negatable flags and options with optional values).\n\ntest('when .version used with storeOptionsAsProperties() then version in opts', () => {\n  const program = new commander.Command();\n  const version = '0.0.1';\n  program.storeOptionsAsProperties().version(version);\n  program.parse(['node', 'test']);\n  expect(program.opts()).toEqual({ version });\n});\n\ntest('when .version used with storeOptionsAsProperties(false) then version not in opts', () => {\n  // New behaviour, stop storing version as an option value.\n  const program = new commander.Command();\n  const version = '0.0.1';\n  program.storeOptionsAsProperties(false).version(version);\n  program.parse(['node', 'test']);\n  expect(program.opts()).toEqual({});\n});\n\ndescribe.each([true, false])(\n  'storeOptionsAsProperties is %s',\n  (storeOptionsAsProperties) => {\n    test('when boolean flag not specified then not in opts', () => {\n      const program = new commander.Command();\n      program.storeOptionsAsProperties(storeOptionsAsProperties);\n      program.option('--pepper', 'add pepper');\n      program.parse(['node', 'test']);\n      expect(program.opts()).toEqual({});\n    });\n\n    test('when boolean flag specified then value true', () => {\n      const program = new commander.Command();\n      program.storeOptionsAsProperties(storeOptionsAsProperties);\n      program.option('--pepper', 'add pepper');\n      program.parse(['node', 'test', '--pepper']);\n      expect(program.opts()).toEqual({ pepper: true });\n    });\n\n    test('when option with required value not specified then not in opts', () => {\n      const program = new commander.Command();\n      program.storeOptionsAsProperties(storeOptionsAsProperties);\n      program.option('--pepper <flavour>', 'add pepper');\n      program.parse(['node', 'test']);\n      expect(program.opts()).toEqual({});\n    });\n\n    test('when option with required value specified then value as specified', () => {\n      const pepperValue = 'red';\n      const program = new commander.Command();\n      program.storeOptionsAsProperties(storeOptionsAsProperties);\n      program.option('--pepper <flavour>', 'add pepper');\n      program.parse(['node', 'test', '--pepper', pepperValue]);\n      expect(program.opts()).toEqual({ pepper: pepperValue });\n    });\n\n    test('when option with default value not specified then default value in opts', () => {\n      const pepperDefault = 'red';\n      const program = new commander.Command();\n      program.storeOptionsAsProperties(storeOptionsAsProperties);\n      program.option('--pepper <flavour>', 'add pepper', pepperDefault);\n      program.parse(['node', 'test']);\n      expect(program.opts()).toEqual({ pepper: pepperDefault });\n    });\n  },\n);\n"
  },
  {
    "path": "tests/options.optsWithGlobals.test.js",
    "content": "const commander = require('../');\n\n// Testing optsWithGlobals and getOptionValueSourceWithGlobals with focus on globals.\n\ndescribe('optsWithGlobals', () => {\n  test('when variety of options used with program then opts is same as optsWithGlobals', () => {\n    const program = new commander.Command();\n    program\n      .option('-b, --boolean')\n      .option('-r, --require-value <value)')\n      .option('-f, --float <value>', 'description', parseFloat)\n      .option('-d, --default-value <value)', 'description', 'default value')\n      .option('-n, --no-something');\n\n    program.parse(['-b', '-r', 'req', '-f', '1e2'], { from: 'user' });\n    expect(program.opts()).toEqual(program.optsWithGlobals());\n  });\n\n  test('when options in sub and program then optsWithGlobals includes both', () => {\n    const program = new commander.Command();\n    let mergedOptions;\n    program.option('-g, --global <value>');\n    program\n      .command('sub')\n      .option('-l, --local <value)')\n      .action((options, cmd) => {\n        mergedOptions = cmd.optsWithGlobals();\n      });\n\n    program.parse(['-g', 'GGG', 'sub', '-l', 'LLL'], { from: 'user' });\n    expect(mergedOptions).toEqual({ global: 'GGG', local: 'LLL' });\n  });\n\n  test('when options in sub and subsub then optsWithGlobals includes both', () => {\n    const program = new commander.Command();\n    let mergedOptions;\n    program\n      .command('sub')\n      .option('-g, --global <value)')\n      .command('subsub')\n      .option('-l, --local <value)')\n      .action((options, cmd) => {\n        mergedOptions = cmd.optsWithGlobals();\n      });\n\n    program.parse(['sub', '-g', 'GGG', 'subsub', '-l', 'LLL'], {\n      from: 'user',\n    });\n    expect(mergedOptions).toEqual({ global: 'GGG', local: 'LLL' });\n  });\n\n  test('when same named option in sub and program then optsWithGlobals includes global', () => {\n    const program = new commander.Command();\n    let mergedOptions;\n    program.option('-c, --common <value>').enablePositionalOptions();\n    program\n      .command('sub')\n      .option('-c, --common <value)')\n      .action((options, cmd) => {\n        mergedOptions = cmd.optsWithGlobals();\n      });\n\n    program.parse(['-c', 'GGG', 'sub', '-c', 'LLL'], { from: 'user' });\n    expect(mergedOptions).toEqual({ common: 'GGG' });\n  });\n});\n\ndescribe('getOptionValueSourceWithGlobals', () => {\n  test('when option used with simple command then source is defined', () => {\n    const program = new commander.Command();\n    program.option('-g, --global');\n\n    program.parse(['-g'], { from: 'user' });\n    expect(program.getOptionValueSourceWithGlobals('global')).toEqual('cli');\n  });\n\n  test('when option used with program then source is defined', () => {\n    const program = new commander.Command();\n    program.option('-g, --global');\n    const sub = program\n      .command('sub')\n      .option('-l, --local')\n      .action(() => {});\n\n    program.parse(['sub', '-g'], { from: 'user' });\n    expect(sub.getOptionValueSourceWithGlobals('global')).toEqual('cli');\n  });\n\n  test('when option used with subcommand then source is defined', () => {\n    const program = new commander.Command();\n    program.option('-g, --global');\n    const sub = program\n      .command('sub')\n      .option('-l, --local')\n      .action(() => {});\n\n    program.parse(['sub', '-l'], { from: 'user' });\n    expect(sub.getOptionValueSourceWithGlobals('local')).toEqual('cli');\n  });\n\n  test('when same named option in sub and program then source is defined by global', () => {\n    const program = new commander.Command();\n    program\n      .enablePositionalOptions()\n      .option('-c, --common <value>', 'description', 'default value');\n    const sub = program\n      .command('sub')\n      .option('-c, --common <value>')\n      .action(() => {});\n\n    program.parse(['sub', '--common', 'value'], { from: 'user' });\n    expect(sub.getOptionValueSourceWithGlobals('common')).toEqual('default');\n  });\n});\n"
  },
  {
    "path": "tests/options.preset.test.js",
    "content": "const { Command, Option } = require('../');\n\ntest('when boolean option with string preset used then value is preset', () => {\n  const program = new Command();\n  program.addOption(new Option('-d, --debug').preset('foo'));\n  program.parse(['-d'], { from: 'user' });\n  expect(program.opts().debug).toBe('foo');\n});\n\ntest('when boolean option with number preset used then value is preset', () => {\n  const program = new Command();\n  program.addOption(new Option('-d, --debug').preset(80));\n  program.parse(['-d'], { from: 'user' });\n  expect(program.opts().debug).toBe(80);\n});\n\ntest('when optional with string preset used then value is preset', () => {\n  const program = new Command();\n  program.addOption(new Option('-p, --port [port]').preset('foo'));\n  program.parse(['-p'], { from: 'user' });\n  expect(program.opts().port).toBe('foo');\n});\n\ntest('when optional with number preset used then value is preset', () => {\n  const program = new Command();\n  program.addOption(new Option('-p, --port [port]').preset(80));\n  program.parse(['-p'], { from: 'user' });\n  expect(program.opts().port).toBe(80);\n});\n\ntest('when optional with string preset used with option-argument then value is as specified', () => {\n  const program = new Command();\n  program.addOption(new Option('-p, --port [port]').preset('foo'));\n  program.parse(['-p', '1234'], { from: 'user' });\n  expect(program.opts().port).toBe('1234');\n});\n\ntest('when optional with preset and coerce used then preset is coerced', () => {\n  const program = new Command();\n  program.addOption(\n    new Option('-p, --port [port]').preset('4').argParser(parseFloat),\n  );\n  program.parse(['-p'], { from: 'user' });\n  expect(program.opts().port).toBe(4);\n});\n\ntest('when optional with preset and variadic used then preset is concatenated', () => {\n  const program = new Command();\n  program.addOption(new Option('-n, --name [name...]').preset('two'));\n  program.parse(['-n', 'one', '-n', '-n', 'three'], { from: 'user' });\n  expect(program.opts().name).toEqual(['one', 'two', 'three']);\n});\n\ntest('when negated with string preset used then value is preset', () => {\n  const program = new Command();\n  program.addOption(new Option('--no-colour').preset('foo'));\n  program.parse(['--no-colour'], { from: 'user' });\n  expect(program.opts().colour).toBe('foo');\n});\n"
  },
  {
    "path": "tests/options.registerClash.test.js",
    "content": "const { Command, Option } = require('../');\n\ndescribe('.option()', () => {\n  test('when short option flag conflicts then throws', () => {\n    expect(() => {\n      const program = new Command();\n      program\n        .option('-c, --cheese <type>', 'cheese type')\n        .option('-c, --conflict');\n    }).toThrow('Cannot add option');\n  });\n\n  test('when long option flag conflicts then throws', () => {\n    expect(() => {\n      const program = new Command();\n      program\n        .option('-c, --cheese <type>', 'cheese type')\n        .option('-H, --cheese');\n    }).toThrow('Cannot add option');\n  });\n\n  test('when use help options separately then does not throw', () => {\n    expect(() => {\n      const program = new Command();\n      program.option('-h, --help', 'display help');\n    }).not.toThrow();\n  });\n\n  test('when reuse flags in subcommand then does not throw', () => {\n    expect(() => {\n      const program = new Command();\n      program.option('-e, --example');\n      program.command('sub').option('-e, --example');\n    }).not.toThrow();\n  });\n});\n\ndescribe('.addOption()', () => {\n  test('when short option flags conflicts then throws', () => {\n    expect(() => {\n      const program = new Command();\n      program\n        .option('-c, --cheese <type>', 'cheese type')\n        .addOption(new Option('-c, --conflict'));\n    }).toThrow('Cannot add option');\n  });\n\n  test('when long option flags conflicts then throws', () => {\n    expect(() => {\n      const program = new Command();\n      program\n        .option('-c, --cheese <type>', 'cheese type')\n        .addOption(new Option('-H, --cheese'));\n    }).toThrow('Cannot add option');\n  });\n});\n"
  },
  {
    "path": "tests/options.required.test.js",
    "content": "const commander = require('../');\n\n// option with required value, no default\ndescribe('option with required value, no default', () => {\n  test('when option not specified then value is undefined', () => {\n    const program = new commander.Command();\n    program.option('--cheese <type>', 'cheese type');\n    program.parse(['node', 'test']);\n    expect(program.opts().cheese).toBeUndefined();\n  });\n\n  test('when option specified then value is as specified', () => {\n    const program = new commander.Command();\n    program.option('--cheese <type>', 'cheese type');\n    const cheeseType = 'blue';\n    program.parse(['node', 'test', '--cheese', cheeseType]);\n    expect(program.opts().cheese).toBe(cheeseType);\n  });\n\n  test('when option value not specified then error', () => {\n    // Arrange. Mock error routine to allow interception.\n    const mockOptionMissingArgument = jest.fn(() => {\n      throw new Error('optionMissingArgument');\n    });\n    const program = new commander.Command();\n    program.optionMissingArgument = mockOptionMissingArgument;\n    program.option('--cheese <type>', 'cheese type');\n\n    // Act. The throw is due to the above mock, and not default behaviour.\n    expect(() => {\n      program.parse(['node', 'test', '--cheese']);\n    }).toThrow();\n\n    // Assert\n    expect(mockOptionMissingArgument).toHaveBeenCalled();\n  });\n});\n\n// option with required value, with default\ndescribe('option with required value, with default', () => {\n  test('when option not specified then value is default', () => {\n    const defaultValue = 'default';\n    const program = new commander.Command();\n    program.option('--cheese <type>', 'cheese type', defaultValue);\n    program.parse(['node', 'test']);\n    expect(program.opts().cheese).toBe(defaultValue);\n  });\n\n  test('when option specified then value is as specified', () => {\n    const defaultValue = 'default';\n    const program = new commander.Command();\n    program.option('--cheese <type>', 'cheese type', defaultValue);\n    const cheeseType = 'blue';\n    program.parse(['node', 'test', '--cheese', cheeseType]);\n    expect(program.opts().cheese).toBe(cheeseType);\n  });\n\n  test('when option value not specified then error', () => {\n    // Arrange. Mock error routine to allow interception.\n    const mockOptionMissingArgument = jest.fn(() => {\n      throw new Error('optionMissingArgument');\n    });\n    const defaultValue = 'default';\n    const program = new commander.Command();\n    program.optionMissingArgument = mockOptionMissingArgument;\n    program.option('--cheese <type>', 'cheese type', defaultValue);\n\n    // Act. The throw is due to the above mock, and not default behaviour.\n    expect(() => {\n      program.parse(['node', 'test', '--cheese']);\n    }).toThrow();\n\n    // Assert\n    expect(mockOptionMissingArgument).toHaveBeenCalled();\n  });\n});\n"
  },
  {
    "path": "tests/options.twice.test.js",
    "content": "const { Command, Option } = require('../');\n\n// Test that when option specified twice, second use wins.\n// Seems pretty obvious for boolean options, but there was a bug before Commander v9.\n\ntest('when boolean option used twice then value is true', () => {\n  const program = new Command();\n  program.option('-d, --debug');\n  program.parse(['-d', '-d'], { from: 'user' });\n  expect(program.opts().debug).toBe(true);\n});\n\ntest('when boolean option with default used twice then value is true', () => {\n  const program = new Command();\n  program.option('-d, --debug', 'description', 'foo');\n  program.parse(['-d', '-d'], { from: 'user' });\n  expect(program.opts().debug).toBe(true);\n});\n\ntest('when boolean option with preset used twice then value is preset', () => {\n  const program = new Command();\n  program.addOption(new Option('-d, --debug').preset('foo'));\n  program.parse(['-d', '-d'], { from: 'user' });\n  expect(program.opts().debug).toBe('foo');\n});\n\ntest('when option with required argument used twice then value is from second use', () => {\n  const program = new Command();\n  program.option('-p, --port <port-number>');\n  program.parse(['-p', '1', '-p', '2'], { from: 'user' });\n  expect(program.opts().port).toBe('2');\n});\n\ntest('when option with optional argument used second time without value then value is true', () => {\n  const program = new Command();\n  program.option('--donate [amount]');\n  program.parse(['--donate', '123', '--donate'], { from: 'user' });\n  expect(program.opts().donate).toBe(true);\n});\n\ntest('when option with optional argument used second time with value then value is from second use', () => {\n  const program = new Command();\n  program.option('--donate [amount]');\n  program.parse(['--donate', '--donate', '123'], { from: 'user' });\n  expect(program.opts().donate).toBe('123');\n});\n"
  },
  {
    "path": "tests/options.values.test.js",
    "content": "const commander = require('../');\n\n// Test the ways values can be specified for options.\n// See also references on \"Utility Conventions\" in command.parseOptions.test.js\n\n// options with required values can eat values starting with a dash, including just dash sometimes used as alias for stdin\n//\n// option with required value, using describe.each to test all matrix of values and tests\ndescribe.each([['str'], ['80'], ['-'], ['-5'], ['--flag']])(\n  'option with required value specified as %s',\n  (value) => {\n    function createPortProgram() {\n      const program = new commander.Command();\n      program.option('-p,--port <number>', 'specify port');\n      return program;\n    }\n\n    test('when short flag followed by value then value is as specified', () => {\n      const program = createPortProgram();\n      program.parse(['node', 'test', '-p', value]);\n      expect(program.opts().port).toBe(value);\n    });\n\n    test('when short flag concatenated with value then value is as specified', () => {\n      const program = createPortProgram();\n      program.parse(['node', 'test', `-p${value}`]);\n      expect(program.opts().port).toBe(value);\n    });\n\n    test('when long flag followed by value then value is as specified', () => {\n      const program = createPortProgram();\n      program.parse(['node', 'test', '--port', value]);\n      expect(program.opts().port).toBe(value);\n    });\n\n    test('when long flag = value then value is as specified', () => {\n      const program = createPortProgram();\n      program.parse(['node', 'test', `--port=${value}`]);\n      expect(program.opts().port).toBe(value);\n    });\n  },\n);\n\n// option with optional value\ndescribe('option with optional value', () => {\n  function createPortProgram() {\n    const program = new commander.Command();\n    program.option('-p,--port [number]', 'specify port');\n    return program;\n  }\n\n  test('when short flag followed by value then value is as specified', () => {\n    const program = createPortProgram();\n    program.parse('node test -p 80'.split(' '));\n    expect(program.opts().port).toBe('80');\n  });\n\n  test('when short flag concatenated with value then value is as specified', () => {\n    const program = createPortProgram();\n    program.parse('node test -p80'.split(' '));\n    expect(program.opts().port).toBe('80');\n  });\n\n  test('when long flag followed by value then value is as specified', () => {\n    const program = createPortProgram();\n    program.parse('node test --port 80'.split(' '));\n    expect(program.opts().port).toBe('80');\n  });\n\n  test('when long flag = value then value is as specified', () => {\n    const program = createPortProgram();\n    program.parse('node test --port=80'.split(' '));\n    expect(program.opts().port).toBe('80');\n  });\n\n  test('when long flag followed empty string then value is empty string', () => {\n    const program = createPortProgram();\n    program.option(\n      '-c, --cheese [type]',\n      'optionally specify the type of cheese',\n    );\n    program.parse(['node', 'test', '--cheese', '']);\n    expect(program.opts().cheese).toBe('');\n  });\n});\n"
  },
  {
    "path": "tests/options.variadic.test.js",
    "content": "const commander = require('../');\n\ndescribe('variadic option with required value', () => {\n  test('when variadic with value missing then error', () => {\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeErr: jest.fn() })\n      .option('-r,--required <value...>');\n\n    expect(() => {\n      program.parse(['--required'], { from: 'user' });\n    }).toThrow();\n  });\n\n  test('when variadic with one value then set in array', () => {\n    const program = new commander.Command();\n    program.option('-r,--required <value...>');\n\n    program.parse(['--required', 'one'], { from: 'user' });\n    expect(program.opts().required).toEqual(['one']);\n  });\n\n  test('when variadic with two values then set in array', () => {\n    const program = new commander.Command();\n    program.option('-r,--required <value...>');\n\n    program.parse(['--required', 'one', 'two'], { from: 'user' });\n    expect(program.opts().required).toEqual(['one', 'two']);\n  });\n\n  test('when variadic with repeated values then set in array', () => {\n    const program = new commander.Command();\n    program.option('-r,--required <value...>');\n\n    program.parse(['--required', 'one', '--required', 'two'], { from: 'user' });\n    expect(program.opts().required).toEqual(['one', 'two']);\n  });\n\n  test('when variadic used with choices and one value then set in array', () => {\n    const program = new commander.Command();\n    program.addOption(\n      new commander.Option('-r,--required <value...>').choices(['one', 'two']),\n    );\n\n    program.parse(['--required', 'one'], { from: 'user' });\n    expect(program.opts().required).toEqual(['one']);\n  });\n\n  test('when variadic used with choices and two values then set in array', () => {\n    const program = new commander.Command();\n    program.addOption(\n      new commander.Option('-r,--required <value...>').choices(['one', 'two']),\n    );\n\n    program.parse(['--required', 'one', 'two'], { from: 'user' });\n    expect(program.opts().required).toEqual(['one', 'two']);\n  });\n\n  test('when variadic with short combined argument then not variadic', () => {\n    const program = new commander.Command();\n    program.option('-r,--required <value...>').argument('[arg]');\n\n    program.parse(['-rone', 'operand'], { from: 'user' });\n    expect(program.opts().required).toEqual(['one']);\n  });\n\n  test('when variadic with long combined argument then not variadic', () => {\n    const program = new commander.Command();\n    program.option('-r,--required <value...>').argument('[arg]');\n\n    program.parse(['--required=one', 'operand'], { from: 'user' });\n    expect(program.opts().required).toEqual(['one']);\n  });\n\n  test('when variadic with value followed by option then option not eaten', () => {\n    const program = new commander.Command();\n    program\n      .option('-r,--required <value...>')\n      .option('-f, --flag')\n      .argument('[arg]');\n\n    program.parse(['-r', 'one', '-f'], { from: 'user' });\n    const opts = program.opts();\n    expect(opts.required).toEqual(['one']);\n    expect(opts.flag).toBe(true);\n  });\n\n  test('when variadic with no value and default then set to default', () => {\n    const program = new commander.Command();\n    program.option(\n      '-r,--required <value...>',\n      'variadic description',\n      'default',\n    );\n\n    program.parse([], { from: 'user' });\n    expect(program.opts().required).toEqual('default');\n  });\n\n  test('when variadic with coercion then coercion sets value', () => {\n    const program = new commander.Command();\n    program.option(\n      '-r,--required <value...>',\n      'variadic description',\n      parseFloat,\n    );\n\n    // variadic processing reads the multiple values, but up to custom coercion what it does.\n    program.parse(['--required', '1e2', '1e3'], { from: 'user' });\n    expect(program.opts().required).toEqual(1000);\n  });\n});\n\n// Not retesting everything, but do some tests on variadic with optional\ndescribe('variadic option with optional value', () => {\n  test('when variadic not specified then value undefined', () => {\n    const program = new commander.Command();\n    program.option('-o,--optional [value...]');\n\n    program.parse([], { from: 'user' });\n    expect(program.opts().optional).toBeUndefined();\n  });\n\n  test('when variadic used as boolean flag then value true', () => {\n    const program = new commander.Command();\n    program.option('-o,--optional [value...]');\n\n    program.parse(['--optional'], { from: 'user' });\n    expect(program.opts().optional).toBe(true);\n  });\n\n  test('when variadic with one value then set in array', () => {\n    const program = new commander.Command();\n    program.option('-o,--optional [value...]');\n\n    program.parse(['--optional', 'one'], { from: 'user' });\n    expect(program.opts().optional).toEqual(['one']);\n  });\n\n  test('when variadic with two values then set in array', () => {\n    const program = new commander.Command();\n    program.option('-o,--optional [value...]');\n\n    program.parse(['--optional', 'one', 'two'], { from: 'user' });\n    expect(program.opts().optional).toEqual(['one', 'two']);\n  });\n});\n\ndescribe('variadic special cases', () => {\n  test('when option flags has word character before dots then is variadic', () => {\n    const program = new commander.Command();\n    program.option('-c,--comma [value...]');\n\n    expect(program.options[0].variadic).toBeTruthy();\n  });\n\n  test('when option flags has special characters before dots then not variadic', () => {\n    // This might be used to describe coercion for comma separated values, and is not variadic.\n    const program = new commander.Command();\n    program.option('-c,--comma [value,...]');\n\n    expect(program.options[0].variadic).toBeFalsy();\n  });\n\n  test('when option has default array then specified value is used instead of default (not appended)', () => {\n    const program = new commander.Command();\n    program.option('-c,--comma [value...]', 'values', ['default']);\n    program.parse(['--comma', 'CCC'], { from: 'user' });\n\n    expect(program.opts().comma).toEqual(['CCC']);\n  });\n});\n"
  },
  {
    "path": "tests/options.version.test.js",
    "content": "const commander = require('../');\n\n// Test .version. Using exitOverride to check behaviour (instead of mocking process.exit).\n\ndescribe('.version', () => {\n  test('when no .version and specify --version then unknown option error', () => {\n    const errorMessage = 'unknownOption';\n    const program = new commander.Command();\n    // Override unknownOption as convenient way to check fails as expected.\n    jest.spyOn(program, 'unknownOption').mockImplementation(() => {\n      throw new Error(errorMessage);\n    });\n\n    expect(() => {\n      program.parse(['node', 'test', '--version']);\n    }).toThrow(errorMessage);\n  });\n\n  test('when no .version then helpInformation does not include version', () => {\n    const program = new commander.Command();\n\n    const helpInformation = program.helpInformation();\n\n    expect(helpInformation.includes('Usage')).toBe(true);\n    expect(helpInformation.includes('version')).toBe(false);\n  });\n\n  test('when specify default short flag then display version', () => {\n    const myVersion = '1.2.3';\n    const writeMock = jest.fn();\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeOut: writeMock })\n      .version(myVersion);\n\n    expect(() => {\n      program.parse(['node', 'test', '-V']);\n    }).toThrow(myVersion);\n    expect(writeMock).toHaveBeenCalledWith(`${myVersion}\\n`);\n  });\n\n  test('when specify default long flag then display version', () => {\n    const myVersion = '1.2.3';\n    const writeMock = jest.fn();\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeOut: writeMock })\n      .version(myVersion);\n\n    expect(() => {\n      program.parse(['node', 'test', '--version']);\n    }).toThrow(myVersion);\n    expect(writeMock).toHaveBeenCalledWith(`${myVersion}\\n`);\n  });\n\n  test('when default .version then helpInformation includes default version help', () => {\n    const myVersion = '1.2.3';\n    const program = new commander.Command();\n    program.version(myVersion);\n\n    const helpInformation = program.helpInformation();\n\n    expect(helpInformation.includes('-V, --version')).toBe(true);\n    expect(helpInformation.includes('output the version number')).toBe(true);\n  });\n\n  test('when specify custom short flag then display version', () => {\n    const myVersion = '1.2.3';\n    const writeMock = jest.fn();\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeOut: writeMock })\n      .version(myVersion, '-r, --revision');\n\n    expect(() => {\n      program.parse(['node', 'test', '-r']);\n    }).toThrow(myVersion);\n    expect(writeMock).toHaveBeenCalledWith(`${myVersion}\\n`);\n  });\n\n  test('when specify just custom short flag then display version', () => {\n    const myVersion = '1.2.3';\n    const writeMock = jest.fn();\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeOut: writeMock })\n      .version(myVersion, '-r');\n\n    expect(() => {\n      program.parse(['node', 'test', '-r']);\n    }).toThrow(myVersion);\n    expect(writeMock).toHaveBeenCalledWith(`${myVersion}\\n`);\n  });\n\n  test('when specify custom long flag then display version', () => {\n    const myVersion = '1.2.3';\n    const writeMock = jest.fn();\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeOut: writeMock })\n      .version(myVersion, '-r, --revision');\n\n    expect(() => {\n      program.parse(['node', 'test', '--revision']);\n    }).toThrow(myVersion);\n    expect(writeMock).toHaveBeenCalledWith(`${myVersion}\\n`);\n  });\n\n  test('when specify just custom long flag then display version', () => {\n    const myVersion = '1.2.3';\n    const writeMock = jest.fn();\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeOut: writeMock })\n      .version(myVersion, '--revision');\n\n    expect(() => {\n      program.parse(['node', 'test', '--revision']);\n    }).toThrow(myVersion);\n    expect(writeMock).toHaveBeenCalledWith(`${myVersion}\\n`);\n  });\n\n  test('when custom .version then helpInformation includes custom version help', () => {\n    const myVersion = '1.2.3';\n    const myVersionFlags = '-r, --revision';\n    const myVersionDescription = 'custom description';\n    const program = new commander.Command();\n    program.version(myVersion, myVersionFlags, myVersionDescription);\n\n    const helpInformation = program.helpInformation();\n\n    expect(helpInformation.includes(myVersionFlags)).toBe(true);\n    expect(helpInformation.includes(myVersionDescription)).toBe(true);\n  });\n\n  test('when have .version+version and specify version then command called', () => {\n    const actionMock = jest.fn();\n    const program = new commander.Command();\n    program.version('1.2.3').command('version').action(actionMock);\n\n    program.parse(['node', 'test', 'version']);\n\n    expect(actionMock).toHaveBeenCalled();\n  });\n\n  test('when have .version+version and specify --version then version displayed', () => {\n    const myVersion = '1.2.3';\n    const writeMock = jest.fn();\n    const program = new commander.Command();\n    program\n      .exitOverride()\n      .configureOutput({ writeOut: writeMock })\n      .version(myVersion)\n      .command('version')\n      .action(() => {});\n\n    expect(() => {\n      program.parse(['node', 'test', '--version']);\n    }).toThrow(myVersion);\n    expect(writeMock).toHaveBeenCalledWith(`${myVersion}\\n`);\n  });\n\n  test('when specify version then can get version', () => {\n    const myVersion = '1.2.3';\n    const program = new commander.Command();\n    program.version(myVersion);\n    expect(program.version()).toEqual(myVersion);\n  });\n});\n"
  },
  {
    "path": "tests/program.test.js",
    "content": "const {\n  program,\n  Command,\n  Option,\n  Argument,\n  Help,\n  CommanderError,\n  InvalidArgumentError,\n  InvalidOptionArgumentError,\n  createCommand,\n  createOption,\n  createArgument,\n} = require('../index.js');\n\n// Do some testing of the default export(s).\n// Similar tests to ts-imports.test.ts and esm-imports-test.js.\n\n/* eslint jest/expect-expect: [\"error\", { \"assertFunctionNames\": [\"expect\", \"checkClass\"] }] */\n\nfunction checkClass(obj, name) {\n  expect(typeof obj).toEqual('object');\n  expect(obj.constructor.name).toEqual(name);\n}\n\ntest('program', () => {\n  checkClass(program, 'Command');\n});\n\ntest('Command', () => {\n  checkClass(new Command('name'), 'Command');\n});\n\ntest('Option', () => {\n  checkClass(new Option('-e, --example', 'description'), 'Option');\n});\n\ntest('Argument', () => {\n  checkClass(new Argument('<foo>', 'description'), 'Argument');\n});\n\ntest('Help', () => {\n  checkClass(new Help(), 'Help');\n});\n\ntest('CommanderError', () => {\n  checkClass(new CommanderError(1, 'code', 'failed'), 'CommanderError');\n});\n\ntest('InvalidArgumentError', () => {\n  checkClass(new InvalidArgumentError('failed'), 'InvalidArgumentError');\n});\n\ntest('InvalidOptionArgumentError', () => {\n  // Deprecated\n  checkClass(new InvalidOptionArgumentError('failed'), 'InvalidArgumentError');\n});\n\ntest('createCommand', () => {\n  checkClass(createCommand('foo'), 'Command');\n});\n\ntest('createOption', () => {\n  checkClass(createOption('-e, --example', 'description'), 'Option');\n});\n\ntest('createArgument', () => {\n  checkClass(createArgument('<foo>', 'description'), 'Argument');\n});\n"
  },
  {
    "path": "tests/ts-imports.test.ts",
    "content": "import {\n  program,\n  Command,\n  Option,\n  CommanderError,\n  InvalidArgumentError,\n  InvalidOptionArgumentError,\n  Help,\n  createCommand,\n} from '../';\n\n// Do some simple checks that expected imports are available at runtime.\n// Similar tests to esm-imports-test.js\n\n/* eslint-disable jest/expect-expect */\n\nfunction checkClass(obj: object, name: string): void {\n  expect(typeof obj).toEqual('object');\n  expect(obj.constructor.name).toEqual(name);\n}\n\ntest('program', () => {\n  checkClass(program, 'Command');\n});\n\ntest('createCommand', () => {\n  checkClass(createCommand(), 'Command');\n});\n\ntest('Command', () => {\n  checkClass(new Command('name'), 'Command');\n});\n\ntest('Option', () => {\n  checkClass(new Option('-e, --example', 'description'), 'Option');\n});\n\ntest('CommanderError', () => {\n  checkClass(new CommanderError(1, 'code', 'failed'), 'CommanderError');\n});\n\ntest('InvalidArgumentError', () => {\n  checkClass(new InvalidArgumentError('failed'), 'InvalidArgumentError');\n});\n\ntest('InvalidOptionArgumentError', () => {\n  // Deprecated\n  checkClass(new InvalidOptionArgumentError('failed'), 'InvalidArgumentError');\n});\n\ntest('Help', () => {\n  checkClass(new Help(), 'Help');\n});\n"
  },
  {
    "path": "tests/useColor.test.js",
    "content": "const { useColor } = require('../lib/command.js');\n\ndescribe('internal useColor environment variable support', () => {\n  let holdNoColor = process.env.NO_COLOR;\n  let holdForceColor = process.env.FORCE_COLOR;\n  let holdCliColorForce = process.env.CLICOLOR_FORCE;\n\n  beforeEach(() => {\n    delete process.env.NO_COLOR;\n    delete process.env.FORCE_COLOR;\n    delete process.env.CLICOLOR_FORCE;\n  });\n\n  afterAll(() => {\n    if (holdNoColor === undefined) delete process.env.NO_COLOR;\n    else process.env.NO_COLOR = holdNoColor;\n\n    if (holdForceColor === undefined) delete process.env.FORCE_COLOR;\n    else process.env.FORCE_COLOR = holdForceColor;\n\n    if (holdCliColorForce === undefined) delete process.env.CLICOLOR_FORCE;\n    else process.env.CLICOLOR_FORCE = holdCliColorForce;\n  });\n\n  test('when no ENV defined then returns undefined', () => {\n    expect(useColor()).toBeUndefined();\n  });\n\n  // https://no-color.org\n  //\n  //    Command-line software which adds ANSI color to its output by default should check for a NO_COLOR environment variable that,\n  //    when present and not an empty string (regardless of its value), prevents the addition of ANSI color.\n\n  test('when NO_COLOR defined then returns false', () => {\n    process.env.NO_COLOR = 'non-empty';\n    expect(useColor()).toBe(false);\n  });\n\n  test('when NO_COLOR empty then returns undefined', () => {\n    process.env.NO_COLOR = '';\n    expect(useColor()).toBe(undefined);\n  });\n\n  // https://bixense.com/clicolors/\n\n  test('when CLICOLOR_FORCE defined then returns true', () => {\n    process.env.CLICOLOR_FORCE = '1';\n    expect(useColor()).toBe(true);\n  });\n\n  test('when CLICOLOR_FORCE empty then returns true', () => {\n    // Follow original Apple usage and test for existence, don't ignore empty value.\n    process.env.CLICOLOR_FORCE = '';\n    expect(useColor()).toBe(true);\n  });\n\n  test('when CLICOLOR_FORCE and NO_COLOR defined then returns false', () => {\n    // NO_COLOR trumps CLICOLOR_FORCE\n    process.env.NO_COLOR = '1';\n    process.env.CLICOLOR_FORCE = '1';\n    expect(useColor()).toBe(false);\n  });\n\n  // chalk: https://github.com/chalk/supports-color/blob/c214314a14bcb174b12b3014b2b0a8de375029ae/index.js#L33\n  // node: https://github.com/nodejs/node/blob/0a00217a5f67ef4a22384cfc80eb6dd9a917fdc1/lib/internal/tty.js#L109\n  // (https://force-color.org recent web page from 2023, does not match major javascript implementations)\n  //\n  // Chalk ignores anything except for 0,1,2,3,4,true,false values.\n  // Node somewhat follows Chalk with 0,1,2,3,true, but treats empty as true and unexpected values as false.\n  // Test the expected Chalk values (which do produce same result in node).\n\n  test.each([\n    ['true', true],\n    ['false', false],\n    ['0', false],\n    ['1', true],\n    ['2', true],\n    ['3', true],\n  ])('when FORCE_COLOR=%s then returns %s', (value, result) => {\n    process.env.FORCE_COLOR = value;\n    expect(useColor()).toBe(result);\n  });\n});\n"
  },
  {
    "path": "tsconfig.js.json",
    "content": "{\n  /* \n    Simple override including just JavaScript files.\n    Used by npm run-script typecheck:js\n  */\n  /* Visit https://aka.ms/tsconfig to read more about tsconfig configuration. */\n  \"extends\": \"./tsconfig.json\",\n  \"include\": [\n    /* All JavaScript targets from tsconfig.json include. */\n    \"*.js\",\n    \".prettierrc.js\" /* missed by above pattern */,\n    \"*.mjs\",\n    \"lib/**/*.js\",\n  ],\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  /*\n    TypeScript is being used to do type checking across both JavaScript and TypeScript files.\n    In particular, this picks up some problems in the JSDoc in the JavaScript files, and validates the code\n    is consistent with the JSDoc.\n     \n    The settings here are used by VSCode.\n    \n    See also tsconfig.js.json and tsconfig.ts.json.\n  */\n  /* Visit https://aka.ms/tsconfig to read more about tsconfig configuration. */\n  \"compilerOptions\": {\n    \"lib\": [\"es2021\"],\n    \"module\": \"node16\",\n    \"target\": \"es2021\",\n\n    \"allowJs\": true,\n    \"checkJs\": true,\n\n    /* Strict by default, but dial it down to reduce churn in our JavaScript code. */\n    \"strict\": true,\n    \"noImplicitAny\": false,\n    \"strictNullChecks\": false,\n    \"useUnknownInCatchVariables\": false,\n\n    \"types\": [\"node\", \"jest\"],\n    \"noEmit\": true /* just type checking and not emitting transpiled files */,\n    \"skipLibCheck\": false /* we want to check our hand crafted definitions */,\n    \"forceConsistentCasingInFileNames\": true,\n    \"esModuleInterop\": true /* common TypeScript config */,\n    \"resolveJsonModule\": true /* needed for globals in node_modules?! */,\n  },\n  \"include\": [\n    /* JavaScript. Should match includes in tsconfig.js.json. */\n    \"*.js\",\n    \".prettierrc.js\" /* missed by above pattern */,\n    \"*.mjs\",\n    \"lib/**/*.js\",\n    /* TypeScript. Should match includes in tsconfig.ts.json. */\n    \"**/*.ts\",\n    \"**/*.mts\",\n  ],\n  \"exclude\": [\"node_modules\"],\n}\n"
  },
  {
    "path": "tsconfig.ts.json",
    "content": "{\n  /* \n    Override to include just TypeScript files and use stricter settings than we do with JavaScript.\n    Used by:\n    - npm run-script typecheck:ts\n  */\n  /* Visit https://aka.ms/tsconfig to read more about tsconfig configuration. */\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    /* Full strict is fine for the TypeScript files, so turn back on the checks we turned off for mixed-use. */\n    \"noImplicitAny\": true,\n    \"strictNullChecks\": true,\n    \"useUnknownInCatchVariables\": true,\n  },\n  \"include\": [\n    /* All TypeScript targets from tsconfig.json include. */\n    \"**/*.ts\",\n    \"**/*.mts\",\n  ],\n}\n"
  },
  {
    "path": "typings/esm.d.mts",
    "content": "// Just reexport the types from cjs\n// This is a bit indirect. There is not an index.js, but TypeScript will look for index.d.ts for types.\nexport * from './index.js';\n"
  },
  {
    "path": "typings/index.d.ts",
    "content": "// Type definitions for commander\n// Original definitions by: Alan Agius <https://github.com/alan-agius4>, Marcelo Dezem <https://github.com/mdezem>, vvakame <https://github.com/vvakame>, Jules Randolph <https://github.com/sveinburne>\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n// This is a trick to encourage editor to suggest the known literals while still\n// allowing any BaseType value.\n// References:\n// - https://github.com/microsoft/TypeScript/issues/29729\n// - https://github.com/sindresorhus/type-fest/blob/main/source/literal-union.d.ts\n// - https://github.com/sindresorhus/type-fest/blob/main/source/primitive.d.ts\ntype LiteralUnion<LiteralType, BaseType extends string | number> =\n  | LiteralType\n  | (BaseType & Record<never, never>);\n\nexport class CommanderError extends Error {\n  code: string;\n  exitCode: number;\n  message: string;\n  nestedError?: string;\n\n  /**\n   * Constructs the CommanderError class\n   * @param exitCode - suggested exit code which could be used with process.exit\n   * @param code - an id string representing the error\n   * @param message - human-readable description of the error\n   */\n  constructor(exitCode: number, code: string, message: string);\n}\n\nexport class InvalidArgumentError extends CommanderError {\n  /**\n   * Constructs the InvalidArgumentError class\n   * @param message - explanation of why argument is invalid\n   */\n  constructor(message: string);\n}\nexport { InvalidArgumentError as InvalidOptionArgumentError }; // deprecated old name\n\nexport interface ErrorOptions {\n  // optional parameter for error()\n  /** an id string representing the error */\n  code?: string;\n  /** suggested exit code which could be used with process.exit */\n  exitCode?: number;\n}\n\nexport class Argument {\n  description: string;\n  required: boolean;\n  variadic: boolean;\n  defaultValue?: any;\n  defaultValueDescription?: string;\n  parseArg?: <T>(value: string, previous: T) => T;\n  argChoices?: string[];\n\n  /**\n   * Initialize a new command argument with the given name and description.\n   * The default is that the argument is required, and you can explicitly\n   * indicate this with <> around the name. Put [] around the name for an optional argument.\n   */\n  constructor(arg: string, description?: string);\n\n  /**\n   * Return argument name.\n   */\n  name(): string;\n\n  /**\n   * Set the default value, and optionally supply the description to be displayed in the help.\n   */\n  default(value: unknown, description?: string): this;\n\n  /**\n   * Set the custom handler for processing CLI command arguments into argument values.\n   */\n  argParser<T>(fn: (value: string, previous: T) => T): this;\n\n  /**\n   * Only allow argument value to be one of choices.\n   */\n  choices(values: readonly string[]): this;\n\n  /**\n   * Make argument required.\n   */\n  argRequired(): this;\n\n  /**\n   * Make argument optional.\n   */\n  argOptional(): this;\n}\n\nexport class Option {\n  flags: string;\n  description: string;\n\n  required: boolean; // A value must be supplied when the option is specified.\n  optional: boolean; // A value is optional when the option is specified.\n  variadic: boolean;\n  mandatory: boolean; // The option must have a value after parsing, which usually means it must be specified on command line.\n  short?: string;\n  long?: string;\n  negate: boolean;\n  defaultValue?: any;\n  defaultValueDescription?: string;\n  presetArg?: unknown;\n  envVar?: string;\n  parseArg?: <T>(value: string, previous: T) => T;\n  hidden: boolean;\n  argChoices?: string[];\n  helpGroupHeading?: string;\n\n  constructor(flags: string, description?: string);\n\n  /**\n   * Set the default value, and optionally supply the description to be displayed in the help.\n   */\n  default(value: unknown, description?: string): this;\n\n  /**\n   * Preset to use when option used without option-argument, especially optional but also boolean and negated.\n   * The custom processing (parseArg) is called.\n   *\n   * @example\n   * ```ts\n   * new Option('--color').default('GREYSCALE').preset('RGB');\n   * new Option('--donate [amount]').preset('20').argParser(parseFloat);\n   * ```\n   */\n  preset(arg: unknown): this;\n\n  /**\n   * Add option name(s) that conflict with this option.\n   * An error will be displayed if conflicting options are found during parsing.\n   *\n   * @example\n   * ```ts\n   * new Option('--rgb').conflicts('cmyk');\n   * new Option('--js').conflicts(['ts', 'jsx']);\n   * ```\n   */\n  conflicts(names: string | string[]): this;\n\n  /**\n   * Specify implied option values for when this option is set and the implied options are not.\n   *\n   * The custom processing (parseArg) is not called on the implied values.\n   *\n   * @example\n   * program\n   *   .addOption(new Option('--log', 'write logging information to file'))\n   *   .addOption(new Option('--trace', 'log extra details').implies({ log: 'trace.txt' }));\n   */\n  implies(optionValues: OptionValues): this;\n\n  /**\n   * Set environment variable to check for option value.\n   *\n   * An environment variables is only used if when processed the current option value is\n   * undefined, or the source of the current value is 'default' or 'config' or 'env'.\n   */\n  env(name: string): this;\n\n  /**\n   * Set the custom handler for processing CLI option arguments into option values.\n   */\n  argParser<T>(fn: (value: string, previous: T) => T): this;\n\n  /**\n   * Whether the option is mandatory and must have a value after parsing.\n   */\n  makeOptionMandatory(mandatory?: boolean): this;\n\n  /**\n   * Hide option in help.\n   */\n  hideHelp(hide?: boolean): this;\n\n  /**\n   * Only allow option value to be one of choices.\n   */\n  choices(values: readonly string[]): this;\n\n  /**\n   * Return option name.\n   */\n  name(): string;\n\n  /**\n   * Return option name, in a camelcase format that can be used\n   * as an object attribute key.\n   */\n  attributeName(): string;\n\n  /**\n   * Set the help group heading.\n   */\n  helpGroup(heading: string): this;\n\n  /**\n   * Return whether a boolean option.\n   *\n   * Options are one of boolean, negated, required argument, or optional argument.\n   */\n  isBoolean(): boolean;\n}\n\nexport class Help {\n  /** output helpWidth, long lines are wrapped to fit */\n  helpWidth?: number;\n  minWidthToWrap: number;\n  sortSubcommands: boolean;\n  sortOptions: boolean;\n  showGlobalOptions: boolean;\n\n  constructor();\n\n  /*\n   * prepareContext is called by Commander after applying overrides from `Command.configureHelp()`\n   * and just before calling `formatHelp()`.\n   *\n   * Commander just uses the helpWidth and the others are provided for subclasses.\n   */\n  prepareContext(contextOptions: {\n    error?: boolean;\n    helpWidth?: number;\n    outputHasColors?: boolean;\n  }): void;\n\n  /** Get the command term to show in the list of subcommands. */\n  subcommandTerm(cmd: Command): string;\n  /** Get the command summary to show in the list of subcommands. */\n  subcommandDescription(cmd: Command): string;\n  /** Get the option term to show in the list of options. */\n  optionTerm(option: Option): string;\n  /** Get the option description to show in the list of options. */\n  optionDescription(option: Option): string;\n  /** Get the argument term to show in the list of arguments. */\n  argumentTerm(argument: Argument): string;\n  /** Get the argument description to show in the list of arguments. */\n  argumentDescription(argument: Argument): string;\n\n  /** Get the command usage to be displayed at the top of the built-in help. */\n  commandUsage(cmd: Command): string;\n  /** Get the description for the command. */\n  commandDescription(cmd: Command): string;\n\n  /** Get an array of the visible subcommands. Includes a placeholder for the implicit help command, if there is one. */\n  visibleCommands(cmd: Command): Command[];\n  /** Get an array of the visible options. Includes a placeholder for the implicit help option, if there is one. */\n  visibleOptions(cmd: Command): Option[];\n  /** Get an array of the visible global options. (Not including help.) */\n  visibleGlobalOptions(cmd: Command): Option[];\n  /** Get an array of the arguments which have descriptions. */\n  visibleArguments(cmd: Command): Argument[];\n\n  /** Get the longest command term length. */\n  longestSubcommandTermLength(cmd: Command, helper: Help): number;\n  /** Get the longest option term length. */\n  longestOptionTermLength(cmd: Command, helper: Help): number;\n  /** Get the longest global option term length. */\n  longestGlobalOptionTermLength(cmd: Command, helper: Help): number;\n  /** Get the longest argument term length. */\n  longestArgumentTermLength(cmd: Command, helper: Help): number;\n\n  /** Return display width of string, ignoring ANSI escape sequences. Used in padding and wrapping calculations. */\n  displayWidth(str: string): number;\n\n  /** Style the titles. Called with 'Usage:', 'Options:', etc. */\n  styleTitle(title: string): string;\n\n  /** Usage: <str> */\n  styleUsage(str: string): string;\n  /** Style for command name in usage string.  */\n  styleCommandText(str: string): string;\n\n  styleCommandDescription(str: string): string;\n  styleOptionDescription(str: string): string;\n  styleSubcommandDescription(str: string): string;\n  styleArgumentDescription(str: string): string;\n  /** Base style used by descriptions. */\n  styleDescriptionText(str: string): string;\n\n  styleOptionTerm(str: string): string;\n  styleSubcommandTerm(str: string): string;\n  styleArgumentTerm(str: string): string;\n\n  /** Base style used in terms and usage for options. */\n  styleOptionText(str: string): string;\n  /** Base style used in terms and usage for subcommands. */\n  styleSubcommandText(str: string): string;\n  /** Base style used in terms and usage for arguments. */\n  styleArgumentText(str: string): string;\n\n  /** Calculate the pad width from the maximum term length. */\n  padWidth(cmd: Command, helper: Help): number;\n\n  /**\n   * Wrap a string at whitespace, preserving existing line breaks.\n   * Wrapping is skipped if the width is less than `minWidthToWrap`.\n   */\n  boxWrap(str: string, width: number): string;\n\n  /** Detect manually wrapped and indented strings by checking for line break followed by whitespace. */\n  preformatted(str: string): boolean;\n\n  /**\n   * Format the \"item\", which consists of a term and description. Pad the term and wrap the description, indenting the following lines.\n   *\n   * So \"TTT\", 5, \"DDD DDDD DD DDD\" might be formatted for this.helpWidth=17 like so:\n   *   TTT    DDD DDDD\n   *          DD DDD\n   */\n  formatItem(\n    term: string,\n    termWidth: number,\n    description: string,\n    helper: Help,\n  ): string;\n\n  /**\n   * Format a list of items, given a heading and an array of formatted items.\n   */\n  formatItemList(heading: string, items: string[], helper: Help): string[];\n\n  /**\n   * Group items by their help group heading.\n   */\n  groupItems<T extends Command | Option>(\n    unsortedItems: T[],\n    visibleItems: T[],\n    getGroup: (item: T) => string,\n  ): Map<string, T[]>;\n\n  /** Generate the built-in help text. */\n  formatHelp(cmd: Command, helper: Help): string;\n}\nexport type HelpConfiguration = Partial<Help>;\n\nexport interface ParseOptions {\n  from: 'node' | 'electron' | 'user';\n}\nexport interface HelpContext {\n  // optional parameter for .help() and .outputHelp()\n  error: boolean;\n}\nexport interface AddHelpTextContext {\n  // passed to text function used with .addHelpText()\n  error: boolean;\n  command: Command;\n}\nexport interface OutputConfiguration {\n  writeOut?(str: string): void;\n  writeErr?(str: string): void;\n  outputError?(str: string, write: (str: string) => void): void;\n\n  getOutHelpWidth?(): number;\n  getErrHelpWidth?(): number;\n\n  getOutHasColors?(): boolean;\n  getErrHasColors?(): boolean;\n  stripColor?(str: string): string;\n}\n\nexport type AddHelpTextPosition = 'beforeAll' | 'before' | 'after' | 'afterAll';\nexport type HookEvent = 'preSubcommand' | 'preAction' | 'postAction';\n// The source is a string so author can define their own too.\nexport type OptionValueSource =\n  | LiteralUnion<'default' | 'config' | 'env' | 'cli' | 'implied', string>\n  | undefined;\n\nexport type OptionValues = Record<string, any>;\n\nexport class Command {\n  args: string[];\n  processedArgs: any[];\n  readonly commands: readonly Command[];\n  readonly options: readonly Option[];\n  readonly registeredArguments: readonly Argument[];\n  parent: Command | null;\n\n  constructor(name?: string);\n\n  /**\n   * Set the program version to `str`.\n   *\n   * This method auto-registers the \"-V, --version\" flag\n   * which will print the version number when passed.\n   *\n   * You can optionally supply the  flags and description to override the defaults.\n   */\n  version(str: string, flags?: string, description?: string): this;\n  /**\n   * Get the program version.\n   */\n  version(): string | undefined;\n\n  /**\n   * Define a command, implemented using an action handler.\n   *\n   * @remarks\n   * The command description is supplied using `.description`, not as a parameter to `.command`.\n   *\n   * @example\n   * ```ts\n   * program\n   *   .command('clone <source> [destination]')\n   *   .description('clone a repository into a newly created directory')\n   *   .action((source, destination) => {\n   *     console.log('clone command called');\n   *   });\n   * ```\n   *\n   * @param nameAndArgs - command name and arguments, args are  `<required>` or `[optional]` and last may also be `variadic...`\n   * @param opts - configuration options\n   * @returns new command\n   */\n  command(\n    nameAndArgs: string,\n    opts?: CommandOptions,\n  ): ReturnType<this['createCommand']>;\n  /**\n   * Define a command, implemented in a separate executable file.\n   *\n   * @remarks\n   * The command description is supplied as the second parameter to `.command`.\n   *\n   * @example\n   * ```ts\n   *  program\n   *    .command('start <service>', 'start named service')\n   *    .command('stop [service]', 'stop named service, or all if no name supplied');\n   * ```\n   *\n   * @param nameAndArgs - command name and arguments, args are  `<required>` or `[optional]` and last may also be `variadic...`\n   * @param description - description of executable command\n   * @param opts - configuration options\n   * @returns `this` command for chaining\n   */\n  command(\n    nameAndArgs: string,\n    description: string,\n    opts?: ExecutableCommandOptions,\n  ): this;\n\n  /**\n   * Factory routine to create a new unattached command.\n   *\n   * See .command() for creating an attached subcommand, which uses this routine to\n   * create the command. You can override createCommand to customise subcommands.\n   */\n  createCommand(name?: string): Command;\n\n  /**\n   * Add a prepared subcommand.\n   *\n   * See .command() for creating an attached subcommand which inherits settings from its parent.\n   *\n   * @returns `this` command for chaining\n   */\n  addCommand(cmd: Command, opts?: CommandOptions): this;\n\n  /**\n   * Factory routine to create a new unattached argument.\n   *\n   * See .argument() for creating an attached argument, which uses this routine to\n   * create the argument. You can override createArgument to return a custom argument.\n   */\n  createArgument(name: string, description?: string): Argument;\n\n  /**\n   * Define argument syntax for command.\n   *\n   * The default is that the argument is required, and you can explicitly\n   * indicate this with <> around the name. Put [] around the name for an optional argument.\n   *\n   * @example\n   * ```\n   * program.argument('<input-file>');\n   * program.argument('[output-file]');\n   * ```\n   *\n   * @returns `this` command for chaining\n   */\n  argument<T>(\n    flags: string,\n    description: string,\n    parseArg: (value: string, previous: T) => T,\n    defaultValue?: T,\n  ): this;\n  argument(name: string, description?: string, defaultValue?: unknown): this;\n\n  /**\n   * Define argument syntax for command, adding a prepared argument.\n   *\n   * @returns `this` command for chaining\n   */\n  addArgument(arg: Argument): this;\n\n  /**\n   * Define argument syntax for command, adding multiple at once (without descriptions).\n   *\n   * See also .argument().\n   *\n   * @example\n   * ```\n   * program.arguments('<cmd> [env]');\n   * ```\n   *\n   * @returns `this` command for chaining\n   */\n  arguments(names: string): this;\n\n  /**\n   * Customise or override default help command. By default a help command is automatically added if your command has subcommands.\n   *\n   * @example\n   * ```ts\n   * program.helpCommand('help [cmd]');\n   * program.helpCommand('help [cmd]', 'show help');\n   * program.helpCommand(false); // suppress default help command\n   * program.helpCommand(true); // add help command even if no subcommands\n   * ```\n   */\n  helpCommand(nameAndArgs: string, description?: string): this;\n  helpCommand(enable: boolean): this;\n\n  /**\n   * Add prepared custom help command.\n   */\n  addHelpCommand(cmd: Command): this;\n  /** @deprecated since v12, instead use helpCommand */\n  addHelpCommand(nameAndArgs: string, description?: string): this;\n  /** @deprecated since v12, instead use helpCommand */\n  addHelpCommand(enable?: boolean): this;\n\n  /**\n   * Add hook for life cycle event.\n   */\n  hook(\n    event: HookEvent,\n    listener: (\n      thisCommand: Command,\n      actionCommand: Command,\n    ) => void | Promise<void>,\n  ): this;\n\n  /**\n   * Register callback to use as replacement for calling process.exit.\n   */\n  exitOverride(callback?: (err: CommanderError) => never | void): this;\n\n  /**\n   * Display error message and exit (or call exitOverride).\n   */\n  error(message: string, errorOptions?: ErrorOptions): never;\n\n  /**\n   * You can customise the help with a subclass of Help by overriding createHelp,\n   * or by overriding Help properties using configureHelp().\n   */\n  createHelp(): Help;\n\n  /**\n   * You can customise the help by overriding Help properties using configureHelp(),\n   * or with a subclass of Help by overriding createHelp().\n   */\n  configureHelp(configuration: HelpConfiguration): this;\n  /** Get configuration */\n  configureHelp(): HelpConfiguration;\n\n  /**\n   * The default output goes to stdout and stderr. You can customise this for special\n   * applications. You can also customise the display of errors by overriding outputError.\n   *\n   * The configuration properties are all functions:\n   * ```\n   * // functions to change where being written, stdout and stderr\n   * writeOut(str)\n   * writeErr(str)\n   * // matching functions to specify width for wrapping help\n   * getOutHelpWidth()\n   * getErrHelpWidth()\n   * // functions based on what is being written out\n   * outputError(str, write) // used for displaying errors, and not used for displaying help\n   * ```\n   */\n  configureOutput(configuration: OutputConfiguration): this;\n  /** Get configuration */\n  configureOutput(): OutputConfiguration;\n\n  /**\n   * Copy settings that are useful to have in common across root command and subcommands.\n   *\n   * (Used internally when adding a command using `.command()` so subcommands inherit parent settings.)\n   */\n  copyInheritedSettings(sourceCommand: Command): this;\n\n  /**\n   * Display the help or a custom message after an error occurs.\n   */\n  showHelpAfterError(displayHelp?: boolean | string): this;\n\n  /**\n   * Display suggestion of similar commands for unknown commands, or options for unknown options.\n   */\n  showSuggestionAfterError(displaySuggestion?: boolean): this;\n\n  /**\n   * Register callback `fn` for the command.\n   *\n   * @example\n   * ```\n   * program\n   *   .command('serve')\n   *   .description('start service')\n   *   .action(function() {\n   *     // do work here\n   *   });\n   * ```\n   *\n   * @returns `this` command for chaining\n   */\n  action(fn: (this: this, ...args: any[]) => void | Promise<void>): this;\n\n  /**\n   * Define option with `flags`, `description`, and optional argument parsing function or `defaultValue` or both.\n   *\n   * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space. A required\n   * option-argument is indicated by `<>` and an optional option-argument by `[]`.\n   *\n   * See the README for more details, and see also addOption() and requiredOption().\n   *\n   * @example\n   *\n   * ```js\n   * program\n   *     .option('-p, --pepper', 'add pepper')\n   *     .option('--pt, --pizza-type <TYPE>', 'type of pizza') // required option-argument\n   *     .option('-c, --cheese [CHEESE]', 'add extra cheese', 'mozzarella') // optional option-argument with default\n   *     .option('-t, --tip <VALUE>', 'add tip to purchase cost', parseFloat) // custom parse function\n   * ```\n   *\n   * @returns `this` command for chaining\n   */\n  option(\n    flags: string,\n    description?: string,\n    defaultValue?: string | boolean | string[],\n  ): this;\n  option<T>(\n    flags: string,\n    description: string,\n    parseArg: (value: string, previous: T) => T,\n    defaultValue?: T,\n  ): this;\n  /** @deprecated since v7, instead use choices or a custom function */\n  option(\n    flags: string,\n    description: string,\n    regexp: RegExp,\n    defaultValue?: string | boolean | string[],\n  ): this;\n\n  /**\n   * Define a required option, which must have a value after parsing. This usually means\n   * the option must be specified on the command line. (Otherwise the same as .option().)\n   *\n   * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space.\n   */\n  requiredOption(\n    flags: string,\n    description?: string,\n    defaultValue?: string | boolean | string[],\n  ): this;\n  requiredOption<T>(\n    flags: string,\n    description: string,\n    parseArg: (value: string, previous: T) => T,\n    defaultValue?: T,\n  ): this;\n  /** @deprecated since v7, instead use choices or a custom function */\n  requiredOption(\n    flags: string,\n    description: string,\n    regexp: RegExp,\n    defaultValue?: string | boolean | string[],\n  ): this;\n\n  /**\n   * Factory routine to create a new unattached option.\n   *\n   * See .option() for creating an attached option, which uses this routine to\n   * create the option. You can override createOption to return a custom option.\n   */\n\n  createOption(flags: string, description?: string): Option;\n\n  /**\n   * Add a prepared Option.\n   *\n   * See .option() and .requiredOption() for creating and attaching an option in a single call.\n   */\n  addOption(option: Option): this;\n\n  /**\n   * Whether to store option values as properties on command object,\n   * or store separately (specify false). In both cases the option values can be accessed using .opts().\n   *\n   * @returns `this` command for chaining\n   */\n  storeOptionsAsProperties<T extends OptionValues>(): this & T;\n  storeOptionsAsProperties<T extends OptionValues>(\n    storeAsProperties: true,\n  ): this & T;\n  storeOptionsAsProperties(storeAsProperties?: boolean): this;\n\n  /**\n   * Retrieve option value.\n   */\n  getOptionValue(key: string): any;\n\n  /**\n   * Store option value.\n   */\n  setOptionValue(key: string, value: unknown): this;\n\n  /**\n   * Store option value and where the value came from.\n   */\n  setOptionValueWithSource(\n    key: string,\n    value: unknown,\n    source: OptionValueSource,\n  ): this;\n\n  /**\n   * Get source of option value.\n   */\n  getOptionValueSource(key: string): OptionValueSource | undefined;\n\n  /**\n   * Get source of option value. See also .optsWithGlobals().\n   */\n  getOptionValueSourceWithGlobals(key: string): OptionValueSource | undefined;\n\n  /**\n   * Alter parsing of short flags with optional values.\n   *\n   * @example\n   * ```\n   * // for `.option('-f,--flag [value]'):\n   * .combineFlagAndOptionalValue(true)  // `-f80` is treated like `--flag=80`, this is the default behaviour\n   * .combineFlagAndOptionalValue(false) // `-fb` is treated like `-f -b`\n   * ```\n   *\n   * @returns `this` command for chaining\n   */\n  combineFlagAndOptionalValue(combine?: boolean): this;\n\n  /**\n   * Allow unknown options on the command line.\n   *\n   * @returns `this` command for chaining\n   */\n  allowUnknownOption(allowUnknown?: boolean): this;\n\n  /**\n   * Allow excess command-arguments on the command line. Pass false to make excess arguments an error.\n   *\n   * @returns `this` command for chaining\n   */\n  allowExcessArguments(allowExcess?: boolean): this;\n\n  /**\n   * Enable positional options. Positional means global options are specified before subcommands which lets\n   * subcommands reuse the same option names, and also enables subcommands to turn on passThroughOptions.\n   *\n   * The default behaviour is non-positional and global options may appear anywhere on the command line.\n   *\n   * @returns `this` command for chaining\n   */\n  enablePositionalOptions(positional?: boolean): this;\n\n  /**\n   * Pass through options that come after command-arguments rather than treat them as command-options,\n   * so actual command-options come before command-arguments. Turning this on for a subcommand requires\n   * positional options to have been enabled on the program (parent commands).\n   *\n   * The default behaviour is non-positional and options may appear before or after command-arguments.\n   *\n   * @returns `this` command for chaining\n   */\n  passThroughOptions(passThrough?: boolean): this;\n\n  /**\n   * Parse `argv`, setting options and invoking commands when defined.\n   *\n   * Use parseAsync instead of parse if any of your action handlers are async.\n   *\n   * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!\n   *\n   * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:\n   * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that\n   * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged\n   * - `'user'`: just user arguments\n   *\n   * @example\n   * ```\n   * program.parse(); // parse process.argv and auto-detect electron and special node flags\n   * program.parse(process.argv); // assume argv[0] is app and argv[1] is script\n   * program.parse(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]\n   * ```\n   *\n   * @returns `this` command for chaining\n   */\n  parse(argv?: readonly string[], parseOptions?: ParseOptions): this;\n\n  /**\n   * Parse `argv`, setting options and invoking commands when defined.\n   *\n   * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!\n   *\n   * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:\n   * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that\n   * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged\n   * - `'user'`: just user arguments\n   *\n   * @example\n   * ```\n   * await program.parseAsync(); // parse process.argv and auto-detect electron and special node flags\n   * await program.parseAsync(process.argv); // assume argv[0] is app and argv[1] is script\n   * await program.parseAsync(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]\n   * ```\n   *\n   * @returns Promise\n   */\n  parseAsync(\n    argv?: readonly string[],\n    parseOptions?: ParseOptions,\n  ): Promise<this>;\n\n  /**\n   * Called the first time parse is called to save state and allow a restore before subsequent calls to parse.\n   * Not usually called directly, but available for subclasses to save their custom state.\n   *\n   * This is called in a lazy way. Only commands used in parsing chain will have state saved.\n   */\n  saveStateBeforeParse(): void;\n\n  /**\n   * Restore state before parse for calls after the first.\n   * Not usually called directly, but available for subclasses to save their custom state.\n   *\n   * This is called in a lazy way. Only commands used in parsing chain will have state restored.\n   */\n  restoreStateBeforeParse(): void;\n\n  /**\n   * Parse options from `argv` removing known options,\n   * and return argv split into operands and unknown arguments.\n   *\n   * Side effects: modifies command by storing options. Does not reset state if called again.\n   *\n   *     argv => operands, unknown\n   *     --known kkk op => [op], []\n   *     op --known kkk => [op], []\n   *     sub --unknown uuu op => [sub], [--unknown uuu op]\n   *     sub -- --unknown uuu op => [sub --unknown uuu op], []\n   */\n  parseOptions(argv: string[]): ParseOptionsResult;\n\n  /**\n   * Return an object containing local option values as key-value pairs\n   */\n  opts<T extends OptionValues>(): T;\n\n  /**\n   * Return an object containing merged local and global option values as key-value pairs.\n   */\n  optsWithGlobals<T extends OptionValues>(): T;\n\n  /**\n   * Set the description.\n   *\n   * @returns `this` command for chaining\n   */\n\n  description(str: string): this;\n  /** @deprecated since v8, instead use .argument to add command argument with description */\n  description(str: string, argsDescription: Record<string, string>): this;\n  /**\n   * Get the description.\n   */\n  description(): string;\n\n  /**\n   * Set the summary. Used when listed as subcommand of parent.\n   *\n   * @returns `this` command for chaining\n   */\n\n  summary(str: string): this;\n  /**\n   * Get the summary.\n   */\n  summary(): string;\n\n  /**\n   * Set an alias for the command.\n   *\n   * You may call more than once to add multiple aliases. Only the first alias is shown in the auto-generated help.\n   *\n   * @returns `this` command for chaining\n   */\n  alias(alias: string): this;\n  /**\n   * Get alias for the command.\n   */\n  alias(): string;\n\n  /**\n   * Set aliases for the command.\n   *\n   * Only the first alias is shown in the auto-generated help.\n   *\n   * @returns `this` command for chaining\n   */\n  aliases(aliases: readonly string[]): this;\n  /**\n   * Get aliases for the command.\n   */\n  aliases(): string[];\n\n  /**\n   * Set the command usage.\n   *\n   * @returns `this` command for chaining\n   */\n  usage(str: string): this;\n  /**\n   * Get the command usage.\n   */\n  usage(): string;\n\n  /**\n   * Set the name of the command.\n   *\n   * @returns `this` command for chaining\n   */\n  name(str: string): this;\n  /**\n   * Get the name of the command.\n   */\n  name(): string;\n\n  /**\n   * Set the name of the command from script filename, such as process.argv[1],\n   * or require.main.filename, or __filename.\n   *\n   * (Used internally and public although not documented in README.)\n   *\n   * @example\n   * ```ts\n   * program.nameFromFilename(require.main.filename);\n   * ```\n   *\n   * @returns `this` command for chaining\n   */\n  nameFromFilename(filename: string): this;\n\n  /**\n   * Set the directory for searching for executable subcommands of this command.\n   *\n   * @example\n   * ```ts\n   * program.executableDir(__dirname);\n   * // or\n   * program.executableDir('subcommands');\n   * ```\n   *\n   * @returns `this` command for chaining\n   */\n  executableDir(path: string): this;\n  /**\n   * Get the executable search directory.\n   */\n  executableDir(): string | null;\n\n  /**\n   * Set the help group heading for this subcommand in parent command's help.\n   *\n   * @returns `this` command for chaining\n   */\n  helpGroup(heading: string): this;\n  /**\n   * Get the help group heading for this subcommand in parent command's help.\n   */\n  helpGroup(): string;\n\n  /**\n   * Set the default help group heading for subcommands added to this command.\n   * (This does not override a group set directly on the subcommand using .helpGroup().)\n   *\n   * @example\n   * program.commandsGroup('Development Commands:);\n   * program.command('watch')...\n   * program.command('lint')...\n   * ...\n   *\n   * @returns `this` command for chaining\n   */\n  commandsGroup(heading: string): this;\n  /**\n   * Get the default help group heading for subcommands added to this command.\n   */\n  commandsGroup(): string;\n\n  /**\n   * Set the default help group heading for options added to this command.\n   * (This does not override a group set directly on the option using .helpGroup().)\n   *\n   * @example\n   * program\n   *   .optionsGroup('Development Options:')\n   *   .option('-d, --debug', 'output extra debugging')\n   *   .option('-p, --profile', 'output profiling information')\n   *\n   * @returns `this` command for chaining\n   */\n  optionsGroup(heading: string): this;\n  /**\n   * Get the default help group heading for options added to this command.\n   */\n  optionsGroup(): string;\n\n  /**\n   * Output help information for this command.\n   *\n   * Outputs built-in help, and custom text added using `.addHelpText()`.\n   *\n   */\n  outputHelp(context?: HelpContext): void;\n  /** @deprecated since v7 */\n  outputHelp(cb: (str: string) => string): void;\n\n  /**\n   * Return command help documentation.\n   */\n  helpInformation(context?: HelpContext): string;\n\n  /**\n   * You can pass in flags and a description to override the help\n   * flags and help description for your command. Pass in false\n   * to disable the built-in help option.\n   */\n  helpOption(flags?: string | boolean, description?: string): this;\n\n  /**\n   * Supply your own option to use for the built-in help option.\n   * This is an alternative to using helpOption() to customise the flags and description etc.\n   */\n  addHelpOption(option: Option): this;\n\n  /**\n   * Output help information and exit.\n   *\n   * Outputs built-in help, and custom text added using `.addHelpText()`.\n   */\n  help(context?: HelpContext): never;\n  /** @deprecated since v7 */\n  help(cb: (str: string) => string): never;\n\n  /**\n   * Add additional text to be displayed with the built-in help.\n   *\n   * Position is 'before' or 'after' to affect just this command,\n   * and 'beforeAll' or 'afterAll' to affect this command and all its subcommands.\n   */\n  addHelpText(position: AddHelpTextPosition, text: string): this;\n  addHelpText(\n    position: AddHelpTextPosition,\n    text: (context: AddHelpTextContext) => string,\n  ): this;\n\n  /**\n   * Add a listener (callback) for when events occur. (Implemented using EventEmitter.)\n   */\n  on(event: string | symbol, listener: (...args: any[]) => void): this;\n}\n\nexport interface CommandOptions {\n  hidden?: boolean;\n  isDefault?: boolean;\n  /** @deprecated since v7, replaced by hidden */\n  noHelp?: boolean;\n}\nexport interface ExecutableCommandOptions extends CommandOptions {\n  executableFile?: string;\n}\n\nexport interface ParseOptionsResult {\n  operands: string[];\n  unknown: string[];\n}\n\nexport function createCommand(name?: string): Command;\nexport function createOption(flags: string, description?: string): Option;\nexport function createArgument(name: string, description?: string): Argument;\n\nexport const program: Command;\n"
  },
  {
    "path": "typings/index.test-d.ts",
    "content": "import * as commander from './index';\nimport { expectType } from 'tsd';\n\n// We are not just checking return types here, we are also implicitly checking that the expected syntax is allowed.\n\nconst program: commander.Command = new commander.Command();\n// @ts-expect-error Check that Command is strongly typed and does not allow arbitrary properties\n// eslint-disable-next-line @typescript-eslint/no-unused-expressions\nprogram.silly; // <-- Error, hurrah!\n\n// Check for exported global Command object\nexpectType<commander.Command>(commander.program);\n\n// Check export classes and functions exist\nexpectType<commander.Command>(new commander.Command());\nexpectType<commander.Command>(new commander.Command('name'));\nexpectType<commander.Option>(new commander.Option('-f'));\nexpectType<commander.CommanderError>(\n  new commander.CommanderError(1, 'code', 'message'),\n);\nexpectType<commander.InvalidArgumentError>(\n  new commander.InvalidArgumentError('message'),\n);\nexpectType<commander.InvalidArgumentError>(\n  new commander.InvalidOptionArgumentError('message'),\n);\nexpectType<commander.Command>(commander.createCommand());\nexpectType<commander.Option>(commander.createOption('--demo'));\nexpectType<commander.Argument>(commander.createArgument('<foo>'));\n\n// Command properties\nexpectType<string[]>(program.args);\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexpectType<any[]>(program.processedArgs);\nexpectType<readonly commander.Command[]>(program.commands);\nexpectType<readonly commander.Option[]>(program.options);\nexpectType<readonly commander.Argument[]>(program.registeredArguments);\nexpectType<commander.Command | null>(program.parent);\n\n// version\nexpectType<commander.Command>(program.version('1.2.3'));\nexpectType<commander.Command>(program.version('1.2.3', '-r,--revision'));\nexpectType<commander.Command>(\n  program.version('1.2.3', '-r,--revision', 'show revision information'),\n);\nexpectType<string | undefined>(program.version());\n\n// command (and CommandOptions)\nexpectType<commander.Command>(program.command('action'));\nexpectType<commander.Command>(\n  program.command('action', { isDefault: true, hidden: true, noHelp: true }),\n);\nexpectType<commander.Command>(program.command('exec', 'exec description'));\nexpectType<commander.Command>(\n  program.command('exec', 'exec description', {\n    isDefault: true,\n    hidden: true,\n    noHelp: true,\n    executableFile: 'foo',\n  }),\n);\n\n// addCommand\nexpectType<commander.Command>(program.addCommand(new commander.Command('abc')));\n\n// argument\nexpectType<commander.Command>(program.argument('<value>'));\nexpectType<commander.Command>(program.argument('<value>', 'description'));\nexpectType<commander.Command>(\n  program.argument('[value]', 'description', 'default'),\n);\nexpectType<commander.Command>(\n  program.argument('[value]', 'description', parseFloat),\n);\nexpectType<commander.Command>(\n  program.argument('[value]', 'description', parseFloat, 1.23),\n);\n\n// arguments\nexpectType<commander.Command>(program.arguments('<cmd> [env]'));\n\n// addHelpCommand\nexpectType<commander.Command>(\n  program.addHelpCommand(new commander.Command('assist')),\n);\n// Deprecated uses\nexpectType<commander.Command>(program.addHelpCommand());\nexpectType<commander.Command>(program.addHelpCommand(false));\nexpectType<commander.Command>(program.addHelpCommand(true));\nexpectType<commander.Command>(program.addHelpCommand('assist [cmd]'));\nexpectType<commander.Command>(\n  program.addHelpCommand('assist [file]', 'display help'),\n);\n\n// helpCommand\nexpectType<commander.Command>(program.helpCommand(false));\nexpectType<commander.Command>(program.helpCommand(true));\nexpectType<commander.Command>(program.helpCommand('assist [cmd]'));\nexpectType<commander.Command>(\n  program.helpCommand('assist [file]', 'display help'),\n);\n\n// exitOverride\nexpectType<commander.Command>(program.exitOverride());\nexpectType<commander.Command>(\n  program.exitOverride((err): never => {\n    return process.exit(err.exitCode);\n  }),\n);\nexpectType<commander.Command>(\n  program.exitOverride((err): void => {\n    if (err.code !== 'commander.executeSubCommandAsync') {\n      throw err;\n    } else {\n      // Async callback from spawn events, not useful to throw.\n    }\n  }),\n);\n\n// error\nexpectType<never>(program.error('Goodbye'));\nexpectType<never>(program.error('Goodbye', { code: 'my.error' }));\nexpectType<never>(program.error('Goodbye', { exitCode: 2 }));\nexpectType<never>(program.error('Goodbye', { code: 'my.error', exitCode: 2 }));\n\n// hook\nexpectType<commander.Command>(program.hook('preAction', () => {}));\nexpectType<commander.Command>(program.hook('postAction', () => {}));\nexpectType<commander.Command>(program.hook('preAction', async () => {}));\nexpectType<commander.Command>(\n  program.hook('preAction', (thisCommand, actionCommand) => {\n    // implicit parameter types\n    expectType<commander.Command>(thisCommand);\n    expectType<commander.Command>(actionCommand);\n  }),\n);\nexpectType<commander.Command>(program.hook('preSubcommand', () => {}));\nexpectType<commander.Command>(\n  program.hook('preSubcommand', (thisCommand, subcommand) => {\n    // implicit parameter types\n    expectType<commander.Command>(thisCommand);\n    expectType<commander.Command>(subcommand);\n  }),\n);\n\n// action\nexpectType<commander.Command>(program.action(() => {}));\nexpectType<commander.Command>(program.action(async () => {}));\nprogram.action(function () {\n  expectType<typeof program>(this);\n});\n\n// option\nexpectType<commander.Command>(program.option('-a,--alpha'));\nexpectType<commander.Command>(program.option('-p, --peppers', 'Add peppers'));\nexpectType<commander.Command>(\n  program.option('-s, --string [value]', 'default string', 'value'),\n);\nexpectType<commander.Command>(\n  program.option('-b, --boolean', 'default boolean', false),\n);\nexpectType<commander.Command>(\n  program.option('--drink <size', 'drink size', /small|medium|large/),\n); // deprecated\n\n// example coercion functions from README\n\nfunction myParseInt(value: string): number {\n  return parseInt(value);\n}\n\nfunction increaseVerbosity(dummyValue: string, previous: number): number {\n  return previous + 1;\n}\n\nfunction collect(value: string, previous: string[]): string[] {\n  return previous.concat([value]);\n}\n\nfunction commaSeparatedList(value: string): string[] {\n  return value.split(',');\n}\n\nexpectType<commander.Command>(\n  program.option('-f, --float <number>', 'float argument', parseFloat),\n);\nexpectType<commander.Command>(\n  program.option('-f, --float <number>', 'float argument', parseFloat, 3.2),\n);\nexpectType<commander.Command>(\n  program.option('-i, --integer <number>', 'integer argument', myParseInt),\n);\nexpectType<commander.Command>(\n  program.option('-i, --integer <number>', 'integer argument', myParseInt, 5),\n);\nexpectType<commander.Command>(\n  program.option(\n    '-v, --verbose',\n    'verbosity that can be increased',\n    increaseVerbosity,\n    0,\n  ),\n);\nexpectType<commander.Command>(\n  program.option('-c, --collect <value>', 'repeatable value', collect, []),\n);\nexpectType<commander.Command>(\n  program.option(\n    '-l, --list <items>',\n    'comma separated list',\n    commaSeparatedList,\n  ),\n);\n\n// requiredOption, same tests as option\nexpectType<commander.Command>(program.requiredOption('-a,--alpha'));\nexpectType<commander.Command>(\n  program.requiredOption('-p, --peppers', 'Add peppers'),\n);\nexpectType<commander.Command>(\n  program.requiredOption('-s, --string [value]', 'default string', 'value'),\n);\nexpectType<commander.Command>(\n  program.requiredOption('-b, --boolean', 'default boolean', false),\n);\nexpectType<commander.Command>(\n  program.requiredOption('--drink <size', 'drink size', /small|medium|large/),\n); // deprecated\n\nexpectType<commander.Command>(\n  program.requiredOption('-f, --float <number>', 'float argument', parseFloat),\n);\nexpectType<commander.Command>(\n  program.requiredOption(\n    '-f, --float <number>',\n    'float argument',\n    parseFloat,\n    3.2,\n  ),\n);\nexpectType<commander.Command>(\n  program.requiredOption(\n    '-i, --integer <number>',\n    'integer argument',\n    myParseInt,\n  ),\n);\nexpectType<commander.Command>(\n  program.requiredOption(\n    '-i, --integer <number>',\n    'integer argument',\n    myParseInt,\n    5,\n  ),\n);\nexpectType<commander.Command>(\n  program.requiredOption(\n    '-v, --verbose',\n    'verbosity that can be increased',\n    increaseVerbosity,\n    0,\n  ),\n);\nexpectType<commander.Command>(\n  program.requiredOption(\n    '-c, --collect <value>',\n    'repeatable value',\n    collect,\n    [],\n  ),\n);\nexpectType<commander.Command>(\n  program.requiredOption(\n    '-l, --list <items>',\n    'comma separated list',\n    commaSeparatedList,\n  ),\n);\n\n// createOption\nexpectType<commander.Option>(program.createOption('a, --alpha'));\nexpectType<commander.Option>(program.createOption('a, --alpha', 'description'));\n\n// addOption\nexpectType<commander.Command>(\n  program.addOption(new commander.Option('-s,--simple')),\n);\n\n// storeOptionsAsProperties\nexpectType<commander.Command & commander.OptionValues>(\n  program.storeOptionsAsProperties(),\n);\nexpectType<commander.Command & commander.OptionValues>(\n  program.storeOptionsAsProperties(true),\n);\nexpectType<commander.Command>(program.storeOptionsAsProperties(false));\n\n// getOptionValue\nvoid program.getOptionValue('example');\n\n// setOptionValue\nexpectType<commander.Command>(program.setOptionValue('example', 'value'));\nexpectType<commander.Command>(program.setOptionValue('example', true));\n\n// setOptionValueWithSource\nexpectType<commander.Command>(\n  program.setOptionValueWithSource('example', [], 'cli'),\n);\n\n// getOptionValueSource\nexpectType<commander.OptionValueSource | undefined>(\n  program.getOptionValueSource('example'),\n);\n\n// getOptionValueSourceWithGlobals\nexpectType<commander.OptionValueSource | undefined>(\n  program.getOptionValueSourceWithGlobals('example'),\n);\n\n// combineFlagAndOptionalValue\nexpectType<commander.Command>(program.combineFlagAndOptionalValue());\nexpectType<commander.Command>(program.combineFlagAndOptionalValue(false));\n\n// allowUnknownOption\nexpectType<commander.Command>(program.allowUnknownOption());\nexpectType<commander.Command>(program.allowUnknownOption(false));\n\n// allowExcessArguments\nexpectType<commander.Command>(program.allowExcessArguments());\nexpectType<commander.Command>(program.allowExcessArguments(false));\n\n// enablePositionalOptions\nexpectType<commander.Command>(program.enablePositionalOptions());\nexpectType<commander.Command>(program.enablePositionalOptions(false));\n\n// passThroughOptions\nexpectType<commander.Command>(program.passThroughOptions());\nexpectType<commander.Command>(program.passThroughOptions(false));\n\n// parse\nexpectType<commander.Command>(program.parse());\nexpectType<commander.Command>(program.parse(process.argv));\nexpectType<commander.Command>(\n  program.parse(['node', 'script.js'], { from: 'node' }),\n);\nexpectType<commander.Command>(\n  program.parse(['node', 'script.js'], { from: 'electron' }),\n);\nexpectType<commander.Command>(program.parse(['--option'], { from: 'user' }));\nexpectType<commander.Command>(program.parse(['node', 'script.js'] as const));\n\n// parseAsync, same tests as parse\nexpectType<Promise<commander.Command>>(program.parseAsync());\nexpectType<Promise<commander.Command>>(program.parseAsync(process.argv));\nexpectType<Promise<commander.Command>>(\n  program.parseAsync(['node', 'script.js'], { from: 'node' }),\n);\nexpectType<Promise<commander.Command>>(\n  program.parseAsync(['node', 'script.js'], { from: 'electron' }),\n);\nexpectType<Promise<commander.Command>>(\n  program.parseAsync(['--option'], { from: 'user' }),\n);\nexpectType<Promise<commander.Command>>(\n  program.parseAsync(['node', 'script.js'] as const),\n);\n\n// parseOptions (and ParseOptionsResult)\nexpectType<{ operands: string[]; unknown: string[] }>(\n  program.parseOptions(['node', 'script.js', 'hello']),\n);\n\n// save/restore state\nexpectType<void>(program.saveStateBeforeParse());\nexpectType<void>(program.restoreStateBeforeParse());\n\n// opts\nconst opts = program.opts();\nexpectType<commander.OptionValues>(opts);\nexpectType(opts.foo);\nexpectType(opts.bar);\n\n// opts with generics\ninterface MyCheeseOption {\n  cheese: string;\n}\nconst myCheeseOption = program.opts<MyCheeseOption>();\nexpectType<string>(myCheeseOption.cheese);\n// @ts-expect-error Check that options strongly typed and does not allow arbitrary properties\nexpectType(myCheeseOption.foo);\n\n// optsWithGlobals\nconst optsWithGlobals = program.optsWithGlobals();\nexpectType<commander.OptionValues>(optsWithGlobals);\nexpectType(optsWithGlobals.foo);\nexpectType(optsWithGlobals.bar);\n\n// optsWithGlobals with generics\nconst myCheeseOptionWithGlobals = program.optsWithGlobals<MyCheeseOption>();\nexpectType<string>(myCheeseOptionWithGlobals.cheese);\n// @ts-expect-error Check that options strongly typed and does not allow arbitrary properties\nexpectType(myCheeseOptionWithGlobals.foo);\n\n// description\nexpectType<commander.Command>(program.description('my description'));\nexpectType<string>(program.description());\nexpectType<commander.Command>(\n  program.description('my description of command with arg foo', {\n    foo: 'foo description',\n  }),\n); // deprecated\n\n// summary\nexpectType<commander.Command>(program.summary('my summary'));\nexpectType<string>(program.summary());\n\n// alias\nexpectType<commander.Command>(program.alias('my alias'));\nexpectType<string>(program.alias());\n\n// aliases\nexpectType<commander.Command>(program.aliases(['first-alias', 'second-alias']));\nexpectType<commander.Command>(\n  program.aliases(['first-alias', 'second-alias'] as const),\n);\nexpectType<string[]>(program.aliases());\n\n// usage\nexpectType<commander.Command>(program.usage('my usage'));\nexpectType<string>(program.usage());\n\n// name\nexpectType<commander.Command>(program.name('my-name'));\nexpectType<string>(program.name());\n\n// helpGroup related\nexpectType<commander.Command>(program.helpGroup('My Group'));\nexpectType<string>(program.helpGroup());\n\nexpectType<commander.Command>(program.commandsGroup('My Group'));\nexpectType<string>(program.commandsGroup());\n\nexpectType<commander.Command>(program.optionsGroup('My Group'));\nexpectType<string>(program.optionsGroup());\n\n// nameFromFilename\nexpectType<commander.Command>(program.nameFromFilename(__filename));\n\n// executableDir\nexpectType<commander.Command>(program.executableDir(__dirname));\nexpectType<string | null>(program.executableDir());\n\n// outputHelp\nexpectType<void>(program.outputHelp());\nexpectType<void>(\n  program.outputHelp((str: string) => {\n    return str;\n  }),\n);\nexpectType<void>(program.outputHelp({ error: true }));\n\n// help\nexpectType<never>(program.help());\nexpectType<never>(\n  program.help((str: string) => {\n    return str;\n  }),\n);\nexpectType<never>(program.help({ error: true }));\n\n// helpInformation\nexpectType<string>(program.helpInformation());\nexpectType<string>(program.helpInformation({ error: true }));\n\n// helpOption\nexpectType<commander.Command>(program.helpOption('-h,--help'));\nexpectType<commander.Command>(\n  program.helpOption('-h,--help', 'custom description'),\n);\nexpectType<commander.Command>(\n  program.helpOption(undefined, 'custom description'),\n);\nexpectType<commander.Command>(program.helpOption(false));\n\n// addHelpOption\nexpectType<commander.Command>(\n  program.addHelpOption(new commander.Option('-h,--help')),\n);\n\n// addHelpText\nexpectType<commander.Command>(program.addHelpText('after', 'text'));\nexpectType<commander.Command>(program.addHelpText('afterAll', 'text'));\nexpectType<commander.Command>(program.addHelpText('before', () => 'before'));\nexpectType<commander.Command>(\n  program.addHelpText('beforeAll', (context) => {\n    expectType<boolean>(context.error);\n    expectType<commander.Command>(context.command);\n    return '';\n  }),\n);\n\n// on\nexpectType<commander.Command>(program.on('command:foo', () => {}));\n\n// createCommand\nexpectType<commander.Command>(program.createCommand());\nexpectType<commander.Command>(program.createCommand('name'));\n\nclass MyCommand extends commander.Command {\n  createCommand(name?: string): MyCommand {\n    return new MyCommand(name);\n  }\n\n  myFunction(): void {\n    // do nothing.\n  }\n}\nconst myProgram = new MyCommand();\nexpectType<MyCommand>(myProgram.command('sub'));\n\n// configureHelp\nexpectType<commander.Help>(program.createHelp());\nexpectType<commander.Command>(\n  program.configureHelp({\n    sortSubcommands: true, // override property\n    visibleCommands: () => [], // override method\n  }),\n);\nexpectType<commander.HelpConfiguration>(program.configureHelp());\n\n// copyInheritedSettings\nexpectType<commander.Command>(\n  program.copyInheritedSettings(new commander.Command()),\n);\n\n// showHelpAfterError\nexpectType<commander.Command>(program.showHelpAfterError());\nexpectType<commander.Command>(program.showHelpAfterError(true));\nexpectType<commander.Command>(program.showHelpAfterError('See --help'));\n\n// showSuggestionAfterError\nexpectType<commander.Command>(program.showSuggestionAfterError());\nexpectType<commander.Command>(program.showSuggestionAfterError(false));\n\n// configureOutput\nexpectType<commander.Command>(program.configureOutput({}));\nexpectType<commander.OutputConfiguration>(program.configureOutput());\n\nexpectType<commander.Command>(\n  program.configureOutput({\n    writeOut: (str: string) => {\n      console.log(str);\n    },\n    writeErr: (str: string) => {\n      console.error(str);\n    },\n    outputError: (str: string, write: (str: string) => void) => {\n      write(str);\n    },\n\n    getOutHelpWidth: () => 80,\n    getErrHelpWidth: () => 80,\n\n    getOutHasColors: () => true,\n    getErrHasColors: () => true,\n    stripColor: (str) => str,\n  }),\n);\n\n// Help\nconst helper = new commander.Help();\nconst helperCommand = new commander.Command();\nconst helperOption = new commander.Option('-a, --all');\nconst helperArgument = new commander.Argument('<file>');\n\nhelper.prepareContext({});\nhelper.prepareContext({ helpWidth: 120, error: true, outputHasColors: false });\n\nexpectType<number | undefined>(helper.helpWidth);\nexpectType<number>(helper.minWidthToWrap);\nexpectType<boolean>(helper.sortSubcommands);\nexpectType<boolean>(helper.sortOptions);\nexpectType<boolean>(helper.showGlobalOptions);\n\nexpectType<string>(helper.subcommandTerm(helperCommand));\nexpectType<string>(helper.commandUsage(helperCommand));\nexpectType<string>(helper.commandDescription(helperCommand));\nexpectType<string>(helper.subcommandDescription(helperCommand));\nexpectType<string>(helper.optionTerm(helperOption));\nexpectType<string>(helper.optionDescription(helperOption));\nexpectType<string>(helper.argumentTerm(helperArgument));\nexpectType<string>(helper.argumentDescription(helperArgument));\n\nexpectType<commander.Command[]>(helper.visibleCommands(helperCommand));\nexpectType<commander.Option[]>(helper.visibleOptions(helperCommand));\nexpectType<commander.Option[]>(helper.visibleGlobalOptions(helperCommand));\nexpectType<commander.Argument[]>(helper.visibleArguments(helperCommand));\n\nexpectType<number>(helper.longestSubcommandTermLength(helperCommand, helper));\nexpectType<number>(helper.longestOptionTermLength(helperCommand, helper));\nexpectType<number>(helper.longestGlobalOptionTermLength(helperCommand, helper));\nexpectType<number>(helper.longestArgumentTermLength(helperCommand, helper));\nexpectType<number>(helper.padWidth(helperCommand, helper));\n\nexpectType<number>(helper.displayWidth('some string'));\nexpectType<string>(helper.boxWrap('a b c', 50));\nexpectType<string>(\n  helper.formatItem('--example', 12, 'example description', helper),\n);\nexpectType<boolean>(helper.preformatted('a\\nb c'));\n\n{\n  const formattedItems = [\n    '--example  example description',\n    '--example2 example2 description',\n  ];\n  expectType<string[]>(\n    helper.formatItemList('Options', formattedItems, helper),\n  );\n}\n\n{\n  const unsortedOptions = [new commander.Option('-a, --all')];\n  const sortedOptions = unsortedOptions;\n  const groupsItemsOptionHeading = (option: commander.Option) =>\n    option.helpGroupHeading ?? 'Options:';\n  expectType<Map<string, commander.Option[]>>(\n    helper.groupItems(unsortedOptions, sortedOptions, groupsItemsOptionHeading),\n  );\n}\n\n{\n  const unsortedCommands = [new commander.Command('foo')];\n  const sortedCommands = unsortedCommands;\n  const groupsItemsCommandHeading = (cmd: commander.Command) =>\n    cmd.helpGroup() ?? 'Commands:';\n  expectType<Map<string, commander.Command[]>>(\n    helper.groupItems(\n      unsortedCommands,\n      sortedCommands,\n      groupsItemsCommandHeading,\n    ),\n  );\n}\n\nexpectType<string>(helper.styleTitle('Usage:'));\n\nexpectType<string>(helper.styleUsage('foo [options] <file>'));\nexpectType<string>(helper.styleCommandText('foo'));\n\nexpectType<string>(helper.styleCommandDescription('description'));\nexpectType<string>(helper.styleOptionDescription('description'));\nexpectType<string>(helper.styleSubcommandDescription('description'));\nexpectType<string>(helper.styleArgumentDescription('description'));\nexpectType<string>(helper.styleDescriptionText('description'));\n\nexpectType<string>(helper.styleOptionTerm('-a, --all'));\nexpectType<string>(helper.styleSubcommandTerm('bar [options]'));\nexpectType<string>(helper.styleArgumentTerm('<file>'));\n\nexpectType<string>(helper.styleOptionText('-a, --all'));\nexpectType<string>(helper.styleSubcommandText('bar'));\nexpectType<string>(helper.styleArgumentText('<file>'));\n\nexpectType<string>(helper.formatHelp(helperCommand, helper));\n\n// Option properties\nconst baseOption = new commander.Option('-f,--foo', 'foo description');\nexpectType<string>(baseOption.flags);\nexpectType<string>(baseOption.description);\nexpectType<boolean>(baseOption.required);\nexpectType<boolean>(baseOption.optional);\nexpectType<boolean>(baseOption.variadic);\nexpectType<boolean>(baseOption.mandatory);\nexpectType<string | undefined>(baseOption.short);\nexpectType<string | undefined>(baseOption.long);\nexpectType<boolean>(baseOption.negate);\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexpectType<any>(baseOption.defaultValue);\nexpectType<string | undefined>(baseOption.defaultValueDescription);\nexpectType<unknown>(baseOption.presetArg);\nexpectType<string | undefined>(baseOption.envVar);\nexpectType<boolean>(baseOption.hidden);\nexpectType<string[] | undefined>(baseOption.argChoices);\nexpectType<string | undefined>(baseOption.helpGroupHeading);\n\n// Option methods\n\n// default\nexpectType<commander.Option>(baseOption.default(3));\nexpectType<commander.Option>(baseOption.default(60, 'one minute'));\n\n// preset\nexpectType<commander.Option>(baseOption.preset(123));\nexpectType<commander.Option>(baseOption.preset('abc'));\n\n// env\nexpectType<commander.Option>(baseOption.env('PORT'));\n\n// argParser\nexpectType<commander.Option>(\n  baseOption.argParser((value: string) => parseInt(value)),\n);\nexpectType<commander.Option>(\n  baseOption.argParser((value: string, previous: string[]) => {\n    return previous.concat(value);\n  }),\n);\n\n// makeOptionMandatory\nexpectType<commander.Option>(baseOption.makeOptionMandatory());\nexpectType<commander.Option>(baseOption.makeOptionMandatory(true));\n\n// hideHelp\nexpectType<commander.Option>(baseOption.hideHelp());\nexpectType<commander.Option>(baseOption.hideHelp(true));\nexpectType<commander.Option>(baseOption.hideHelp(false));\n\n// choices\nexpectType<commander.Option>(baseOption.choices(['a', 'b']));\nexpectType<commander.Option>(baseOption.choices(['a', 'b'] as const));\n\n// conflicts\nexpectType<commander.Option>(baseOption.conflicts('a'));\nexpectType<commander.Option>(baseOption.conflicts(['a', 'b']));\n\n// implies\nexpectType<commander.Option>(\n  baseOption.implies({ option: 'VALUE', colour: false }),\n);\n\n// name\nexpectType<string>(baseOption.name());\n\n// attributeName\nexpectType<string>(baseOption.attributeName());\n\n// helpGroup\nexpectType<commander.Option>(baseOption.helpGroup('My Group'));\n// @ts-expect-error: Option helpGroup() can not be used as a getter.\nbaseOption.helpGroup();\n\n// isBoolean\nexpectType<boolean>(baseOption.isBoolean());\n\n// Argument properties\nconst baseArgument = new commander.Argument('<foo');\nexpectType<string>(baseArgument.description);\nexpectType<boolean>(baseArgument.required);\nexpectType<boolean>(baseArgument.variadic);\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexpectType<any>(baseArgument.defaultValue);\nexpectType<string | undefined>(baseArgument.defaultValueDescription);\nexpectType<string[] | undefined>(baseArgument.argChoices);\n\n// Argument methods\n\n// name\nexpectType<string>(baseArgument.name());\n\n// default\nexpectType<commander.Argument>(baseArgument.default(3));\nexpectType<commander.Argument>(baseArgument.default(60, 'one minute'));\n\n// argParser\nexpectType<commander.Argument>(\n  baseArgument.argParser((value: string) => parseInt(value)),\n);\nexpectType<commander.Argument>(\n  baseArgument.argParser((value: string, previous: string[]) => {\n    return previous.concat(value);\n  }),\n);\n\n// choices\nexpectType<commander.Argument>(baseArgument.choices(['a', 'b']));\nexpectType<commander.Argument>(baseArgument.choices(['a', 'b'] as const));\n\n// argRequired\nexpectType<commander.Argument>(baseArgument.argRequired());\n\n// argOptional\nexpectType<commander.Argument>(baseArgument.argOptional());\n\n// createArgument\nexpectType<commander.Argument>(program.createArgument('<name>'));\nexpectType<commander.Argument>(program.createArgument('<name>', 'description'));\n"
  }
]