[
  {
    "path": ".github/dependabot.yml",
    "content": "# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates\nversion: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\" # Location of package manifests\n    schedule:\n      interval: \"monthly\"\n"
  },
  {
    "path": ".github/workflows/TagBot.yml",
    "content": "name: TagBot\non:\n  issue_comment:\n    types:\n      - created\n  workflow_dispatch:\njobs:\n  TagBot:\n    if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'\n    runs-on: ubuntu-latest\n    steps:\n      - uses: JuliaRegistries/TagBot@v1\n        with:\n          token: ${{ secrets.GITHUB_TOKEN }}\n          ssh: ${{ secrets.DOCUMENTER_KEY }}\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\non:\n  push:\n    branches:\n      - master\n    tags: '*'\n  pull_request:\n  schedule:\n    # Run CI against `master` every Sunday\n    - cron: '0 0 * * 0'\njobs:\n  test:\n    name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}\n    runs-on: ${{ matrix.os }}\n    continue-on-error: ${{ matrix.version == 'nightly' }}\n    strategy:\n      matrix:\n        version:\n          - '1.0'  # Oldest supported version\n          - '1'    # Latest release\n          - 'nightly'\n        os:\n          - ubuntu-latest\n          - macOS-latest\n          - windows-latest\n        arch:\n          - x64\n          - x86\n        exclude:\n          # Remove some configurations from the build matrix to reduce CI time.\n          # See https://github.com/marketplace/actions/setup-julia-environment\n          - os: macOS-latest\n            arch: x86\n          - os: windows-latest\n            arch: x86\n    steps:\n      - uses: actions/checkout@v6\n      - uses: julia-actions/setup-julia@v2\n        with:\n          version: ${{ matrix.version }}\n          arch: ${{ matrix.arch }}\n      - uses: julia-actions/cache@v3\n      - uses: julia-actions/julia-buildpkg@v1\n      - uses: julia-actions/julia-runtest@v1\n      - uses: julia-actions/julia-processcoverage@v1\n      - uses: codecov/codecov-action@v6\n        with:\n          files: lcov.info\n"
  },
  {
    "path": ".github/workflows/documentation.yml",
    "content": "name: Documentation\n\non:\n  push:\n    branches:\n      - master\n    tags: '*'\n  pull_request:\n\njobs:\n  build:\n    permissions:\n      actions: write\n      contents: write\n      pull-requests: read\n      statuses: write\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: julia-actions/setup-julia@v2\n        with:\n          version: '1.12'\n      - uses: julia-actions/cache@v3\n      - name: Install dependencies\n        shell: julia --color=yes --project=docs {0}\n        run: |\n          using Pkg\n          Pkg.develop(PackageSpec(path=pwd()))\n          Pkg.instantiate()\n      - name: Build and deploy\n        run: julia --color=yes --project=docs docs/make.jl\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # If authenticating with GitHub Actions token\n          DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # If authenticating with SSH deploy key\n"
  },
  {
    "path": "LICENSE.md",
    "content": "The ArgParse Julia module is licensed under the MIT License:\n\n> Copyright (c) 2012: Carlo Baldassi\n>\n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> \"Software\"), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n>\n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nPortions of this software are derived from Python 3.5.1 code, and therefore is licensed under\nthe permissive but slightly more strict Python Software Foundation license, and is partially\ncopyright 2001-2016 Python Software Foundation; All Rights Reserved.\n\n> 1. This LICENSE AGREEMENT is between the Python Software Foundation (\"PSF\"), and\n>    the Individual or Organization (\"Licensee\") accessing and otherwise using Python\n>    3.5.1 software in source or binary form and its associated documentation.\n>\n> 2. Subject to the terms and conditions of this License Agreement, PSF hereby\n>    grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,\n>    analyze, test, perform and/or display publicly, prepare derivative works,\n>    distribute, and otherwise use Python 3.5.1 alone or in any derivative\n>    version, provided, however, that PSF's License Agreement and PSF's notice of\n>    copyright, i.e., \"Copyright © 2001-2016 Python Software Foundation; All Rights\n>    Reserved\" are retained in Python 3.5.1 alone or in any derivative version\n>    prepared by Licensee.\n>\n> 3. In the event Licensee prepares a derivative work that is based on or\n>    incorporates Python 3.5.1 or any part thereof, and wants to make the\n>    derivative work available to others as provided herein, then Licensee hereby\n>    agrees to include in any such work a brief summary of the changes made to Python\n>    3.5.1.\n>\n> 4. PSF is making Python 3.5.1 available to Licensee on an \"AS IS\" basis.\n>    PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.  BY WAY OF\n>    EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR\n>    WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE\n>    USE OF PYTHON 3.5.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.\n>\n> 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.5.1\n>    FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF\n>    MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.5.1, OR ANY DERIVATIVE\n>    THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\n>\n> 6. This License Agreement will automatically terminate upon a material breach of\n>    its terms and conditions.\n>\n> 7. Nothing in this License Agreement shall be deemed to create any relationship\n>    of agency, partnership, or joint venture between PSF and Licensee.  This License\n>    Agreement does not grant permission to use PSF trademarks or trade name in a\n>    trademark sense to endorse or promote products or services of Licensee, or any\n>    third party.\n>\n> 8. By copying, installing or otherwise using Python 3.5.1, Licensee agrees\n>    to be bound by the terms and conditions of this License Agreement.\n"
  },
  {
    "path": "Project.toml",
    "content": "name = \"ArgParse\"\nuuid = \"c7e460c6-2fb9-53a9-8c5b-16f535851c63\"\nauthor = [\"Carlo Baldassi <carlobaldassi@gmail.com>\"]\nversion = \"1.2.0\"\n\n[deps]\nLogging = \"56ddb016-857b-54e1-b83d-db4d58db5568\"\nTextWrap = \"b718987f-49a8-5099-9789-dcd902bef87d\"\n\n[compat]\nTextWrap = \"0.1.4, 1\"\njulia = \"1\"\n\n[extras]\nTest = \"8dfed614-e22c-5e08-85e1-65c5234f0b40\"\n\n[targets]\ntest = [\"Test\"]\n\n[workspace]\nprojects = [\"docs\"]\n"
  },
  {
    "path": "README.md",
    "content": "# ArgParse.jl\n\n[![DOCS][docs-img]][docs-url] [![CI][CI-img]][CI-url] [![CODECOV][codecov-img]][codecov-url]\n\nArgParse.jl is a package for parsing command-line arguments to [Julia][julia] programs.\n\n### Installation and usage\n\nTo install the module, use Julia's package manager: start pkg mode by pressing `]` and then enter:\n\n```\n(v1.5) pkg> add ArgParse\n```\n\nThe module can then be loaded like any other Julia module:\n\n```\njulia> using ArgParse\n```\n\n### Documentation\n\n- The manual is [HERE][docs-url].\n- See also the examples in the [examples directory](examples).\n\n## Changes in release 1.2.0\n\n* Add options to control the help text formatting ([#132][PR132])\n* Allow defaults that can be converted into the target argument type ([#133][PR133])\n\n## Changes in release 1.1.5\n\n* Fix ambiguity with julia 1.11 new `wrap` function (see [#128][PR128])\n* Throw a new `ArgParseSettingError` for all settings-related errors\n* Fixed some tests\n\n## Changes in release 1.1.4\n\n* Fix in @project_version macro (see [#107][PR107])\n\n## Changes in release 1.1.3\n\n* Added a @project_version macro (see [#106][PR106])\n\n## Changes in release 1.1.2\n\n* Faster startup time by disabling optimizations/inference (see [#104][PR104])\n\n## Changes in release 1.1.1\n\n* Fixed the case when using symbol keys, commands are not required, no command is provided\n\n## Changes in release 1.1.0\n\n* Try using the constructor for types that don't define a `convert` method from `AbstractString`\n\n## Changes in release 1.0.1\n\n* Small fixes in docs\n\n## Changes in release 1.0.0\n\n* Drop support for Julia versions v0.6/v0.7\n* Renamed a few functions and macros (old versions can be used but produce deprecation warnings):\n  + `@add_arg_table` → `@add_arg_table!`\n  + `add_arg_table` → `add_arg_table!`\n  + `add_arg_group` → `add_arg_group!`\n  + `set_default_arg_group` → `set_default_arg_group!`\n  + `import_settings` → `import_settings!`. The signature of this function has also changed:\n    `args_only` is now a keyword argument\n* Parsing does not exit julia by default when in interactive mode now\n* Added mutually-exclusive and/or required argument groups\n* Added command aliases\n\n## Changes in release 0.6.2\n\n* Fix a remaining compatibility issue (`@warn`)\n\n## Changes in release 0.6.1\n\n* Testing infrastructure update, tiny docs fixes\n\n## Changes in release 0.6.0\n\n* Added support for Julia v0.7, dropped support for Julia v0.5.\n* Added `exit_after_help` setting to control whether to exit julia after help/version info is displayed\n  (which is still the defult) or to just abort the parsing and return `nothing` instead.\n\n## Changes in release 0.5.0\n\n* Added support for Julia v0.6, dropped support for Julia v0.4.\n* The default output type is now `Dict{String,Any}`, as stated in the docs,\n  rather than `Dict{AbstractString,Any}`.\n* Added docstrings, moved documentation to Documenter.jl\n\n## Changes in release 0.4.0\n\n### New features\n\n* Added support for vectors of METAVAR names (see [#33][PR33])\n\n### Other changes\n\n* Support for Julia v0.3 was dropped.\n\n## Changes in release 0.3.1\n\n### New available settings\n\n* `fromfile_prexif_chars` (see [#27][PR27])\n* `preformatted_desciption`/`preformatted_epilog` (see [#28][PR28])\n\n## Changes in release 0.3.0\n\n### Breaking changes\n\nUpgrading from versions 0.2.X to 0.3.X, the following API changes were made,\nwhich may break existing code:\n\n* Option arguments are no longer evaluated by default. This is for security\n  reasons. Evaluation can be forced on a per-option basis with the\n  `eval_arg=true` setting (although this is discuraged).\n* The syntax of the `add_arg_table` function has changed, it now takes a `Dict`\n  object instead of an `@options` opbject, since the dependency on the\n  Options.jl module was removed. (The `@add_arg_table` macro is unchanged\n  though.)\n\n### Other changes\n\n* Documented that overloading the function `ArgParse.parse_item` can be used to\n  instruct ArgParse on how to parse custom types. Parse error reporting was\n  also improved\n* Removed dependecy on the Options.jl module\n* Enabled precompilation on Julia 0.4\n\n\n[Julia]: http://julialang.org\n\n[docs-img]: https://img.shields.io/badge/docs-stable-blue.svg\n[docs-url]: https://carlobaldassi.github.io/ArgParse.jl/stable\n\n[codecov-img]: https://codecov.io/gh/carlobaldassi/ArgParse.jl/branch/master/graph/badge.svg\n[codecov-url]: https://codecov.io/gh/carlobaldassi/ArgParse.jl\n\n[CI-img]: https://github.com/carlobaldassi/ArgParse.jl/actions/workflows/ci.yml/badge.svg\n[CI-url]: https://github.com/carlobaldassi/ArgParse.jl/actions/workflows/ci.yml\n\n[PR27]: https://github.com/carlobaldassi/ArgParse.jl/pull/27\n[PR28]: https://github.com/carlobaldassi/ArgParse.jl/pull/28\n[PR33]: https://github.com/carlobaldassi/ArgParse.jl/pull/33\n[PR104]: https://github.com/carlobaldassi/ArgParse.jl/pull/104\n[PR106]: https://github.com/carlobaldassi/ArgParse.jl/pull/106\n[PR107]: https://github.com/carlobaldassi/ArgParse.jl/pull/107\n[PR128]: https://github.com/carlobaldassi/ArgParse.jl/pull/128\n[PR132]: https://github.com/carlobaldassi/ArgParse.jl/pull/132\n[PR133]: https://github.com/carlobaldassi/ArgParse.jl/pull/133\n"
  },
  {
    "path": "docs/.gitignore",
    "content": "Manifest.toml\nbuild/\n"
  },
  {
    "path": "docs/Project.toml",
    "content": "[deps]\nArgParse = \"c7e460c6-2fb9-53a9-8c5b-16f535851c63\"\nDocumenter = \"e30172f5-a6a5-5a46-863b-614d45cd2de4\"\n\n[compat]\nDocumenter = \"1\"\n"
  },
  {
    "path": "docs/make.jl",
    "content": "using Documenter, ArgParse\n\nCIbuild = get(ENV, \"CI\", nothing) == \"true\"\n\nmakedocs(\n    modules  = [ArgParse],\n    format   = Documenter.HTML(prettyurls = CIbuild),\n    sitename = \"ArgParse.jl\",\n    pages    = Any[\n        \"Home\" => \"index.md\",\n        \"Manual\" => [\n            \"parse_args.md\",\n            \"settings.md\",\n            \"arg_table.md\",\n            \"import.md\",\n            \"conflicts.md\",\n            \"custom.md\",\n            \"details.md\"\n        ]\n    ],\n    warnonly = [:missing_docs],\n)\n\ndeploydocs(\n    repo   = \"github.com/carlobaldassi/ArgParse.jl.git\",\n)\n"
  },
  {
    "path": "docs/src/arg_table.md",
    "content": "# Argument table\n\nThe argument table is used to store allowed arguments and options in an [`ArgParseSettings`](@ref) object.\n\nEach entry of the table consist of an argument name and a list of argument settings, e.g.:\n\n```julia\n\"--verbose\"\n    help = \"verbose output\"\n    action = :store_true\n```\n\nThere are two very similar methods to populate a table:\n\n```@docs\n@add_arg_table!\n```\n\n```@docs\nadd_arg_table!\n```\n\n## Argument names\n\nArgument names are strings or, in the case of options, lists of strings. An argument is an option if it begins with a `'-'`\ncharacter, otherwise it'a positional argument. A single `'-'` introduces a short option, which must consist of a single\ncharacter; long options begin with `\"--\"` instead.\n\nPositional argument names can be any string, except all-uppercase strings between `'%'` characters, which are reserved\n(e.g. `\"%COMMAND%\"`).\nOption names can contain any character except `'='`, whitespaces and non-breakable spaces.\nDepending on the value of the `add_help` and `add_version` settings, options `--help`, `-h` and `--version` may\nbe reserved.\nIf the `allow_ambiguous_opts` setting is `false`, some characters are not allowed as short options: all digits, the dot,\nthe underscore and the opening parethesis (e.g. `-1`, `-.`, `-_`, `-(`).\n\nFor positional arguments, the argument name will be used as the key in the `Dict` object returned by the [`parse_args`](@ref)\nfunction.  For options, it will be used to produce a default key in case a `dest_name` is not explicitly specified in the table\nentry, using either the first long option name in the list or the first short option name if no long options are present.\nFor example:\n\n| argument name                | default `dest_name`     |\n|:-----------------------------|:------------------------|\n| `\"--long\"`                   | `\"long\"`                |\n| `\"--long\", \"-s\"`             | `\"long\"`                |\n| `\"-s\", \"--long1\", \"--long2\"` | `\"long1\"`               |\n| `\"-s\", \"-x\"`                 | `\"s\"`                   |\n\nIn case the `autofix_names` setting is `true` (it is `false` by default), dashes in the names of arguments and long options will be\nconverted to underscores: for example, `\"--my-opt\"` will yield `\"my_opt\"` as the default `dest_name`.\n\nThe argument name is also used to generate a default metavar in case `metavar` is not explicitly set in the table entry. The rules\nare the same used to determine the default `dest_name`, but for options the result will be uppercased (e.g. `\"--long\"` will\nbecome `LONG`). Note that this poses additional constraints on the positional argument names (e.g. whitespace is not allowed in\nmetavars).\n\n## Argument entry settings\n\nArgument entry settings determine all aspects of an argument's behavior. Some settings combinations are contradictory and will produce\nan error (e.g. using both `action = :store_true` and `nargs = 1`, or using `action = :store_true` with a positional argument).\nAlso, some settings are only meaningful under some conditions (e.g. passing a `metavar` to a flag-like option does not make sense)\nand will be ignored with a warning (unless the `suppress_warnings` general setting is `true`).\n\nThis is the list of all available settings:\n\n* `nargs` (default = `'A'`): the number of extra command-line tokens parsed with the entry. See\n  the section [Available actions and nargs values](@ref) for a complete desctiption.\n* `action`: the action performed when the argument is parsed. It can be passed as a `String` or as a `Symbol` (e.g. both\n  `:store_arg` and `\"store_arg\"` are accepted). The default action is `:store_arg` unless `nargs` is `0`, in which case the\n  default is `:store_true`. See the section [Available actions and nargs values](@ref) for a list of all available actions and a\n  detailed explanation.\n* `arg_type` (default = `Any`): the type of the argument. Only makes sense with non-flag arguments. Only works out-of-the-box with\n  string, symbol and number types, but see the section [Parsing to custom types](@ref) for details on how to make it work for\n  general types (including user-defined ones).\n* `default` (default = `nothing`): the default value if the option or positional argument is not parsed. Only makes sense with\n  non-flag arguments, or when the action is `:store_const` or `:append_const`. Unless it's `nothing`, it must be consistent with\n  `arg_type` and `range_tester`.\n* `constant` (default = `nothing`): this value is used by the `:store_const` and `:append_const` actions, or when `nargs = '?'`\n  and the option argument is not provided.\n* `required` (default = `false`): determines if an argument is required (this setting is ignored by flags, which are always\n  optional, and in general should be avoided for options if possible).\n* `range_tester` (default = `x->true`): a function returning `true` if an argument is allowed and otherwise returning `false` (e.g. you could use `arg_type = Integer` and `range_tester = isodd` to allow only odd integer values)\n* `dest_name` (default = auto-generated): the key which will be associated with the argument in the `Dict` object returned by\n  `parse_args`. The auto-generation rules are explained in the [Argument names](@ref) section. Multiple arguments can share\n  the same destination, provided their actions and types are compatible.\n* `help` (default = `\"\"`): the help string which will be shown in the auto-generated help screen. It's a `String` which will\n  be automaticaly formatted; also, `arg_type` and `default` will be automatically appended to it if provided.\n* `metavar` (default = auto-generated): a token which will be used in usage and help screens to describe the argument syntax. For\n  positional arguments, it will also be used as an identifier in all other messages (e.g. in reporting errors), therefore it must\n  be unique. For optional arguments, if `nargs > 1` then `metavar` can be a `Vector` of `String`s of length `nargs`. The\n  auto-generations rules are explained in the [Argument names](@ref) section.\n* `force_override`: if `true`, conflicts are ignored when adding this entry in the argument table (see also the\n  [Conflicts and overrides](@ref) section). By default, it follows the general `error_on_conflict` settings.\n* `group`: the option group to which the argument will be assigned to (see the [Argument groups](@ref) section). By default, the\n  current default group is used if specified, otherwise the assignment is automatic.\n* `eval_arg` (default: `false`): if `true`, the argument will be parsed as a Julia expression and evaluated, which means that\n  for example `\"2+2\"` will yield the integer `4` rather than a string. Note that this is a security risk for outside-facing\n  programs and should generally be avoided: overload `ArgParse.parse_item` instead (see the section [Parsing to custom types](@ref)).\n  Only makes sense for non-flag arguments.\n\n## Available actions and nargs values\n\nThe `nargs` and `action` argument entry settings are used together to determine how many tokens will be parsed from the command\nline and what action will be performed on them.\n\nThe `nargs` setting can be a number or a character; the possible values are:\n\n* `'A'`: automatic, i.e. inferred from the action (this is the default). In practice, it means `0` for options with flag actions\n(see the actions categorization below, in this section) and `1` for options with non-flag actions (but it's different from\nusing an explicit `1` because the result is not stored in a `Vector`).\n* `0`: this is the only possibility (besides `'A'`) for flag actions, and it means no extra tokens will be parsed from\n  the command line. If `action` is not specified, setting `nargs` to `0` will make `action` default to `:store_true`.\n* a positive integer number `N`: exactly `N` tokens will be parsed from the command-line, and stored into a `Vector`\n  of length `N`. Note that `nargs=1` produces a `Vector` of one item.\n* `'?'`: optional, i.e. a token will only be parsed if it does not look like an option (see the [Parsing details](@ref) section\n  for a discussion of how exactly this is established). If the option string is not given, the `default` argument value will be\n  used. If the option string is given but not followed by an option parameter, the `constant` argument value will be used\n  instead. This only makes sense with options.\n* `'*'`: any number, i.e. all subsequent tokens are stored into a `Vector`, up until a token which looks like an option is\n  encountered, or all tokens are consumed.\n* `'+'`: like `'*'`, but at least one token is required.\n* `'R'`: all remainder tokens, i.e. like `'*'` but it does not stop at options.\n\nActions can be categorized in many ways; one prominent distinction is flag vs. non-flag: some actions are for options which take no\nargument (i.e. flags), all others (except `command`, which is special) are for other options and positional arguments:\n\n* flag actions are only compatible with `nargs = 0` or `nargs = 'A'`\n* non-flag actions are not compatible with `nargs = 0`.\n\nIn other words, all flags (takes no argument) are options (starts with a dash), but not all options (starts with a dash)\nare flags (takes no argument).\n\nThis is the list of all available actions (in each example, suppose we defined `settings = ArgParseSettings()`):\n\n* `store_arg` (non-flag): store the argument. This is the default unless `nargs` is `0`. Example:\n\n  ```julia-repl\n  julia> @add_arg_table!(settings, \"arg\", action => :store_arg);\n\n  julia> parse_args([\"x\"], settings)\n  Dict{String,Any} with 1 entry:\n    \"arg\" => \"x\"\n  ```\n\n  The result is a vector if `nargs` is a non-zero number, or one of `'*'`, `'+'`, `'R'`:\n\n  ```julia-repl\n  julia> @add_arg_table!(settings, \"arg\", action => :store_arg, nargs => 2);\n\n  julia> parse_args([\"x\", \"y\"], settings)\n  Dict{String,Any} with 1 entry:\n    \"arg\" => Any[\"x\",\"y\"]\n  ```\n\n* `store_true` (flag): store `true` if given, otherwise `false`. Example:\n\n  ```julia-repl\n  julia> @add_arg_table!(settings, \"-v\", action => :store_true);\n\n  julia> parse_args([], settings)\n  Dict{String,Any} with 1 entry:\n    \"v\" => false\n\n  julia> parse_args([\"-v\"], settings)\n  Dict{String,Any} with 1 entry:\n    \"v\" => true\n  ```\n\n* `store_false` (flag): store `false` if given, otherwise `true`. Example:\n\n  ```julia-repl\n  julia> @add_arg_table!(settings, \"-v\", action => :store_false);\n\n  julia> parse_args([], settings)\n  Dict{String,Any} with 1 entry:\n    \"v\" => true\n\n  julia> parse_args([\"-v\"], settings)\n  Dict{String,Any} with 1 entry:\n    \"v\" => false\n  ```\n\n* `store_const` (flag): store the value passed as `constant` in the entry settings if given, otherwise `default`.\n  Example:\n\n  ```julia-repl\n  julia> @add_arg_table!(settings, \"-v\", action => :store_const,\n                                         constant => 1,\n                                         default => 0);\n\n  julia> parse_args([], settings)\n  Dict{String,Any} with 1 entry:\n    \"v\" => 0\n\n  julia> parse_args([\"-v\"], settings)\n  Dict{String,Any} with 1 entry:\n    \"v\" => 1\n  ```\n\n* `append_arg` (non-flag): append the argument to the result. Example:\n\n  ```julia-repl\n  julia> @add_arg_table!(settings, \"-x\", action => :append_arg);\n\n  julia> parse_args([\"-x\", \"1\", \"-x\", \"2\"], settings)\n  Dict{String,Any} with 1 entry:\n    \"x\" => Any[\"1\",\"2\"]\n  ```\n\n  The result will be a `Vector{Vector}` if `nargs` is a non-zero number, or one of `'*'`, `'+'`, `'R'`:\n\n  ```julia-repl\n  julia> @add_arg_table!(settings, \"-x\", action => :append_arg, nargs => '*');\n\n  julia> parse_args([\"-x\", \"1\", \"2\", \"-x\", \"3\"], settings)\n  Dict{String,Any} with 1 entry:\n    \"x\" => Array{Any,1}[Any[\"1\",\"2\"],Any[\"3\"]]\n  ```\n\n* `append_const` (flag): append the value passed as `constant` in the entry settings. Example:\n\n  ```julia-repl\n  julia> @add_arg_table!(settings, \"-x\", action => :append_const, constant => 1);\n\n  julia> parse_args([\"-x\", \"-x\", \"-x\"], settings)\n  Dict{String,Any} with 1 entry:\n    \"x\" => Any[1,1,1]\n  ```\n\n* `count_invocations` (flag): increase a counter; the final result will be the number of times the option was\n  invoked. Example:\n\n  ```julia-repl\n  julia> @add_arg_table!(settings, \"-x\", action => :count_invocations);\n\n  julia> parse_args([\"-x\", \"-x\", \"-x\"], settings)\n  Dict{String,Any} with 1 entry:\n    \"x\" => 3\n  ```\n\n* `show_help` (flag): show the help screen and exit. This is useful if the `add_help` general setting is\n  `false`. Example:\n\n  ```julia-repl\n  julia> @add_arg_table!(settings, \"-x\", action => :show_help);\n\n  julia> parse_args([\"-x\"], settings)\n  usage: <PROGRAM> [-x]\n\n  optional arguments:\n    -x\n  ```\n\n* `show_version` (flag): show the version information and exit. This is useful if the `add_version` general\n  setting is `false`. Example:\n\n  ```julia-repl\n  julia> settings.version = \"1.0\";\n\n  julia> @add_arg_table!(settings, \"-v\", action => :show_version);\n\n  julia> parse_args([\"-v\"], settings)\n  1.0\n  ```\n\n* `command` (special): the argument or option is a command, i.e. it starts a sub-parsing session (see the\n  [Commands](@ref) section).\n\n\n## Commands\n\nCommands are a special kind of arguments which introduce sub-parsing sessions as soon as they are encountered by `parse_args`\n(and are therefore mutually exclusive).\nThe `ArgParse` module allows commands to look both as positional arguments or as options, with minor differences between the two.\nUnlike actual positional arguments, commands that *look* like positional arguments can have extra names (aliases).\n\nCommands are introduced by the `action = :command` setting in the argument table. Suppose we save the following script in\na file called `cmd_example.jl`:\n\n```julia\nusing ArgParse\n\nfunction parse_commandline()\n    s = ArgParseSettings()\n\n    @add_arg_table! s begin\n        \"cmd1\", \"C\"\n            help = \"first command\"\n            action = :command\n        \"cmd2\", \"K\"\n            help = \"second command\"\n            action = :command\n    end\n\n    return parse_args(s)\nend\n\nparsed_args = parse_commandline()\nprintln(parsed_args)\n```\n\nInvoking the script from the command line, we would get the following help screen:\n\n```text\n$ julia cmd_example.jl --help\nusage: cmd_example.jl [-h] {cmd1|cmd2}\n\ncommands:\n  cmd1        first command (aliases: C)\n  cmd2        second command (aliases: K)\n\noptional arguments:\n  -h, --help  show this help message and exit\n```\n\nIf commands are present in the argument table, `parse_args` will set the special key `\"%COMMAND%\"` in the returned `Dict` and\nfill it with the invoked command (or `nothing` if no command was given):\n\n```text\n$ julia cmd_example.jl cmd1\nDict(\"%COMMAND%\"=>\"cmd1\", \"cmd1\"=>Dict())\n```\n\nThis is unless `parse_args` is invoked with `as_symbols=true`, in which case the special key becomes `:_COMMAND_`. (In that case,\nno other argument is allowed to use `_COMMAND_` as its `dest_name`, or an error will be raised.)\n\nAliases are recognized when parsing, but the returned `Dict` will always use the command's name (the first entry in the\ntable):\n\n```text\n$ julia cmd_example.jl C\nDict(\"%COMMAND%\"=>\"cmd1\", \"cmd1\"=>Dict())\n```\n\nSince commands introduce sub-parsing sessions, an additional key will be added for the called command (`\"cmd1\"` in this case) whose\nassociated value is another `Dict{String, Any}` containing the result of the sub-parsing (in the above case it's empty). In fact,\nwith the default settings, commands have their own help screens:\n\n```text\n$ julia cmd_example.jl cmd1 --help\nusage: cmd_example.jl cmd1 [-h]\n\noptional arguments:\n  -h, --help  show this help message and exit\n```\n\nThe argument settings and tables for commands can be accessed by using a dict-like notation, i.e. `settings[\"cmd1\"]` is an\n`ArgParseSettings` object specific to the `\"cmd1\"` command. Therefore, to populate a command sub-argument-table, simply\nuse `@add_arg_table!(settings[\"cmd1\"], table...)` and similar.\n\nThese sub-settings are created when a command is added to the argument table, and by default they inherit their parent general\nsettings except for the `prog` setting (which is auto-generated, as can be seen in the above example) and the\n`description`, `epilog` and `usage` settings (which are left empty).\n\nCommands can also have sub-commands.\n\nBy default, if commands exist, they are required; this can be avoided by setting the `commands_are_required = false` general setting.\n\nThe only meaningful settings for commands in an argument entry besides `action` are `help`, `force_override`, `group` and\n(for flags only) `dest_name`.\n\nThe only differences between positional-arguments-like and option-like commands are in the way they are parsed, and the fact\nthat options accept a `dest_name` setting.\n\nNote that short-form option-like commands will be still be recognized in the middle of a short options group and trigger a sub-parsing\nsession: for example, if an option `-c` is associated to a command, then `-xch` will parse option `-x` according to the parent\nsettings, and option `-h` according to the command sub-settings.\n\n## Argument groups\n\nBy default, the auto-generated help screen divides arguments into three groups: commands, positional arguments and optional\narguments, displayed in that order. Example:\n\n```@setup args\nusing ArgParse\n```\n\n```@repl args\nsettings = ArgParseSettings();\n\n@add_arg_table! settings begin\n   \"--opt\"\n   \"arg\"\n     required = true\n   \"cmd1\"\n     action = :command\n   \"cmd2\"\n     action = :command\nend;\n\nsettings.exit_after_help = false # hide\n\nparse_args([\"--help\"], settings)\n```\n\nIt is possible to partition the arguments differently by defining and using customized argument groups.\nGroups of options can also be declared to be mutually exclusive, meaning that no more than one of the\noptions in the group can be provided. A group can also be declared to be required, meaning that at least\none argument in the group needs to be provided.\n\n```@docs\nadd_arg_group!\n```\n\n```@docs\nset_default_arg_group!\n```\n\nBesides setting a default group with `add_arg_group!` and `set_default_group!`, it's also possible to assign individual arguments\nto a group by using the `group` setting in the argument table entry, which follows the same rules as `set_default_group!`.\n\nNote that if the `add_help` or `add_version` general settings are `true`, the `--help, -h` and `--version` options\nwill always be added to the `optional` group.\n\n## Argument table styles\n\nHere are some examples of styles for the [`@add_arg_table!`](@ref) marco and [`add_arg_table!`](@ref) function invocation:\n\n```julia\n@add_arg_table! settings begin\n    \"--opt\", \"-o\"\n        help = \"an option\"\n    \"arg\"\n        help = \"a positional argument\"\nend\n\n@add_arg_table!(settings\n    , [\"--opt\", \"-o\"]\n    ,    help => \"an option\"\n    , \"arg\"\n    ,    help => \"a positional argument\"\n    )\n\n@add_arg_table! settings begin\n    ([\"--opt\", \"-o\"]; help = an option)\n    (\"arg\"; help = \"a positional argument\")\nend\n\n@add_arg_table!(settings,\n    [\"-opt\", \"-o\"],\n    begin\n        help = \"an option\"\n    end,\n    \"arg\",\n    begin\n        help = \"a positional argument\"\n    end)\n\nadd_arg_table!(settings,\n    [\"-opt\", \"-o\"], Dict(:help => \"an option\"),\n    \"arg\"         , Dict(:help => \"a positional argument\")\n    )\n```\n\nOne restriction is that groups introduced by `begin...end` blocks or semicolon-separated lists between parentheses\ncannot introduce argument names unless the first item in the block is an argument name.\n"
  },
  {
    "path": "docs/src/conflicts.md",
    "content": "# Conflicts and overrides\n\nConflicts between arguments, be them options, positional arguments or commands, can arise for a variety of reasons:\n\n* Two options have the same name (either long or short)\n* Two arguments have the same destination key, but different types (e.g. one is `Any` and the other `String`)\n* Two arguments have the same destination key, but incompatible actions (e.g. one does `:store_arg` and the other\n  `:append_arg`)\n* Two positional arguments have the same metavar (and are therefore indistinguishable in the usage and help screens\n  and in error messages)\n* An argument's destination key is the same as a command name\n* Two commands with the same name are given, but one has a long-option form (e.g. `test` and `--test`)\n* A command alias is equal to another command's name or alias\n\nWhen the general setting `error_on_conflict` is `true`, or any time the specific `force_override` table entry\nsetting is `false`, any of the above conditions leads to an error.\n\nOn the other hand, setting `error_on_conflict` to `false`, or `force_override` to `true`, will try to force\nthe resolution of most of the conflicts in favor of the newest added entry. The general rules are the following:\n\n* In case of duplicate options, all conflicting forms of the older options are removed; if all forms of an\n  option are removed, the option is deleted entirely\n* In case of duplicate destination key and incompatible types or actions, the older argument is deleted\n* In case of duplicate positional arguments metavars, the older argument is deleted\n* A command can override an argument with the same destination key\n* However, an argument can never override a command; neither can a command override another command when added\n  with `@add_arg_table!` (compatible commands are merged by [`import_settings!`](@ref) though)\n* Conflicting command aliases are removed\n"
  },
  {
    "path": "docs/src/custom.md",
    "content": "# Parsing to custom types\n\nIf you specify an `arg_type` setting (see the [Argument entry settings](@ref) section) for an\noption or an argument, `parse_args` will try to parse it, i.e. to convert the string to the\nspecified type. For `Number` types, Julia's built-in `parse` function will be used. For other\ntypes, first `convert` and then the type's constructor will be tried. In order to extend this\nfunctionality, e.g. to user-defined custom types, without adding methods to `convert` or the\nconstructor, you can overload the `ArgParse.parse_item` function. Example:\n\n```julia\nstruct CustomType\n    val::Int\nend\n\nfunction ArgParse.parse_item(::Type{CustomType}, x::AbstractString)\n    return CustomType(parse(Int, x))\nend\n```\n\nNote that the second argument needs to be of type `AbstractString` to avoid ambiguity errors. Also\nnote that if your type is parametric (e.g. `CustomType{T}`), you need to overload the function like\nthis: `function ArgParse.parse_item(::Type{CustomType{T}}, x::AbstractString) where {T}`.\n"
  },
  {
    "path": "docs/src/details.md",
    "content": "# Parsing details\n\nDuring parsing, `parse_args` must determine whether an argument is an option, an option argument, a positional\nargument, or a command. The general rules are explained in the [`parse_args`](@ref) documentation, but\nambiguities may arise under particular circumstances. In particular, negative numbers like `-1` or `-.1e5`\nmay look like options. Under the default settings, such options are forbidden, and therefore those tokens are\nalways recognized as non-options. However, if the `allow_ambiguous_opts` general setting is `true`, existing\noptions in the argument table will take precedence: for example, if the option `-1` is added, and it takes an\nargument, then `-123` will be parsed as that option, and `23` will be its argument.\n\nSome ambiguities still remains though, because the `ArgParse` module can actually accept and parse expressions,\nnot only numbers (although this is not the default), and therefore one may try to pass arguments like `-e` or\n`-pi`; in that case, these will always be at risk of being recognized as options. The easiest workaround is to\nput them in parentheses, e.g. `(-e)`.\n\nWhen an option is declared to accept a fixed positive number of arguments or the remainder of the command line\n(i.e. if `nargs` is a non-zero number, or `'A'`, or `'R'`), `parse_args` will not try to check if the\nargument(s) looks like an option.\n\nIf `nargs` is one of `'?'` or `'*'` or `'+'`, then `parse_args` will take in only arguments which do not\nlook like options.\n\nWhen `nargs` is `'+'` or `'*'` and an option is being parsed, then using the `'='` character will mark what\nfollows as an argument (i.e. not an option); all which follows goes under the rules explained above. The same is true\nwhen short option groups are being parsed. For example, if the option in question is `-x`, then both\n`-y -x=-2 4 -y` and `-yx-2 4 -y` will parse `\"-2\"` and `\"4\"` as the arguments of `-x`.\n\nFinally, note that with the `eval_arg` setting expressions are evaluated during parsing, which means that there is no\nsafeguard against passing things like ```run(`rm -rf someimportantthing`)``` and seeing your data evaporate\n(don't try that!). Be careful and generally try to avoid using the `eval_arg` setting.\n"
  },
  {
    "path": "docs/src/import.md",
    "content": "# Importing settings\n\nIt may be useful in some cases to import an argument table into the one which is to be used, for example to create\nspecialized versions of a common interface.\n\n```@docs\nimport_settings!\n```\n"
  },
  {
    "path": "docs/src/index.md",
    "content": "# ArgParse.jl documentation\n\n```@meta\nCurrentModule = ArgParse\n```\n\nThis [Julia](http://julialang.org) package allows the creation of user-friendly command-line interfaces\nto Julia programs: the program defines which arguments, options and sub-commands it accepts, and the\n`ArgParse` module does the actual parsing, issues errors when the input is invalid, and automatically\ngenerates help and usage messages.\n\nUsers familiar with Python's `argparse` module will find many similarities, but some important differences\nas well.\n\n## Installation\n\nTo install the module, use Julia's package manager: start pkg mode by pressing `]` and then enter:\n\n```\npkg> add ArgParse\n```\n\nDependencies will be installed automatically.\n\n## Quick overview and a simple example\n\nFirst of all, the module needs to be loaded:\n\n```julia\nusing ArgParse\n```\n\nThere are two main steps for defining a command-line interface: creating an [`ArgParseSettings`](@ref) object, and\npopulating it with allowed arguments and options using either the macro [`@add_arg_table!`](@ref) or the\nfunction [`add_arg_table!`](@ref) (see the [Argument table](@ref) section):\n\n```julia\ns = ArgParseSettings()\n@add_arg_table! s begin\n    \"--opt1\"\n        help = \"an option with an argument\"\n    \"--opt2\", \"-o\"\n        help = \"another option with an argument\"\n        arg_type = Int\n        default = 0\n    \"--flag1\"\n        help = \"an option without argument, i.e. a flag\"\n        action = :store_true\n    \"arg1\"\n        help = \"a positional argument\"\n        required = true\nend\n```\n\nIn the macro, options and positional arguments are specified within a `begin...end` block, by one or more names\nin a line, optionally followed by a list of settings.\nSo, in the above example, there are three options:\n\n* the first one, `\"--opt1\"` takes an argument, but doesn't check for its type, and it doesn't have a default value\n* the second one can be invoked in two different forms (`\"--opt2\"` and `\"-o\"`); it also takes an argument, but\n  it must be of `Int` type (or convertible to it) and its default value is `0`\n* the third one, `--flag1`, is a flag, i.e. it doesn't take any argument.\n\nThere is also only one positional argument, `\"arg1\"`, which is declared as mandatory.\n\nWhen the settings are in place, the actual argument parsing is performed via the [`parse_args`](@ref) function:\n\n```julia\nparsed_args = parse_args(ARGS, s)\n```\n\nThe parameter `ARGS` can be omitted. In case no errors are found, the result will be a `Dict{String,Any}` object.\nIn the above example, it will contain the keys `\"opt1\"`, `\"opt2\"`, `\"flag1\"` and `\"arg1\"`, so that e.g.\n`parsed_args[\"arg1\"]` will yield the value associated with the positional argument.\n\n(The `parse_args` function also accepts an optional `as_symbols` keyword argument: when set to `true`, the\nresult of the parsing will be a `Dict{Symbol,Any}`, which can be useful e.g. for passing it as the keywords to a Julia\nfunction.)\n\nPutting all this together in a file, we can see how a basic command-line interface is created:\n\n```julia\nusing ArgParse\n\nfunction parse_commandline()\n    s = ArgParseSettings()\n\n    @add_arg_table! s begin\n        \"--opt1\"\n            help = \"an option with an argument\"\n        \"--opt2\", \"-o\"\n            help = \"another option with an argument\"\n            arg_type = Int\n            default = 0\n        \"--flag1\"\n            help = \"an option without argument, i.e. a flag\"\n            action = :store_true\n        \"arg1\"\n            help = \"a positional argument\"\n            required = true\n    end\n\n    return parse_args(s)\nend\n\nfunction main()\n    parsed_args = parse_commandline()\n    println(\"Parsed args:\")\n    for (arg,val) in parsed_args\n        println(\"  $arg  =>  $val\")\n    end\nend\n\nmain()\n```\n\nIf we save this as a file called `myprog1.jl`, we can see how a `--help` option is added by default,\nand a help message is automatically generated and formatted:\n\n```text\n$ julia myprog1.jl --help\nusage: myprog1.jl [--opt1 OPT1] [-o OPT2] [--flag1] [-h] arg1\n\npositional arguments:\n  arg1             a positional argument\n\noptional arguments:\n  --opt1 OPT1      an option with an argument\n  -o, --opt2 OPT2  another option with an argument (type: Int64,\n                   default: 0)\n  --flag1          an option without argument, i.e. a flag\n  -h, --help       show this help message and exit\n```\n\nAlso, we can see how invoking it with the wrong arguments produces errors:\n\n```text\n$ julia myprog1.jl\nrequired argument arg1 was not provided\nusage: myprog1.jl [--opt1 OPT1] [-o OPT2] [--flag1] [-h] arg1\n\n$ julia myprog1.jl somearg anotherarg\ntoo many arguments\nusage: myprog1.jl [--opt1 OPT1] [-o OPT2] [--flag1] [-h] arg1\n\n$ julia myprog1.jl --opt2 1.5 somearg\ninvalid argument: 1.5 (conversion to type Int64 failed; you may need to overload ArgParse.parse_item;\n                  the error was: ArgumentError(\"invalid base 10 digit '.' in \\\"1.5\\\"\"))\nusage: myprog1.jl [--opt1 OPT1] [-o OPT2] [--flag1] arg1\n```\n\nWhen everything goes fine instead, our program will print the resulting `Dict`:\n\n```text\n$ julia myprog1.jl somearg\nParsed args:\n  arg1  =>  somearg\n  opt2  =>  0\n  opt1  =>  nothing\n  flag1  =>  false\n\n$ julia myprog1.jl --opt1 \"2+2\" --opt2 \"4\" somearg --flag\nParsed args:\n  arg1  =>  somearg\n  opt2  =>  4\n  opt1  =>  2+2\n  flag1  =>  true\n```\n\nFrom these examples, a number of things can be noticed:\n\n* `opt1` defaults to `nothing`, since no `default` setting was used for it in `@add_arg_table!`\n* `opt1` argument type, begin unspecified, defaults to `Any`, but in practice it's parsed as a\n  string (e.g. `\"2+2\"`)\n* `opt2` instead has `Int` argument type, so `\"4\"` will be parsed and converted to an integer,\n  an error is emitted if the conversion fails\n* positional arguments can be passed in between options\n* long options can be passed in abbreviated form (e.g. `--flag` instead of `--flag1`) as long as\n  there's no ambiguity\n\nMore examples can be found in the `examples` directory, and the complete documentation in the\nmanual pages.\n\n## Contents\n\n```@contents\nPages = [\n  \"parse_args.md\",\n  \"settings.md\",\n  \"arg_table.md\",\n  \"import.md\",\n  \"conflicts.md\",\n  \"custom.md\",\n  \"details.md\"\n]\n```\n"
  },
  {
    "path": "docs/src/parse_args.md",
    "content": "# The `parse_args` function\n\n```@docs\nparse_args\n```\n\n"
  },
  {
    "path": "docs/src/settings.md",
    "content": "# Settings\n\n```@docs\nArgParseSettings\n@project_version\n```\n"
  },
  {
    "path": "examples/argparse_example1.jl",
    "content": "# example 1: minimal options/arguments, auto-generated help/version\n\nusing ArgParse\n\nfunction main(args)\n\n    # initialize the settings (the description is for the help screen)\n    s = ArgParseSettings(description = \"Example 1 for argparse.jl: minimal usage.\")\n\n    @add_arg_table! s begin\n        \"--opt1\"               # an option (will take an argument)\n        \"--opt2\", \"-o\"         # another option, with short form\n        \"arg1\"                 # a positional argument\n    end\n\n    parsed_args = parse_args(s) # the result is a Dict{String,Any}\n    println(\"Parsed args:\")\n    for (key,val) in parsed_args\n        println(\"  $key  =>  $(repr(val))\")\n    end\nend\n\nmain(ARGS)\n"
  },
  {
    "path": "examples/argparse_example2.jl",
    "content": "# example 2: add some flags and the help lines for options\n\nusing ArgParse\n\nfunction main(args)\n\n    s = ArgParseSettings(\"Example 2 for argparse.jl: \" *  # description\n                         \"flags, options help, \" *\n                         \"required arguments.\")\n\n    @add_arg_table! s begin\n        \"--opt1\"\n            help = \"an option\"     # used by the help screen\n        \"--opt2\", \"-o\"\n            action = :store_true   # this makes it a flag\n            help = \"a flag\"\n        \"arg1\"\n            help = \"an argument\"\n            required = true        # makes the argument mandatory\n    end\n\n    parsed_args = parse_args(args, s)\n    println(\"Parsed args:\")\n    for (key,val) in parsed_args\n        println(\"  $key  =>  $(repr(val))\")\n    end\nend\n\nmain(ARGS)\n"
  },
  {
    "path": "examples/argparse_example3.jl",
    "content": "# example 3: version information, default values, options with\n#            types and variable number of arguments\n\nusing ArgParse\n\nfunction main(args)\n\n    s = ArgParseSettings(\"Example 3 for argparse.jl: \" *\n                         \"version info, default values, \" *\n                         \"options with types, variable \" *\n                         \"number of arguments.\",\n                         version = \"Version 1.0\", # version info\n                         add_version = true)      # audo-add version option\n\n    @add_arg_table! s begin\n        \"--opt1\"\n            nargs = '?'              # '?' means optional argument\n            arg_type = Int           # only Int arguments allowed\n            default = 0              # this is used when the option is not passed\n            constant = 1             # this is used if --opt1 is paseed with no argument\n            help = \"an option\"\n        \"--karma\", \"-k\"\n            action = :count_invocations  # increase a counter each time the option is given\n            help = \"increase karma\"\n        \"arg1\"\n            nargs = 2                        # eats up two arguments; puts the result in a Vector\n            help = \"first argument, two \" *\n                   \"entries at once\"\n            required = true\n        \"arg2\"\n            nargs = '*'                            # eats up as many arguments as possible before an option\n            default = Any[\"no_arg_given\"]          # since the result will be a Vector{Any}, the default must\n                                                   # also be (or it can be [] or nothing)\n            help = \"second argument, eats up \" *\n                   \"as many items as possible \" *\n                   \"before an option\"\n    end\n\n    parsed_args = parse_args(args, s)\n    println(\"Parsed args:\")\n    for (key,val) in parsed_args\n        println(\"  $key  =>  $(repr(val))\")\n    end\nend\n\nmain(ARGS)\n"
  },
  {
    "path": "examples/argparse_example4.jl",
    "content": "# example 4: dest_name, metavar, range_tester, alternative\n#            actions, epilog with examples\n\nusing ArgParse\n\nfunction main(args)\n\n    s = ArgParseSettings(\"Example 4 for argparse.jl: \" *\n                         \"more tweaking of the arg fields: \" *\n                         \"dest_name, metvar, range_tested, \" *\n                         \"alternative actions.\")\n\n    @add_arg_table! s begin\n        \"--opt1\"\n            action = :append_const   # appends 'constant' to 'dest_name'\n            arg_type = String        # the only utility of this is restricting the dest array type\n            constant = \"O1\"\n            dest_name = \"O_stack\"    # this changes the destination\n            help = \"append O1\"\n        \"--opt2\"\n            action = :append_const\n            arg_type = String\n            constant = \"O2\"\n            dest_name = \"O_stack\"    # same dest_name as opt1, different constant\n            help = \"append O2\"\n        \"-k\"\n            action = :store_const    # stores constant if given, default otherwise\n            default = 0\n            constant = 42\n            help = \"provide the answer\"\n        \"--awkward-option\"\n            nargs = '+'                         # eats up as many argument as found (at least 1)\n            action = :append_arg                # argument chunks are appended when the option is\n                                                # called repeatedly\n            arg_type = String\n            dest_name = \"awk\"\n            range_tester = (x->x==\"X\"||x==\"Y\")  # each argument must be either \"X\" or \"Y\"\n            metavar = \"XY\"\n            help = \"either X or Y; all XY's are \" *\n                   \"stored in chunks\"\n    end\n\n    # we add an epilog and provide usage examples, also demonstrating\n    # how to have some control on the formatting: we use additional '\\n' at\n    # the end of lines to force newlines, and '\\ua0' to put non-breakable spaces.\n    # Non-breakable spaces are not removed and are not used to split lines; they\n    # will be substituted with spaces in the final output.\n    s.epilog = \"\"\"\n        examples:\\n\n        \\n\n        \\ua0\\ua0$(basename(Base.source_path())) --opt1 --opt2 --opt2 -k\\n\n        \\n\n        \\ua0\\ua0$(basename(Base.source_path())) --awkward X X --opt1 --awkward X Y X --opt2\\n\n        \\n\n        The first form takes option 1 once, than option 2, then activates the answer flag,\n        while the second form takes only option 1 and then 2, and intersperses them with \"X\\ua0X\"\n        and \"X\\ua0Y\\ua0X\" groups, for no particular reason.\n        \"\"\"\n\n    # the epilog section will be displayed like this in the help screen:\n    #\n    #     examples:\n    #\n    #       argparse_example4.jl --opt1 --opt2 --opt2 -kkkkk\n    #\n    #       argparse_example4.jl --awkward X X --opt1 --awkward X Y X --opt2\n    #\n    #     The first form takes option 1 once, than option 2, then activates the\n    #     answer flag, while the second form takes only option 1 and then 2, and\n    #     intersperses them with \"X X\" and \"X Y X\" groups, for no particular\n    #     reason.\n\n    parsed_args = parse_args(args, s)\n    println(\"Parsed args:\")\n    for (key,val) in parsed_args\n        println(\"  $key  =>  $(repr(val))\")\n    end\nend\n\nmain(ARGS)\n"
  },
  {
    "path": "examples/argparse_example5.jl",
    "content": "# example 5: manual help/version, import another parser\n\nusing ArgParse\n\nfunction main(args)\n\n    s0 = ArgParseSettings()  # a \"parent\" structure e.g. one with some useful set of rules\n                             # which we want to extend\n\n    # So we just add a simple table\n    @add_arg_table! s0 begin\n        \"--parent-flag\", \"-o\"\n            action=>\"store_true\"\n            help=>\"parent flag\"\n        \"--flag\"\n            action=>\"store_true\"\n            help=>\"another parent flag\"\n        \"parent-argument\"\n            help = \"parent argument\"\n    end\n\n    s = ArgParseSettings(\"Example 5 for argparse.jl: \" *\n                         \"importing another parser, \" *\n                         \"manual help and version.\",\n                         add_help = false,           # disable auto-add of --help option\n                         version = \"Version 1.0\")    # we set the version info, but --version won't be added\n\n    import_settings!(s, s0)      # now s has all of s0 arguments (except help/version)\n\n    s.error_on_conflict = false  # do not error-out when trying to override an option\n\n    @add_arg_table! s begin\n        \"-o\"                       # this will partially override s0's --parent-flag\n            action = :store_true\n            help = \"child flag\"\n        \"--flag\"                   # this will fully override s0's --flag\n            action = :store_true\n            help = \"another child flag\"\n        \"-?\", \"--HELP\", \"--¡ḧëļṕ\"                # (almost) all characters allowed\n            action = :show_help                  # will invoke the help generator\n            help = \"this will help you\"\n        \"-v\", \"--VERSION\"\n            action = :show_version               # will show version information\n            help = \"show version information\" *\n                   \"and exit\"\n    end\n\n    parsed_args = parse_args(args, s)\n    println(\"Parsed args:\")\n    for (key,val) in parsed_args\n        println(\"  $key  =>  $(repr(val))\")\n    end\nend\n\nmain(ARGS)\n"
  },
  {
    "path": "examples/argparse_example6.jl",
    "content": "# example 6: commands & subtables\n\nusing ArgParse\n\nfunction main(args)\n\n    s = ArgParseSettings(\"Example 6 for argparse.jl: \" *\n                         \"commands and their associated sub-tables.\")\n\n    @add_arg_table! s begin\n        \"run\"\n            action = :command        # adds a command which will be read from an argument\n            help = \"start running mode\"\n        \"jump\", \"ju\", \"J\"            # another one, this one has two aliases\n            action = :command\n            help = \"start jumping mode\"\n    end\n\n    @add_arg_table! s[\"run\"] begin    # add command arg_table: same as usual, but invoked on s[\"cmd\"]\n        \"--speed\"\n            arg_type = Float64\n            default = 10.\n            help = \"running speed, in Å/month\"\n    end\n\n    s[\"jump\"].description = \"Jump mode for example 6\"  # this is how settings are tweaked\n                                                       # for commands\n    s[\"jump\"].commands_are_required = false            # this makes the sub-commands optional\n    s[\"jump\"].autofix_names = true                     # this uses dashes in long options, underscores\n                                                       # in auto-generated dest_names\n\n    @add_arg_table! s[\"jump\"] begin\n        \"--higher\"\n            action = :store_true\n            help = \"enhance jumping\"\n        \"--somersault\"\n            action = :command        # this adds a sub-command (passed via an option instead)\n            dest_name = \"som\"        # flag commands can set a dest_name\n            help = \"somersault jumping mode\"\n        \"--clap-feet\"                # dest_name will be \"clap_feet\" (see the \"autofix_names\" settings\")\n            action = :command\n            help = \"clap feet jumping mode\"\n    end\n\n    s[\"jump\"][\"som\"].description = \"Somersault jump \" *  # this is how settings are tweaked\n                                   \"mode for example 6\"  # for sub-commands\n\n    s[\"jump\"][\"clap_feet\"].description = \"Clap-feet jump \" *  # notice the underscore in the name\n                                         \"mode for example 6\"\n\n    parsed_args = parse_args(args, s)\n    println(\"Parsed args:\")\n    for (key,val) in parsed_args\n        println(\"  $key  =>  $(repr(val))\")\n    end\n    println()\n\n    # parsed_args will have a special field \"%COMMAND%\"\n    # which will hold the executed command name (or 'nothing')\n    println(\"Command: \", parsed_args[\"%COMMAND%\"])\n\n    # thus, the command args are in parsed_args[parsed_args[\"%COMMAND%]]\n    println(\"Parsed command args:\")\n    command_args = parsed_args[parsed_args[\"%COMMAND%\"]]\n    for (key,val) in command_args\n        println(\"  $key  =>  $(repr(val))\")\n    end\nend\n\nmain(ARGS)\n"
  },
  {
    "path": "examples/argparse_example7.jl",
    "content": "# example 7: argument groups\n\nusing ArgParse\n\nfunction main(args)\n\n    s = ArgParseSettings(\"Example 7 for argparse.jl: \" *\n                         \"argument groups.\")\n\n    add_arg_group!(s, \"stack options\") # add a group and sets it as the default\n    @add_arg_table! s begin            # all options (and arguments) in this table\n                                       # will be assigned to the newly added group\n        \"--opt1\"\n            action = :append_const\n            arg_type = String\n            constant = \"O1\"\n            dest_name = \"O_stack\"\n            help = \"append O1 to the stack\"\n        \"--opt2\"\n            action = :append_const\n            arg_type = String\n            constant = \"O2\"\n            dest_name = \"O_stack\"\n            help = \"append O2 to the stack\"\n    end\n\n    add_arg_group!(s, \"weird options\", \"weird\") # another group, this time with a tag which allows\n                                                # to refer to it\n\n    set_default_arg_group!(s, \"weird\") # set the default group (useless here, since we just added it)\n\n    @add_arg_table! s begin\n        \"--awkward-option\"\n            nargs = '+'\n            action = :append_arg\n            dest_name = \"awk\"\n            arg_type = String\n            range_tester = (x->x==\"X\"||x==\"Y\")\n            metavar = \"XY\"\n            help = \"either X or Y; all XY's are \" *\n                   \"stored in chunks\"\n    end\n\n    set_default_arg_group!(s) # reset the default arg group (which means arguments\n                              # are automatically assigned to commands/options/pos.args\n                              # groups)\n    @add_arg_table! s begin\n        \"-k\"\n            action = :store_const\n            default = 0\n            constant = 42\n            help = \"provide the answer\"\n        \"--şİłłÿ\"\n            action = :store_true\n            help = \"an option with a silly name\"\n            group = \"weird\"   # this overrides the default group: this option\n                              # will be grouped together with --awkward-option\n    end\n\n    parsed_args = parse_args(args, s)\n    println(\"Parsed args:\")\n    for (key,val) in parsed_args\n        println(\"  $key  =>  $(repr(val))\")\n    end\nend\n\nmain(ARGS)\n"
  },
  {
    "path": "examples/argparse_example8.jl",
    "content": "# example 8: mutually exculsive and required groups\n\nusing ArgParse\n\nfunction main(args)\n\n    s = ArgParseSettings(\"Example 8 for argparse.jl: \" *\n                         \"mutually exclusive and requiredd groups.\")\n\n    add_arg_group!(s, \"Mutually exclusive options\", exclusive=true)\n    @add_arg_table! s begin\n        \"--maybe\", \"-M\"\n            action = :store_true\n            help = \"maybe...\"\n        \"--maybe-not\", \"-N\"\n            action = :store_true\n            help = \"maybe not...\"\n    end\n\n    add_arg_group!(s, \"Required mutually exclusive options\", exclusive=true, required=true)\n    @add_arg_table! s begin\n        \"--either\", \"-E\"\n            action = :store_true\n            help = \"choose the `either` option\"\n        \"--or\", \"-O\"\n            action = :store_arg\n            arg_type = Int\n            help = \"set the `or` option\"\n    end\n\n    add_arg_group!(s, \"Required arguments\", required=true)\n    @add_arg_table! s begin\n        \"--enhance\", \"-+\"\n            action = :store_const\n            default = 0\n            constant = 42\n            help = \"set the enhancement option\"\n        \"arg1\"\n            nargs = 2                        # eats up two arguments; puts the result in a Vector\n            help = \"first argument, two \" *\n                   \"entries at once\"\n    end\n\n    parsed_args = parse_args(args, s)\n    println(\"Parsed args:\")\n    for (key,val) in parsed_args\n        println(\"  $key  =>  $(repr(val))\")\n    end\nend\n\nmain(ARGS)\n"
  },
  {
    "path": "src/ArgParse.jl",
    "content": "\"\"\"\n    ArgParse\n\nThis module allows the creation of user-friendly command-line interfaces to Julia programs:\nthe program defines which arguments, options and sub-commands it accepts, and the `ArgParse` module\ndoes the actual parsing, issues errors when the input is invalid, and automatically generates help\nand usage messages.\n\nUsers familiar with Python's `argparse` module will find many similarities, but some important\ndifferences as well.\n\"\"\"\nmodule ArgParse\n\nimport TextWrap\n\nif isdefined(Base, :Experimental) && isdefined(Base.Experimental, Symbol(\"@compiler_options\"))\n    @eval Base.Experimental.@compiler_options compile=min optimize=0 infer=false\nend\n\nexport\n# types\n    ArgParseSettings,\n    ArgParseSettingsError,\n    ArgParseError,\n\n# functions & macros\n    add_arg_table!,\n    @add_arg_table!,\n    add_arg_group!,\n    set_default_arg_group!,\n    import_settings!,\n    usage_string,\n    parse_args,\n    @project_version\n\nimport Base: show, getindex, setindex!, haskey\n\n@nospecialize # use only declared type signatures, helps with compile time\n\ninclude(\"common.jl\")\ninclude(\"settings.jl\")\ninclude(\"parsing.jl\")\ninclude(\"deprecated.jl\")\n\nend # module ArgParse\n"
  },
  {
    "path": "src/common.jl",
    "content": "## Some common functions, constants, macros\n\n# auxiliary functions/constants\nfound_a_bug() = error(\"you just found a bug in the ArgParse module, please report it.\")\nconst nbspc = '\\u00a0'\nconst nbsps = \"$nbspc\"\nprintln_unnbsp(io::IO, args...) = println(io, map(s->replace(s, nbspc => ' '), args)...)\n\nmacro defaults(opts, ex)\n    @assert ex.head == :block\n    lines = filter(x->!(x isa LineNumberNode), ex.args)\n    @assert all(x->Meta.isexpr(x, :(=)), lines)\n\n    opts = esc(opts)\n    # Transform the opts array into a Dict\n    exret = :($opts = Dict{Symbol,Any}($opts))\n    # Initialize the checks\n    found = esc(gensym(\"found\"))\n    exret = quote\n        $exret\n        $found = Dict{Symbol,Bool}(k => false for (k,v) in $opts)\n    end\n\n    for y in lines\n        sym = y.args[1]\n        qsym = Expr(:quote, sym)\n        exret = quote\n            $exret\n            if haskey($opts, $qsym)\n                $(esc(sym)) = $opts[$qsym]\n                $found[$qsym] = true\n            else\n                $(esc(y))\n            end\n        end\n    end\n    exret = quote\n        $exret\n        for (k,v) in $found\n            v || serror(\"unknown description field: $k\")\n        end\n    end\n    exret\nend\n\n"
  },
  {
    "path": "src/deprecated.jl",
    "content": "\n@deprecate add_arg_table add_arg_table!\n@deprecate import_settings(settings, other) import_settings!(settings, other)\n@deprecate import_settings(settings, other, ao) import_settings!(settings, other; args_only=ao)\n@deprecate add_arg_group(args...; kw...) add_arg_group!(args...; kw...)\n@deprecate set_default_arg_group set_default_arg_group!\n\n# The Base.@deprecate macro doesn't work with macros\n# Here's an attempt at mimicking most of what that does\n# and deprecate @add_arg_table -> @add_arg_table!\nusing Base: JLOptions, CoreLogging\nusing Logging: @logmsg\n\nfunction callframe(st, name)\n    found = false\n    for sf in st\n        sf == StackTraces.UNKNOWN && continue\n        if found && sf.func == Symbol(\"top-level scope\")\n            return sf\n        end\n        sf.func == name && (found = true)\n    end\n    return StackTraces.UNKNOWN\nend\n\nexport @add_arg_table\nmacro add_arg_table(s, x...)\n    opts = JLOptions()\n    msg = \"`@add_arg_table` is deprecated, use `@add_arg_table!` instead\"\n    opts.depwarn == 2 && throw(ErrorException(msg))\n    deplevel = opts.depwarn == 1 ? CoreLogging.Warn : CoreLogging.BelowMinLevel\n    st = stacktrace()\n    caller = callframe(st, Symbol(\"@add_arg_table\"))\n    @logmsg(deplevel, msg,\n            _file = String(caller.file),\n            _line = caller.line,\n            _group = :depwarn,\n            maxlog = 1)\n\n    return _add_arg_table!(s, x...)\nend\n"
  },
  {
    "path": "src/parsing.jl",
    "content": "## All types, functions and constants related to the actual process of\n## parsing the arguments\n\n# ArgParseError\nstruct ArgParseError <: Exception\n    text::AbstractString\nend\n\nargparse_error(x...) = throw(ArgParseError(string(x...)))\n\n# parsing checks\nfunction test_range(range_tester::Function, arg, name::AbstractString)\n    local rng_chk::Bool\n    try\n        rng_chk = range_tester(arg)\n    catch\n        rng_chk = false\n    end\n    rng_chk || argparse_error(\"out of range input for $name: $arg\")\n    return\nend\n\nfunction test_exclusive_groups!(exc_groups::Dict{ArgParseGroup,AbstractString},\n                                settings::ArgParseSettings,\n                                f::ArgParseField,\n                                name::AbstractString)\n    arg_group = get_group(f.group, f, settings)\n    if haskey(exc_groups, arg_group)\n        prev_id = exc_groups[arg_group]\n        if isempty(prev_id)\n            exc_groups[arg_group] = idstring(f)\n        elseif prev_id != idstring(f)\n            argparse_error(\"option $name not allowed with $prev_id\")\n        end\n    end\n    return\nend\n\nfunction test_required_args(settings::ArgParseSettings, found_args::Set{AbstractString})\n    req_groups = Dict{ArgParseGroup,Bool}(g=>false for g in settings.args_groups if g.required)\n    fields = settings.args_table.fields\n    for f in fields\n        found = idstring(f) ∈ found_args\n        !is_cmd(f) && f.required && !found &&\n            argparse_error(\"required $(idstring(f)) was not provided\")\n        found && (req_groups[get_group(f.group, f, settings)] = true)\n    end\n    for (g,found) in req_groups\n        found && continue\n        ids = String[idstring(f) for f in fields if get_group(f.group, f, settings) ≡ g]\n        argparse_error(\"one of these is required: \" * join(ids, \", \"))\n    end\n    return true\nend\n\nfunction check_settings_can_use_symbols(settings::ArgParseSettings)\n    args_table = settings.args_table\n    if !isempty(args_table.subsettings)\n        for f in args_table.fields\n            if f.dest_name == string(scmd_dest_name)\n                serror(\"the dest_name $scmd_dest_name cannot be used with the as_symbols option\")\n            end\n        end\n        for subs in values(args_table.subsettings)\n            check_settings_can_use_symbols(subs)\n        end\n    end\n    settings.suppress_warnings && return true\n    for f in args_table.fields\n        if '-' in f.dest_name\n            @warn \"dest_name=$(f.dest_name) contains a hyphen; use the autofix_names=true setting to have it converted to an underscore\"\n        end\n    end\n    return true\nend\n\n# parsing aux functions\nfunction parse_item_wrapper(::Type{T}, x::AbstractString) where {T}\n    local r::T\n    try\n        r = parse_item(T, x)\n    catch err\n        argparse_error(\"\"\"\n            invalid argument: $x (conversion to type $T failed; you may need to overload\n                              ArgParse.parse_item; the error was: $err)\"\"\")\n    end\n    return r\nend\n\nparse_item(::Type{Any}, x::AbstractString) = x\nparse_item(::Type{T}, x::AbstractString) where {T<:Number} = parse(T, x)\nparse_item(::Type{T}, x::AbstractString) where {T} = applicable(convert, T, x) ? convert(T, x) : T(x)\n\nfunction parse_item_eval(::Type{T}, x::AbstractString) where {T}\n    local r::T\n    try\n        r = convert(T, eval(Meta.parse(x)))\n    catch err\n        argparse_error(\"\"\"\n            invalid argument: $x (must evaluate or convert to type $T;\n                              the error was: $err)\"\"\")\n    end\n    return r\nend\n\nconst number_regex =\n    r\"^[+-]?                                          # optional sign\n        (\n          0x[0-9a-fA-F](_?[0-9a-fA-F])*             | # hex\n          0o[0-7](_?[0-7])*                         | # oct\n          0b[01](_?[01])*                           | # bin\n          (                                           # float mantissa\n            [0-9](_?[0-9])*(\\.([0-9](_?[0-9])*)?)?  | #   start with digit\n            \\.[0-9](_?[0-9])*                         #   start with dot\n          )([eEf][-+]?[0-9]+)?                        # float optional exp\n        )\n      $\"x\n\nfunction looks_like_an_option(arg::AbstractString, settings::ArgParseSettings)\n    arg == \"-\" && return false\n    startswith(arg, \"--\") && return true\n    startswith(arg, '-') || return false\n    # begins with '-'\n    # check if it's a number:\n    occursin(number_regex, arg) || return true\n    # looks like a number; but is it overridden by an option?\n    d = arg[2:2]\n    for a in settings.args_table.fields, s in a.short_opt_name\n        s == d && return true\n    end\n    # it's a number\n    return false\nend\n\nfunction usage_string(settings::ArgParseSettings)\n    isempty(settings.usage) || return settings.usage\n\n    usage_pre = \"usage: \" * (isempty(settings.prog) ? \"<PROGRAM>\" : settings.prog)\n\n    lc_len_limit = settings.help_alignment_width\n\n    cmd_lst = String[]\n    pos_lst = String[]\n    opt_lst = String[]\n    exc_lst = Dict{String,Tuple{Bool,Vector{String}}}()\n    for f in settings.args_table.fields\n        arg_group = get_group(f.group, f, settings)\n        if arg_group.exclusive\n            (is_cmd(f) || is_arg(f)) && found_a_bug()\n            _, tgt_opt_lst = get!(exc_lst, arg_group.name, (arg_group.required, String[]))\n        else\n            tgt_opt_lst = opt_lst\n        end\n        if is_cmd(f)\n            if !isempty(f.short_opt_name)\n                idstr = \"-\" * f.short_opt_name[1]\n            elseif !isempty(f.long_opt_name)\n                idstr = \"--\" * f.long_opt_name[1]\n            else\n                idstr = f.metavar\n            end\n            push!(cmd_lst, idstr)\n        elseif is_arg(f)\n            bra_pre, bra_post = f.required ? (\"\",\"\") : (\"[\",\"]\")\n            if isa(f.nargs.desc, Int)\n                if f.metavar isa AbstractString\n                    arg_str = join(repeat([f.metavar], f.nargs.desc), nbsps)\n                else\n                    found_a_bug()\n                end\n            elseif f.nargs.desc == :A\n                arg_str = f.metavar\n            elseif f.nargs.desc == :?\n                found_a_bug()\n            elseif f.nargs.desc == :* || f.nargs.desc == :R || f.nargs.desc == :+\n                arg_str = f.metavar * \"...\"\n            else\n                found_a_bug()\n            end\n            push!(pos_lst, bra_pre * arg_str * bra_post)\n        else\n            bra_pre, bra_post = (f.required || arg_group.exclusive) ? (\"\",\"\") : (\"[\",\"]\")\n            if !isempty(f.short_opt_name)\n                opt_str1 = \"-\" * f.short_opt_name[1]\n            else\n                opt_str1 = \"--\" * f.long_opt_name[1]\n            end\n            if is_flag(f)\n                opt_str2 = \"\"\n            else\n                if f.nargs.desc isa Int\n                    if f.metavar isa AbstractString\n                        opt_str2 = string(ntuple(i->(nbsps * f.metavar), f.nargs.desc)...)\n                    elseif f.metavar isa Vector\n                        opt_str2 = string(ntuple(i->(nbsps * f.metavar[i]), f.nargs.desc)...)\n                    else\n                        found_a_bug()\n                    end\n                elseif f.nargs.desc == :A\n                    opt_str2 = nbsps * f.metavar\n                elseif f.nargs.desc == :?\n                    opt_str2 = nbsps * \"[\" * f.metavar * \"]\"\n                elseif f.nargs.desc == :* || f.nargs.desc == :R\n                    opt_str2 = nbsps * \"[\" * f.metavar * \"...]\"\n                elseif f.nargs.desc == :+\n                    opt_str2 = nbsps * f.metavar * nbsps * \"[\" * f.metavar * \"...]\"\n                else\n                    found_a_bug()\n                end\n            end\n            new_opt = bra_pre * opt_str1 * opt_str2 * bra_post\n            push!(tgt_opt_lst, new_opt)\n        end\n    end\n    excl_str = \"\"\n    for (req,lst) in values(exc_lst)\n        pre, post = req ? (\"{\",\"}\") : (\"[\",\"]\")\n        excl_str *= \" \" * pre * join(lst, \" | \") * post\n    end\n    if isempty(opt_lst)\n        optl_str = \"\"\n    else\n        optl_str = \" \" * join(opt_lst, \" \")\n    end\n    if isempty(pos_lst)\n        posl_str = \"\"\n    else\n        posl_str = \" \" * join(pos_lst, \" \")\n    end\n    if isempty(cmd_lst)\n        cmdl_str = \"\"\n    else\n        bra_pre, bra_post = settings.commands_are_required ? (\"{\",\"}\") :  (\"[\",\"]\")\n        cmdl_str = \" \" * bra_pre * join(cmd_lst, \"|\") * bra_post\n    end\n\n    usage_len = length(usage_pre) + 1\n\n    str_nonwrapped = usage_pre * excl_str * optl_str * posl_str * cmdl_str\n    str_wrapped = TextWrap.wrap(str_nonwrapped, break_long_words = false, break_on_hyphens = false,\n                                subsequent_indent = min(usage_len, lc_len_limit),\n                                width = settings.help_width)\n\n\n    out_str = replace(str_wrapped, nbspc => ' ')\n    return out_str\nend\n\nfunction string_compact(x...)\n    io = IOBuffer()\n    show(IOContext(io, :compact=>true), x...)\n    return String(take!(io))\nend\n\nfunction gen_help_text(arg::ArgParseField, settings::ArgParseSettings)\n    is_flag(arg) && return arg.help\n\n    pre = isempty(arg.help) ? \"\" : \" \"\n    type_str = \"\"\n    default_str = \"\"\n    const_str = \"\"\n    alias_str = \"\"\n    if !is_command_action(arg.action)\n        if arg.arg_type ≠ Any && !(arg.arg_type <: AbstractString)\n            type_str = pre * \"(type: \" * string_compact(arg.arg_type)\n        end\n        if arg.default ≢ nothing && !isequal(arg.default, [])\n            mid = isempty(type_str) ? \" (\" : \", \"\n            default_str = mid * \"default: \" * string_compact(arg.default)\n        end\n        if arg.nargs.desc == :?\n            mid = isempty(type_str) && isempty(default_str) ? \" (\" : \", \"\n            const_str = mid * \"without arg: \" * string_compact(arg.constant)\n        end\n    else\n        is_arg(arg) || found_a_bug()\n        if !isempty(arg.cmd_aliases)\n            alias_str = pre * \"(aliases: \" * join(arg.cmd_aliases, \", \")\n        end\n    end\n    post = all(isempty, (type_str, default_str, const_str, alias_str)) ? \"\" : \")\"\n    return arg.help * type_str * default_str * const_str * alias_str * post\nend\n\nfunction print_group(io::IO, lst::Vector, desc::AbstractString, lc_usable_len::Int, lc_len::Int,\n                     lmargin::AbstractString, rmargin::AbstractString, sindent::AbstractString,\n                     width::Int)\n    isempty(lst) && return\n    println(io, desc, \":\")\n    for l in lst\n        l1len = length(l[1])\n        if l1len ≤ lc_usable_len\n            rfill = \" \"^(lc_len - l1len)\n            ll_nonwrapped = l[1] * rfill * rmargin * l[2]\n            ll_wrapped = TextWrap.wrap(ll_nonwrapped, break_long_words = false, break_on_hyphens = false,\n                                       initial_indent = lmargin, subsequent_indent = sindent, width = width)\n            println_unnbsp(io, ll_wrapped)\n        else\n            println_unnbsp(io, lmargin, l[1])\n            l2_wrapped = TextWrap.wrap(l[2], break_long_words = false, break_on_hyphens = false,\n                                       initial_indent = sindent, subsequent_indent = sindent, width = width)\n            println_unnbsp(io, l2_wrapped)\n        end\n    end\n    println(io)\nend\n\nshow_help(settings::ArgParseSettings; kw...) = show_help(stdout, settings; kw...)\n\nfunction show_help(io::IO, settings::ArgParseSettings; exit_when_done = !isinteractive())\n\n    lc_len_limit = settings.help_alignment_width\n    lc_left_indent = 2\n    lc_right_margin = 2\n\n    lc_usable_len = lc_len_limit - lc_left_indent - lc_right_margin\n    max_lc_len = 0\n\n    usage_str = usage_string(settings)\n\n    group_lists = Dict{AbstractString,Vector{Any}}()\n    for ag in settings.args_groups\n        group_lists[ag.name] = Any[]\n    end\n    for f in settings.args_table.fields\n        dest_lst = group_lists[f.group]\n        if is_arg(f)\n            push!(dest_lst, Any[f.metavar, gen_help_text(f, settings)])\n            max_lc_len = max(max_lc_len, length(f.metavar))\n        else\n            opt_str1 = join([[\"-\"*x for x in f.short_opt_name];\n                             [\"--\"*x for x in f.long_opt_name]],\n                            \", \")\n            if is_flag(f)\n                opt_str2 = \"\"\n            else\n                if f.nargs.desc isa Int\n                    if f.metavar isa AbstractString\n                        opt_str2 = string(ntuple(i->(nbsps * f.metavar), f.nargs.desc)...)\n                    elseif isa(f.metavar, Vector)\n                        opt_str2 = string(ntuple(i->(nbsps * f.metavar[i]), f.nargs.desc)...)\n                    else\n                        found_a_bug()\n                    end\n                elseif f.nargs.desc == :A\n                    opt_str2 = nbsps * f.metavar\n                elseif f.nargs.desc == :?\n                    opt_str2 = nbsps * \"[\" * f.metavar * \"]\"\n                elseif f.nargs.desc == :* || f.nargs.desc == :R\n                    opt_str2 = nbsps * \"[\" * f.metavar * \"...]\"\n                elseif f.nargs.desc == :+\n                    opt_str2 = nbsps * f.metavar * nbsps * \"[\" * f.metavar * \"...]\"\n                else\n                    found_a_bug()\n                end\n            end\n            new_opt = Any[opt_str1 * opt_str2, gen_help_text(f, settings)]\n            push!(dest_lst, new_opt)\n            max_lc_len = max(max_lc_len, length(new_opt[1]))\n        end\n    end\n\n    lc_len = min(lc_usable_len, max_lc_len)\n    lmargin = \" \"^lc_left_indent\n    rmargin = \" \"^lc_right_margin\n\n    sindent = lmargin * \" \"^lc_len * rmargin\n\n    println(io, usage_str)\n    println(io)\n    show_message(io, settings.description, settings.preformatted_description, settings.help_width)\n\n    for ag in settings.args_groups\n        print_group(io, group_lists[ag.name], ag.desc, lc_usable_len, lc_len,\n                    lmargin, rmargin, sindent, settings.help_width)\n    end\n\n    show_message(io, settings.epilog, settings.preformatted_epilog, settings.help_width)\n    exit_when_done && exit(0)\n    return\nend\n\nfunction show_message(io::IO, message::AbstractString, preformatted::Bool, width::Int)\n    if !isempty(message)\n        if preformatted\n            print(io, message)\n        else\n            for l in split(message, \"\\n\\n\")\n                message_wrapped = TextWrap.wrap(l, break_long_words = false, break_on_hyphens = false, width = width)\n                println_unnbsp(io, message_wrapped)\n            end\n        end\n        println(io)\n    end\nend\n\nshow_version(settings::ArgParseSettings; kw...) = show_version(stdout, settings; kw...)\n\nfunction show_version(io::IO, settings::ArgParseSettings; exit_when_done = !isinteractive())\n    println(io, settings.version)\n    exit_when_done && exit(0)\n    return\nend\n\nhas_cmd(settings::ArgParseSettings) = any(is_cmd, settings.args_table.fields)\n\n# parse_args & friends\nfunction default_handler(settings::ArgParseSettings, err, err_code::Int = 1)\n    isinteractive() ? debug_handler(settings, err) : cmdline_handler(settings, err, err_code)\nend\n\nfunction cmdline_handler(settings::ArgParseSettings, err, err_code::Int = 1)\n    println(stderr, err.text)\n    println(stderr, usage_string(settings))\n    exit(err_code)\nend\n\nfunction debug_handler(settings::ArgParseSettings, err)\n    rethrow(err)\nend\n\nparse_args(settings::ArgParseSettings; kw...) = parse_args(ARGS, settings; kw...)\n\n\"\"\"\n    parse_args([args,] settings; as_symbols::Bool = false)\n\nThis is the central function of the `ArgParse` module. It takes a `Vector` of arguments and an\n[`ArgParseSettings`](@ref) object, and returns a `Dict{String,Any}`. If `args` is not provided, the\nglobal variable `ARGS` will be used.\n\nWhen the keyword argument `as_symbols` is `true`, the function will return a `Dict{Symbol,Any}`\ninstead.\n\nThe returned `Dict` keys are defined (possibly implicitly) in `settings`, and their associated\nvalues are parsed from `args`. Special keys are used for more advanced purposes; at the moment, one\nsuch key exists: `%COMMAND%` (`_COMMAND_` when using `as_symbols=true`; see the [Commands](@ref)\nsection).\n\nArguments are parsed in sequence and matched against the argument table in `settings` to determine\nwhether they are long options, short options, option arguments or positional arguments:\n\n  * long options begin with a double dash `\"--\"`; if a `'='` character is found, the remainder is\n    the option argument; therefore, `[\"--opt=arg\"]` and `[\"--opt\", \"arg\"]` are equivalent if `--opt`\n    takes at least one argument. Long options can be abbreviated (e.g. `--opt` instead of\n    `--option`) as long as there is no ambiguity.\n  * short options begin with a single dash `\"-\"` and their name consists of a single character; they\n    can be grouped together (e.g. `[\"-x\", \"-y\"]` can become `[\"-xy\"]`), but in that case only the\n    last option in the group can take an argument (which can also be grouped, e.g.\n    `[\"-a\", \"-f\", \"file.txt\"]` can be passed as `[\"-affile.txt\"]` if `-a` does not take an argument\n    and `-f` does). The `'='` character can be used to separate option names from option arguments\n    as well (e.g. `-af=file.txt`).\n  * positional arguments are anything else; they can appear anywhere.\n\nThe special string `\"--\"` can be used to signal the end of all options; after that, everything is\nconsidered as a positional argument (e.g. if `args = [\"--opt1\", \"--\", \"--opt2\"]`, the parser will\nrecognize `--opt1` as a long option without argument, and `--opt2` as a positional argument).\n\nThe special string `\"-\"` is always parsed as a positional argument.\n\nThe parsing can stop early if a `:show_help` or `:show_version` action is triggered, or if a parsing\nerror is found.\n\nSome ambiguities can arise in parsing, see the [Parsing details](@ref) section for a detailed\ndescription of how they're solved.\n\"\"\"\nfunction parse_args(args_list::Vector, settings::ArgParseSettings; as_symbols::Bool = false)\n    as_symbols && check_settings_can_use_symbols(settings)\n    local parsed_args\n    try\n        parsed_args = parse_args_unhandled(args_list, settings)\n    catch err\n        err isa ArgParseError || rethrow()\n        settings.exc_handler(settings, err)\n    end\n    as_symbols && (parsed_args = convert_to_symbols(parsed_args))\n    return parsed_args\nend\n\nmutable struct ParserState\n    args_list::Vector\n    arg_delim_found::Bool\n    token::Union{AbstractString,Nothing}\n    token_arg::Union{AbstractString,Nothing}\n    arg_consumed::Bool\n    last_arg::Int\n    found_args::Set{AbstractString}\n    command::Union{AbstractString,Nothing}\n    truncated_shopts::Bool\n    abort::Bool\n    exc_groups::Dict{ArgParseGroup,AbstractString}\n    out_dict::Dict{String,Any}\n    function ParserState(args_list::Vector, settings::ArgParseSettings, truncated_shopts::Bool)\n        exc_groups = Dict{ArgParseGroup,AbstractString}(\n                g=>\"\" for g in settings.args_groups if g.exclusive)\n        out_dict = Dict{String,Any}()\n        for f in settings.args_table.fields\n            f.action ∈ (:show_help, :show_version) && continue\n            out_dict[f.dest_name] = deepcopy(f.default)\n        end\n        return new(deepcopy(args_list), false, nothing, nothing, false, 0, Set{AbstractString}(),\n                   nothing, truncated_shopts, false, exc_groups, out_dict)\n    end\nend\n\nfound_command(state::ParserState) = state.command ≢ nothing\nfunction parse_command_args!(state::ParserState, settings::ArgParseSettings)\n    cmd = state.command\n    haskey(settings, cmd) || argparse_error(\"unknown command: $cmd\")\n    #state.out_dict[cmd] = parse_args(state.args_list, settings[cmd])\n    try\n        state.out_dict[cmd] =\n            parse_args_unhandled(state.args_list, settings[cmd], state.truncated_shopts)\n    catch err\n        err isa ArgParseError || rethrow(err)\n        settings[cmd].exc_handler(settings[cmd], err)\n    finally\n        state.truncated_shopts = false\n    end\n    return state.out_dict[cmd]\nend\n\nfunction preparse!(c::Channel, state::ParserState, settings::ArgParseSettings)\n    args_list = state.args_list\n    while !isempty(args_list)\n        state.arg_delim_found && (put!(c, :pos_arg); continue)\n        arg = args_list[1]\n        if state.truncated_shopts\n            @assert arg[1] == '-'\n            looks_like_an_option(arg, settings) ||\n                argparse_error(\"illegal short options sequence after command: $arg\")\n            state.truncated_shopts = false\n        end\n        if arg == \"--\"\n            state.arg_delim_found = true\n            state.token = nothing\n            state.token_arg = nothing\n            popfirst!(args_list)\n            continue\n        elseif startswith(arg, \"--\")\n            eq = findfirst(isequal('='), arg)\n            if eq ≢ nothing\n                opt_name = arg[3:prevind(arg,eq)]\n                arg_after_eq = arg[nextind(arg,eq):end]\n            else\n                opt_name = arg[3:end]\n                arg_after_eq = nothing\n            end\n            isempty(opt_name) && argparse_error(\"illegal option: $arg\")\n            popfirst!(args_list)\n            state.token = opt_name\n            state.token_arg = arg_after_eq\n            put!(c, :long_option)\n        elseif looks_like_an_option(arg, settings)\n            shopts_lst = arg[2:end]\n            popfirst!(args_list)\n            state.token = shopts_lst\n            state.token_arg = nothing\n            put!(c, :short_option_list)\n        else\n            state.token = nothing\n            state.token_arg = nothing\n            put!(c, :pos_arg)\n        end\n    end\nend\n\n# faithful reproduction of Python 3.5.1 argparse.py\n# partially Copyright © 2001-2016 Python Software Foundation; All Rights Reserved\nfunction read_args_from_files(arg_strings, prefixes)\n    new_arg_strings = AbstractString[]\n\n    for arg_string in arg_strings\n        if isempty(arg_string) || arg_string[1] ∉ prefixes\n            # for regular arguments, just add them back into the list\n            push!(new_arg_strings, arg_string)\n        else\n            # replace arguments referencing files with the file content\n            open(arg_string[nextind(arg_string, 1):end]) do args_file\n                arg_strings = AbstractString[]\n                for arg_line in readlines(args_file)\n                    push!(arg_strings, rstrip(arg_line, '\\n'))\n                end\n                arg_strings = read_args_from_files(arg_strings, prefixes)\n                append!(new_arg_strings, arg_strings)\n            end\n        end\n    end\n\n    # return the modified argument list\n    return new_arg_strings\nend\n\nfunction parse_args_unhandled(args_list::Vector,\n                              settings::ArgParseSettings,\n                              truncated_shopts::Bool=false)\n    all(x->(x isa AbstractString), args_list) || error(\"malformed args_list\")\n    if !isempty(settings.fromfile_prefix_chars)\n        args_list = read_args_from_files(args_list, settings.fromfile_prefix_chars)\n    end\n\n    version_added = false\n    help_added = false\n\n    if settings.add_version\n        settings.add_version = false\n        add_arg_field!(settings, \"--version\",\n            action = :show_version,\n            help = \"show version information and exit\",\n            group = \"\"\n            )\n        version_added = true\n    end\n    if settings.add_help\n        settings.add_help = false\n        add_arg_field!(settings, [\"--help\", \"-h\"],\n            action = :show_help,\n            help = \"show this help message and exit\",\n            group = \"\"\n            )\n        help_added = true\n    end\n\n    state = ParserState(args_list, settings, truncated_shopts)\n    preparser = Channel(c->preparse!(c, state, settings))\n\n    try\n        for tag in preparser\n            if tag == :long_option\n                parse_long_opt!(state, settings)\n            elseif tag == :short_option_list\n                parse_short_opt!(state, settings)\n            elseif tag == :pos_arg\n                parse_arg!(state, settings)\n            else\n                found_a_bug()\n            end\n            state.abort && return nothing\n            found_command(state) && break\n        end\n        test_required_args(settings, state.found_args)\n        if found_command(state)\n            cmd_dict = parse_command_args!(state, settings)\n            cmd_dict ≡ nothing && return nothing\n        elseif settings.commands_are_required && has_cmd(settings)\n            argparse_error(\"no command given\")\n        end\n    catch err\n        rethrow()\n    finally\n        if help_added\n            pop!(settings.args_table.fields)\n            settings.add_help = true\n        end\n        if version_added\n            pop!(settings.args_table.fields)\n            settings.add_version = true\n        end\n    end\n\n    return state.out_dict\nend\n\n# common parse functions\nfunction parse1_flag!(state::ParserState, settings::ArgParseSettings, f::ArgParseField,\n                      has_arg::Bool, opt_name::AbstractString)\n    has_arg && argparse_error(\"option $opt_name takes no arguments\")\n    test_exclusive_groups!(state.exc_groups, settings, f, opt_name)\n    command = nothing\n    out_dict = state.out_dict\n    if f.action == :store_true\n        out_dict[f.dest_name] = true\n    elseif f.action == :store_false\n        out_dict[f.dest_name] = false\n    elseif f.action == :store_const\n        out_dict[f.dest_name] = f.constant\n    elseif f.action == :append_const\n        push!(out_dict[f.dest_name], f.constant)\n    elseif f.action == :count_invocations\n        out_dict[f.dest_name] += 1\n    elseif f.action == :command_flag\n        out_dict[f.dest_name] = f.constant\n        command = f.constant\n    elseif f.action == :show_help\n        show_help(settings, exit_when_done = settings.exit_after_help)\n        state.abort = true\n    elseif f.action == :show_version\n        show_version(settings, exit_when_done = settings.exit_after_help)\n        state.abort = true\n    end\n    state.command = command\n    return\nend\n\nfunction parse1_optarg!(state::ParserState, settings::ArgParseSettings, f::ArgParseField,\n                        rest, name::AbstractString)\n    args_list = state.args_list\n    arg_delim_found = state.arg_delim_found\n    out_dict = state.out_dict\n\n    test_exclusive_groups!(state.exc_groups, settings, f, name)\n\n    arg_consumed = false\n    parse_function = f.eval_arg ? parse_item_eval : parse_item_wrapper\n    command = nothing\n    is_multi_nargs(f.nargs) && (opt_arg = Array{f.arg_type}(undef, 0))\n    if f.nargs.desc isa Int\n        num::Int = f.nargs.desc\n        num > 0 || found_a_bug()\n        corr = (rest ≡ nothing) ? 0 : 1\n        if length(args_list) + corr < num\n            argparse_error(\"$name requires $num argument\", num > 1 ? \"s\" : \"\")\n        end\n        if rest ≢ nothing\n            a = parse_function(f.arg_type, rest)\n            test_range(f.range_tester, a, name)\n            push!(opt_arg, a)\n            arg_consumed = true\n        end\n        for i = (1+corr):num\n            a = parse_function(f.arg_type, popfirst!(args_list))\n            test_range(f.range_tester, a, name)\n            push!(opt_arg, a)\n        end\n    elseif f.nargs.desc == :A\n        if rest ≢ nothing\n            a = parse_function(f.arg_type, rest)\n            test_range(f.range_tester, a, name)\n            opt_arg = a\n            arg_consumed = true\n        else\n            isempty(args_list) && argparse_error(\"option $name requires an argument\")\n            a = parse_function(f.arg_type, popfirst!(args_list))\n            test_range(f.range_tester, a, name)\n            opt_arg = a\n        end\n    elseif f.nargs.desc == :?\n        if rest ≢ nothing\n            a = parse_function(f.arg_type, rest)\n            test_range(f.range_tester, a, name)\n            opt_arg = a\n            arg_consumed = true\n        else\n            if isempty(args_list) || looks_like_an_option(args_list[1], settings)\n                opt_arg = deepcopy(f.constant)\n            else\n                a = parse_function(f.arg_type, popfirst!(args_list))\n                test_range(f.range_tester, a, name)\n                opt_arg = a\n            end\n        end\n    elseif f.nargs.desc == :* || f.nargs.desc == :+\n        arg_found = false\n        if rest ≢ nothing\n            a = parse_function(f.arg_type, rest)\n            test_range(f.range_tester, a, name)\n            push!(opt_arg, a)\n            arg_consumed = true\n            arg_found = true\n        end\n        while !isempty(args_list)\n            if !arg_delim_found && looks_like_an_option(args_list[1], settings)\n                break\n            end\n            a = parse_function(f.arg_type, popfirst!(args_list))\n            test_range(f.range_tester, a, name)\n            push!(opt_arg, a)\n            arg_found = true\n        end\n        if f.nargs.desc == :+ && !arg_found\n            argparse_error(\"option $name requires at least one not-option-looking argument\")\n        end\n    elseif f.nargs.desc == :R\n        if rest ≢ nothing\n            a = parse_function(f.arg_type, rest)\n            test_range(f.range_tester, a, name)\n            push!(opt_arg, a)\n            arg_consumed = true\n        end\n        while !isempty(args_list)\n            a = parse_function(f.arg_type, popfirst!(args_list))\n            test_range(f.range_tester, a, name)\n            push!(opt_arg, a)\n        end\n    else\n        found_a_bug()\n    end\n    if f.action == :store_arg\n        out_dict[f.dest_name] = opt_arg\n    elseif f.action == :append_arg\n        push!(out_dict[f.dest_name], opt_arg)\n    elseif f.action == :command_arg\n        if !haskey(settings, opt_arg)\n            found = false\n            for f1 in settings.args_table.fields\n                (is_cmd(f1) && is_arg(f1)) || continue\n                for al in f1.cmd_aliases\n                    if opt_arg == al\n                        found = true\n                        opt_arg = f1.constant\n                        break\n                    end\n                end\n                found && break\n            end\n            !found && argparse_error(\"unknown command: $opt_arg\")\n            haskey(settings, opt_arg) || found_a_bug()\n        end\n        out_dict[f.dest_name] = opt_arg\n        command = opt_arg\n    else\n        found_a_bug()\n    end\n    state.arg_consumed = arg_consumed\n    state.command = command\n    return\nend\n\n# parse long opts\nfunction parse_long_opt!(state::ParserState, settings::ArgParseSettings)\n    opt_name = state.token\n    arg_after_eq = state.token_arg\n    local f::ArgParseField\n    local fln::AbstractString\n    exact_match = false\n    nfound = 0\n    for g in settings.args_table.fields\n        for ln in g.long_opt_name\n            if ln == opt_name\n                exact_match = true\n                nfound = 1\n                f = g\n                fln = ln\n                break\n            elseif startswith(ln, opt_name)\n                nfound += 1\n                f = g\n                fln = ln\n            end\n        end\n        exact_match && break\n    end\n    nfound == 0 && argparse_error(\"unrecognized option --$opt_name\")\n    nfound > 1 && argparse_error(\"long option --$opt_name is ambiguous ($nfound partial matches)\")\n\n    opt_name = fln\n\n    if is_flag(f)\n        parse1_flag!(state, settings, f, arg_after_eq ≢ nothing, \"--\"*opt_name)\n    else\n        parse1_optarg!(state, settings, f, arg_after_eq, \"--\"*opt_name)\n    end\n    push!(state.found_args, idstring(f))\n    return\nend\n\n# parse short opts\nfunction parse_short_opt!(state::ParserState, settings::ArgParseSettings)\n    shopts_lst = state.token\n    rest_as_arg = nothing\n    sind = firstindex(shopts_lst)\n    while sind ≤ ncodeunits(shopts_lst)\n        opt_char, next_sind = iterate(shopts_lst, sind)\n        if next_sind ≤ ncodeunits(shopts_lst)\n            next_opt_char, next2_sind = iterate(shopts_lst, next_sind)\n            if next_opt_char == '='\n                next_is_eq = true\n                rest_as_arg = shopts_lst[next2_sind:end]\n            else\n                next_is_eq = false\n                rest_as_arg = shopts_lst[next_sind:end]\n            end\n        else\n            next_is_eq = false\n            rest_as_arg = nothing\n        end\n\n        opt_name = string(opt_char)\n\n        local f::ArgParseField\n        found = false\n        for outer f in settings.args_table.fields\n            found |= any(sn->sn==opt_name, f.short_opt_name)\n            found && break\n        end\n        found || argparse_error(\"unrecognized option -$opt_name\")\n        if is_flag(f)\n            parse1_flag!(state, settings, f, next_is_eq, \"-\"*opt_name)\n        else\n            parse1_optarg!(state, settings, f, rest_as_arg, \"-\"*opt_name)\n        end\n        push!(state.found_args, idstring(f))\n        state.arg_consumed && break\n        if found_command(state)\n            if rest_as_arg ≢ nothing && !isempty(rest_as_arg)\n                startswith(rest_as_arg, '-') &&\n                    argparse_error(\"illegal short options sequence after command \" *\n                                   \"$(state.command): $rest_as_arg\")\n                pushfirst!(state.args_list, \"-\" * rest_as_arg)\n                state.truncated_shopts = true\n            end\n            return\n        end\n        sind = next_sind\n    end\nend\n\n# parse arg\nfunction parse_arg!(state::ParserState, settings::ArgParseSettings)\n    found = false\n    local f::ArgParseField\n    for new_arg_ind = state.last_arg+1:length(settings.args_table.fields)\n        f = settings.args_table.fields[new_arg_ind]\n        if is_arg(f) && !f.fake\n            found = true\n            state.last_arg = new_arg_ind\n            break\n        end\n    end\n    found || argparse_error(\"too many arguments\")\n\n    parse1_optarg!(state, settings, f, nothing, f.dest_name)\n\n    push!(state.found_args, idstring(f))\n    return\nend\n\n# convert_to_symbols\nconvert_to_symbols(::Nothing) = nothing\nfunction convert_to_symbols(parsed_args::Dict{String,Any})\n    new_parsed_args = Dict{Symbol,Any}()\n    cmd = nothing\n    if haskey(parsed_args, cmd_dest_name)\n        cmd = parsed_args[cmd_dest_name]\n        if cmd ≡ nothing\n            scmd = nothing\n        else\n            scmd = Symbol(cmd)\n            new_parsed_args[scmd] = convert_to_symbols(parsed_args[cmd])\n        end\n        new_parsed_args[scmd_dest_name] = scmd\n    end\n    for (k,v) in parsed_args\n        (k == cmd_dest_name || k == cmd) && continue\n        new_parsed_args[Symbol(k)] = v\n    end\n    return new_parsed_args\nend\n"
  },
  {
    "path": "src/settings.jl",
    "content": "## All types, functions and constants related to the specification of the arguments\n\n# actions\nconst all_actions = [:store_arg, :store_true, :store_false, :store_const,\n                     :append_arg, :append_const, :count_invocations,\n                     :command, :show_help, :show_version]\n\nconst internal_actions = [:store_arg, :store_true, :store_false, :store_const,\n                          :append_arg, :append_const, :count_invocations,\n                          :command_arg, :command_flag,\n                          :show_help, :show_version]\n\nconst nonflag_actions = [:store_arg, :append_arg, :command_arg]\nis_flag_action(a::Symbol) = a ∉ nonflag_actions\n\nconst multi_actions = [:append_arg, :append_const]\nis_multi_action(a::Symbol) = a ∈ multi_actions\n\nconst command_actions = [:command_arg, :command_flag]\nis_command_action(a::Symbol) = a ∈ command_actions\n\n# ArgParseSettingsError\nstruct ArgParseSettingsError <: Exception\n    text::AbstractString\nend\n\nserror(x...) = throw(ArgParseSettingsError(string(x...)))\n\n# ArgConsumerType\nstruct ArgConsumerType\n    desc::Union{Int,Symbol}\n    function ArgConsumerType(n::Integer)\n        n ≥ 0 || serror(\"nargs can't be negative\")\n        new(n)\n    end\n    function ArgConsumerType(s::Symbol)\n        s ∈ [:A, :?, :*, :+, :R] ||\n            serror(\"nargs must be an integer or one of 'A', '?', '*', '+', 'R'\")\n        new(s)\n    end\nend\nArgConsumerType(c::Char) = ArgConsumerType(Symbol(c))\nArgConsumerType() = ArgConsumerType(:A)\n\nfunction show(io::IO, nargs::ArgConsumerType)\n    print(io, nargs.desc isa Int ? nargs.desc : \"'\" * string(nargs.desc) * \"'\")\nend\n\nis_multi_nargs(nargs::ArgConsumerType) = nargs.desc ∉ (0, :A, :?)\n\ndefault_action(nargs::Integer) = nargs == 0 ? :store_true : :store_arg\ndefault_action(nargs::Char) = :store_arg\ndefault_action(nargs::Symbol) = :store_arg\n\ndefault_action(nargs::ArgConsumerType) = default_action(nargs.desc)\n\n# ArgParseGroup\nmutable struct ArgParseGroup\n    name::AbstractString\n    desc::AbstractString\n    exclusive::Bool\n    required::Bool\n    function ArgParseGroup(name::AbstractString,\n                  desc::AbstractString,\n                  exclusive::Bool = false,\n                  required::Bool = false\n                 )\n        new(name, desc, exclusive, required)\n    end\nend\n\nconst cmd_group = ArgParseGroup(\"commands\", \"commands\")\nconst pos_group = ArgParseGroup(\"positional\", \"positional arguments\")\nconst opt_group = ArgParseGroup(\"optional\", \"optional arguments\")\n\nconst std_groups = [cmd_group, pos_group, opt_group]\n\n# ArgParseField\nmutable struct ArgParseField\n    dest_name::AbstractString\n    long_opt_name::Vector{AbstractString}\n    short_opt_name::Vector{AbstractString}\n    arg_type::Type\n    action::Symbol\n    nargs::ArgConsumerType\n    default\n    constant\n    range_tester::Function\n    required::Bool\n    eval_arg::Bool\n    help::AbstractString\n    metavar::Union{AbstractString,Vector{<:AbstractString}}\n    cmd_aliases::Vector{AbstractString}\n    group::AbstractString\n    fake::Bool\n    ArgParseField() = new(\"\", AbstractString[], AbstractString[], Any, :store_true,\n                          ArgConsumerType(), nothing, nothing, _->true, false, false, \"\", \"\",\n                          AbstractString[], \"\", false)\nend\n\nis_flag(arg::ArgParseField) = is_flag_action(arg.action)\n\nis_arg(arg::ArgParseField) = isempty(arg.long_opt_name) && isempty(arg.short_opt_name)\n\nis_cmd(arg::ArgParseField) = is_command_action(arg.action)\n\nconst cmd_dest_name = \"%COMMAND%\"\nconst scmd_dest_name = :_COMMAND_\n\nfunction show(io::IO, s::ArgParseField)\n    println(io, \"ArgParseField(\")\n    for f in fieldnames(ArgParseField)\n        println(io, \"  \", f, \"=\", getfield(s, f))\n    end\n    print(io, \"  )\")\nend\n\n# ArgParseTable\nmutable struct ArgParseTable\n    fields::Vector{ArgParseField}\n    subsettings::Dict{AbstractString,Any} # will actually be a Dict{AbstractString,ArgParseSettings}\n    ArgParseTable() = new(ArgParseField[], Dict{AbstractString,Any}())\nend\n\n# disallow alphanumeric, -\nfunction check_prefix_chars(chars)\n    result = Set{Char}()\n    for c in chars\n        if isletter(c) || isnumeric(c) || c == '-'\n            throw(ArgParseError(\"‘$(c)’ is not allowed as prefix character\"))\n        end\n        push!(result, c)\n    end\n    result\nend\n\n# ArgParseSettings\n\"\"\"\n    ArgParseSettings\n\nThe `ArgParseSettings` object contains all the settings to be used during argument parsing. Settings\nare divided in two groups: general settings and argument-table-related settings.\nWhile the argument table requires specialized functions such as [`@add_arg_table!`](@ref) to be\ndefined and manipulated, general settings are simply object fields (most of them are `Bool` or\n`String`) and can be passed to the constructor as keyword arguments, or directly set at any time.\n\nThis is the list of general settings currently available:\n\n* `prog` (default = `\"\"`): the name of the program, as displayed in the auto-generated help and\n  usage screens. If left empty, the source file name will be used.\n* `description` (default = `\"\"`): a description of what the program does, to be displayed in the\n  auto-generated help-screen, between the usage lines and the arguments description. If\n  `preformatted_description` is `false` (see below), it will be automatically formatted, but you can\n  still force newlines by using two consecutive newlines in the string, and manually control spaces\n  by using non-breakable spaces (the character `'\\\\ua0'`).\n* `preformatted_description` (default = `false`): disable automatic formatting of `description`.\n* `epilog` (default = `\"\"`): like `description`, but will be displayed at the end of the\n  help-screen, after the arguments description. The same formatting rules also apply.\n* `preformatted_epilog` (default = `false`): disable automatic formatting of `epilog`.\n* `usage` (default = `\"\"`): the usage line(s) to be displayed in the help screen and when an error\n  is found during parsing. If left empty, it will be auto-generated.\n* `version` (default = `\"Unknown version\"`): version information. It's used by the `:show_version`\n  action.\n* `add_help` (default = `true`): if `true`, a `--help, -h` option (triggering the `:show_help`\n  action) is added to the argument table.\n* `add_version` (default = `false`): if `true`, a `--version` option (triggering the `:show_version`\n  action) is added to the argument table.\n* `help_width` (default = `70`): set the width of the help text. This does not affect the\n  `usage` line if it is provided by the user rather than being auto-generated; it also does not\n  affect the `description/epilog` lines if the `preformatted_description/epilog` options are set to\n  `false`.\n* `help_alignment_width` (default = `24`): set the maximum width of the left column of the help\n  text, where options and arguments names are listed. This also affects the indentation of the usage\n  line when it is auto-generated. It must be ≥ 4 and should be less than `help_width`.\n* `fromfile_prefix_chars` (default = `Set{Char}()`): an argument beginning with one of these\n  characters will specify a file from which arguments will be read, one argument read per line.\n  Alphanumeric characters and the hyphen-minus (`'-'`) are prohibited.\n* `autofix_names` (default = `false`): if `true`, will try to automatically fix the uses of dashes\n  (`'-'`) and underscores (`'_'`) in option names and destinations: all underscores will be\n  converted to dashes in long option names; also, associated destination names, if auto-generated\n  (see the [Argument names](@ref) section), will have dashes replaced with underscores, both for\n  long options and for positional arguments. For example, an option declared as `\"--my-opt\"` will be\n  associated with the key `\"my_opt\"` by default. It is especially advisable to turn this option on\n  then parsing with the `as_symbols=true` argument to `parse_args`.\n* `error_on_conflict` (default = `true`): if `true`, throw an error in case conflicting entries are\n  added to the argument table; if `false`, later entries will silently take precedence. See the\n  [Conflicts and overrides](@ref) srction for a detailed description of what conflicts are and what\n  is the exact behavior when this setting is `false`.\n* `suppress_warnings` (default = `false`): if `true`, all warnings will be suppressed.\n* `allow_ambiguous_opts` (default = `false`): if `true`, ambiguous options such as `-1` will be\n  accepted.\n* `commands_are_required` (default = `true`): if `true`, commands will be mandatory. See the\n  [Commands](@ref) section.\n* `exc_handler` (default = `ArgParse.default_handler`): this is a function which is invoked when an\n  error is detected during parsing (e.g. an option is not recognized, a required argument is not\n  passed etc.). It takes two arguments: the `settings::ArgParseSettings` object and the\n  `err::ArgParseError` exception. The default handler behaves differently depending on whether it's\n  invoked from a script or in an interactive environment (e.g. REPL/IJulia). In non-interactive\n  (script) mode, it calls `ArgParse.cmdline_handler`, which prints the error text and the usage\n  screen on standard error and exits Julia with error code 1:\n\n  ```julia\n  function cmdline_handler(settings::ArgParseSettings, err, err_code::Int = 1)\n      println(stderr, err.text)\n      println(stderr, usage_string(settings))\n      exit(err_code)\n  end\n  ```\n\n  In interactive mode instead it calls the function `ArgParse.debug_handler`, which just rethrows\n  the error.\n* `exit_after_help` (default = `!isinteractive()`): exit Julia (with error code `0`) when the\n  `:show_help` or `:show_version` actions are triggered. If `false`, those actions will just stop\n  the parsing and make `parse_args` return `nothing`.\n\nHere is a usage example:\n\n```julia\nsettings = ArgParseSettings(description = \"This program does something\",\n                            commands_are_required = false,\n                            version = \"1.0\",\n                            add_version = true)\n```\n\nwhich is also equivalent to:\n\n```julia\nsettings = ArgParseSettings()\nsettings.description = \"This program does something.\"\nsettings.commands_are_required = false\nsettings.version = \"1.0\"\nsettings.add_version = true\n```\n\nAs a shorthand, the `description` field can be passed without keyword, which makes this equivalent\nto the above:\n\n```julia\nsettings = ArgParseSettings(\"This program does something\",\n                            commands_are_required = false,\n                            version = \"1.0\",\n                            add_version = true)\n```\n\nMost settings won't take effect until `parse_args` is invoked, but a few will have immediate\neffects: `autofix_names`, `error_on_conflict`, `suppress_warnings`, `allow_ambiguous_opts`.\n\"\"\"\nmutable struct ArgParseSettings\n    prog::AbstractString\n    description::AbstractString\n    epilog::AbstractString\n    usage::AbstractString\n    version::AbstractString\n    add_help::Bool\n    add_version::Bool\n    help_width::Int\n    help_alignment_width::Int\n    fromfile_prefix_chars::Set{Char}\n    autofix_names::Bool\n    error_on_conflict::Bool\n    suppress_warnings::Bool\n    allow_ambiguous_opts::Bool\n    commands_are_required::Bool\n    args_groups::Vector{ArgParseGroup}\n    default_group::AbstractString\n    args_table::ArgParseTable\n    exc_handler::Function\n    preformatted_description::Bool\n    preformatted_epilog::Bool\n    exit_after_help::Bool\n\n    function ArgParseSettings(;prog::AbstractString = Base.source_path() ≢ nothing ?\n                                                          basename(Base.source_path()) :\n                                                          \"\",\n                               description::AbstractString = \"\",\n                               epilog::AbstractString = \"\",\n                               usage::AbstractString = \"\",\n                               version::AbstractString = \"Unspecified version\",\n                               add_help::Bool = true,\n                               add_version::Bool = false,\n                               help_width::Integer = 70,\n                               help_alignment_width::Integer = 24,\n                               fromfile_prefix_chars = Set{Char}(),\n                               autofix_names::Bool = false,\n                               error_on_conflict::Bool = true,\n                               suppress_warnings::Bool = false,\n                               allow_ambiguous_opts::Bool = false,\n                               commands_are_required::Bool = true,\n                               exc_handler::Function = default_handler,\n                               preformatted_description::Bool = false,\n                               preformatted_epilog::Bool = false,\n                               exit_after_help::Bool = !isinteractive()\n                               )\n        fromfile_prefix_chars = check_prefix_chars(fromfile_prefix_chars)\n        return new(\n            prog, description, epilog, usage, version, add_help, add_version,\n            help_width, help_alignment_width, fromfile_prefix_chars, autofix_names,\n            error_on_conflict, suppress_warnings, allow_ambiguous_opts, commands_are_required,\n            copy(std_groups), \"\", ArgParseTable(), exc_handler,\n            preformatted_description, preformatted_epilog,\n            exit_after_help\n            )\n    end\nend\n\nArgParseSettings(desc::AbstractString; kw...) = ArgParseSettings(; description = desc, kw...)\n\nfunction show(io::IO, s::ArgParseSettings)\n    println(io, \"ArgParseSettings(\")\n    for f in fieldnames(ArgParseSettings)\n        f ∈ (:args_groups, :args_table) && continue\n        println(io, \"  \", f, \"=\", getfield(s, f))\n    end\n    println(io, \"  >> \", usage_string(s))\n    print(io, \"  )\")\nend\n\nArgName{T<:AbstractString} = Union{T, Vector{T}}\n\ngetindex(s::ArgParseSettings, c::AbstractString) = s.args_table.subsettings[c]\nhaskey(s::ArgParseSettings, c::AbstractString) = haskey(s.args_table.subsettings, c)\nsetindex!(s::ArgParseSettings, x::ArgParseSettings, c::AbstractString) =\n    setindex!(s.args_table.subsettings, x, c)\n\n# fields declarations sanity checks\nfunction check_name_format(name::ArgName)\n    isempty(name) && serror(\"empty name\")\n    name isa Vector || return true\n    allopts = true\n    allargs = true\n    for n in name\n        isempty(n) && serror(\"empty name\")\n        if startswith(n, '-')\n            allargs = false\n        else\n            allopts = false\n        end\n    end\n    !(allargs || allopts) && serror(\"multiple names must be either all options or all non-options\")\n    for i1 = 1:length(name), i2 = i1+1:length(name)\n        name[i1] == name[i2] && serror(\"duplicate name $(name[i1])\")\n    end\n    return true\nend\n\nfunction check_type(opt, T::Type, message::AbstractString)\n    opt isa T || serror(message)\n    return true\nend\n\nfunction check_eltype(opt, T::Type, message::AbstractString)\n    eltype(opt) <: T || serror(message)\n    return true\nend\n\nfunction warn_extra_opts(opts, valid_keys::Vector{Symbol})\n    for k in opts\n        k ∈ valid_keys || @warn \"ignored option: $k\"\n    end\n    return true\nend\n\nfunction check_action_is_valid(action::Symbol)\n    action ∈ all_actions || serror(\"invalid action: $action\")\nend\n\nfunction check_nargs_and_action(nargs::ArgConsumerType, action::Symbol)\n    is_flag_action(action) && nargs.desc ≠ 0 && nargs.desc ≠ :A &&\n        serror(\"incompatible nargs and action (flag-action $action, nargs=$nargs)\")\n    is_command_action(action) && nargs.desc ≠ :A &&\n        serror(\"incompatible nargs and action (command action, nargs=$nargs)\")\n    !is_flag_action(action) && nargs.desc == 0 &&\n        serror(\"incompatible nargs and action (non-flag-action $action, nargs=$nargs)\")\n    return true\nend\n\nfunction check_long_opt_name(name::AbstractString, settings::ArgParseSettings)\n    '=' ∈ name            && serror(\"illegal option name: $name (contains '=')\")\n    occursin(r\"\\s\", name) && serror(\"illegal option name: $name (contains whitespace)\")\n    settings.add_help     &&\n        name == \"help\"    && serror(\"option --help is reserved in the current settings\")\n    settings.add_version  &&\n        name == \"version\" && serror(\"option --version is reserved in the current settings\")\n    return true\nend\n\nfunction check_short_opt_name(name::AbstractString, settings::ArgParseSettings)\n    length(name) ≠ 1      && serror(\"short options must use a single character\")\n    name == \"=\"           && serror(\"illegal short option name: $name\")\n    occursin(r\"\\s\", name) && serror(\"illegal option name: $name (contains whitespace)\")\n    !settings.allow_ambiguous_opts && occursin(r\"[0-9.(]\", name) &&\n                             serror(\"ambiguous option name: $name (disabled in current settings)\")\n    settings.add_help && name == \"h\" &&\n                             serror(\"option -h is reserved for help in the current settings\")\n    return true\nend\n\nfunction check_arg_name(name::AbstractString)\n    occursin(r\"^%[A-Z]*%$\", name) && serror(\"invalid positional arg name: $name (is reserved)\")\n    return true\nend\n\nfunction check_cmd_name(name::AbstractString)\n    isempty(name) && found_a_bug()\n    startswith(name, '-') && found_a_bug()\n    occursin(r\"\\s\", name) && serror(\"invalid command name: $name (contains whitespace)\")\n    occursin(r\"^%[A-Z]*%$\", name) && serror(\"invalid command name: $name (is reserved)\")\n    return true\nend\n\nfunction check_dest_name(name::AbstractString)\n    occursin(r\"^%[A-Z]*%$\", name) && serror(\"invalid dest_name: $name (is reserved)\")\n    return true\nend\n\nfunction idstring(arg::ArgParseField)\n    if is_arg(arg)\n        return \"argument $(arg.metavar)\"\n    elseif !isempty(arg.long_opt_name)\n        return \"option --$(arg.long_opt_name[1])\"\n    else\n        return \"option -$(arg.short_opt_name[1])\"\n    end\nend\n\n# TODO improve (test more nonsensical cases)\nfunction check_arg_makes_sense(settings::ArgParseSettings, arg::ArgParseField)\n    is_arg(arg) || return true\n    is_command_action(arg.action) && return true\n\n    for f in settings.args_table.fields\n        is_arg(f) || continue\n        is_command_action(f.action) && serror(\"non-command $(idstring(arg)) can't follow commands\")\n        !f.required && arg.required &&\n            serror(\"required $(idstring(arg)) can't follow non-required arguments\")\n    end\n    return true\nend\n\nfunction check_conflicts_with_commands(settings::ArgParseSettings,\n                                       new_arg::ArgParseField,\n                                       allow_future_merge::Bool)\n    for cmd in keys(settings.args_table.subsettings)\n        cmd == new_arg.dest_name &&\n            serror(\"$(idstring(new_arg)) has the same destination of a command: $cmd\")\n    end\n    for a in settings.args_table.fields\n        if is_cmd(a) && !is_cmd(new_arg)\n            for l1 in a.long_opt_name, l2 in new_arg.long_opt_name\n                # TODO be less strict here and below, and allow partial override?\n                l1 == l2 && serror(\"long opt name --$(l1) already in use by command $(a.constant)\")\n            end\n            for s1 in a.short_opt_name, s2 in new_arg.short_opt_name\n                s1 == s2 && serror(\"short opt name -$(s1) already in use by command $(a.constant)\")\n            end\n        elseif is_cmd(a) && is_cmd(new_arg)\n            if a.constant == new_arg.constant\n                allow_future_merge || serror(\"command $(a.constant) already in use\")\n                is_arg(a) ≠ is_arg(new_arg) &&\n                    serror(\"$(idstring(a)) and $(idstring(new_arg)) are incompatible\")\n            else\n                for al in new_arg.cmd_aliases\n                    al == a.constant && serror(\"invalid alias $al, command already in use\")\n                end\n            end\n        end\n    end\n    return true\nend\n\nfunction check_conflicts_with_commands(settings::ArgParseSettings, new_cmd::AbstractString)\n    for a in settings.args_table.fields\n        new_cmd == a.dest_name &&\n            serror(\"command $new_cmd has the same destination of $(idstring(a))\")\n    end\n    return true\nend\n\nfunction check_for_duplicates(args::Vector{ArgParseField}, new_arg::ArgParseField)\n    for a in args\n        for l1 in a.long_opt_name, l2 in new_arg.long_opt_name\n            l1 == l2 && serror(\"duplicate long opt name $l1\")\n        end\n        for s1 in a.short_opt_name, s2 in new_arg.short_opt_name\n            s1 == s2 && serror(\"duplicate short opt name $s1\")\n        end\n        if is_arg(a) && is_arg(new_arg) && a.metavar == new_arg.metavar\n            serror(\"two arguments have the same metavar: $(a.metavar)\")\n        end\n        if is_cmd(a) && is_cmd(new_arg)\n            for al1 in a.cmd_aliases, al2 in new_arg.cmd_aliases\n                al1 == al2 &&\n                    serror(\"both commands $(a.constant) and $(new_arg.constant) use the same alias $al1\")\n            end\n            for al1 in a.cmd_aliases\n                al1 == new_arg.constant &&\n                    serror(\"$al1 already in use as an alias command $(a.constant)\")\n            end\n            for al2 in new_arg.cmd_aliases\n                al2 == a.constant && serror(\"invalid alias $al2, command already in use\")\n            end\n        end\n        if a.dest_name == new_arg.dest_name\n            a.arg_type == new_arg.arg_type ||\n                serror(\"$(idstring(a)) and $(idstring(new_arg)) have the same destination but different arg types\")\n            if (is_multi_action(a.action) && !is_multi_action(new_arg.action)) ||\n               (!is_multi_action(a.action) && is_multi_action(new_arg.action))\n                serror(\"$(idstring(a)) and $(idstring(new_arg)) have the same destination but incompatible actions\")\n            end\n        end\n    end\n    return true\nend\n\nfunction typecompatible(default::D, arg_type::Type) where D\n    D <: arg_type && return true\n    try\n        applicable(convert, arg_type, default) ? convert(arg_type, default) : arg_type(default)\n        return true\n    catch\n    end\n    return false\nend\n\ncheck_default_type(default::Nothing, arg_type::Type) = true\nfunction check_default_type(default::D, arg_type::Type) where D\n    typecompatible(default, arg_type) || serror(\"typeof(default)=$D is incompatible with arg_type=$arg_type)\")\n    return true\nend\n\ncheck_default_type_multi(default::Nothing, arg_type::Type) = true\nfunction check_default_type_multi(default::Vector, arg_type::Type)\n    all(x->typecompatible(x, arg_type), default) || serror(\"all elements of the default value must be of type $arg_type or convertible to it\")\n    return true\nend\ncheck_default_type_multi(default::D, arg_type::Type) where D =\n    serror(\"typeof(default)=$D is incompatible with nargs, it should be a Vector\")\n\ncheck_default_type_multi2(default::Nothing, arg_type::Type) = true\nfunction check_default_type_multi2(default::Vector{D}, arg_type::Type) where D\n    all(y->(y isa Vector), default) ||\n        serror(\"the default $(default) is incompatible with the action and nargs, it should be a Vector of Vectors\")\n    all(y->all(x->typecompatible(x, arg_type), y), default) || serror(\"all elements of the default value must be of type $arg_type or convertible to it\")\n    return true\nend\ncheck_default_type_multi2(default::D, arg_type::Type) where D =\n    serror(\"the default $(default) is incompatible with the action and nargs, it should be a Vector of Vectors\")\n\nfunction _convert_default(arg_type::Type, default::D) where D\n    D <: arg_type && return default\n    applicable(convert, arg_type, default) ? convert(arg_type, default) : arg_type(default)\nend\n\nconvert_default(arg_type::Type, default::Nothing) = nothing\nconvert_default(arg_type::Type, default) = _convert_default(arg_type, default)\n\nconvert_default_multi(arg_type::Type, default::Nothing) = Array{arg_type}(undef, 0)\nconvert_default_multi(arg_type::Type, default::Vector) = arg_type[_convert_default(arg_type, x) for x in default]\n\nconvert_default_multi2(arg_type::Type, default::Nothing) = Array{Vector{arg_type}}(undef, 0)\nconvert_default_multi2(arg_type::Type, default::Vector) = Vector{arg_type}[arg_type[_convert_default(arg_type, x) for x in y] for y in default]\n\n\ncheck_range_default(default::Nothing, range_tester::Function) = true\nfunction check_range_default(default, range_tester::Function)\n    local res::Bool\n    try\n        res = range_tester(default)\n    catch err\n        serror(\"the range_tester function must be defined for the default value, and return a Bool\")\n    end\n    res || serror(\"the default value must pass the range_tester function\")\n    return true\nend\n\ncheck_range_default_multi(default::Nothing, range_tester::Function) = true\nfunction check_range_default_multi(default::Vector, range_tester::Function)\n    for d in default\n        local res::Bool\n        try\n            res = range_tester(d)\n        catch err\n            serror(\"the range_tester function must be defined for all the default values, and return a Bool\")\n        end\n        res || serror(\"all of the default values must pass the range_tester function\")\n    end\n    return true\nend\n\ncheck_range_default_multi2(default::Nothing, range_tester::Function) = true\nfunction check_range_default_multi2(default::Vector, range_tester::Function)\n    for dl in default, d in dl\n        local res::Bool\n        try\n            res = range_tester(d)\n        catch err\n            serror(\"the range_tester function must be defined for all the default values, and return a Bool\")\n        end\n        res || serror(\"all of the default values must pass the range_tester function\")\n    end\n    return true\nend\n\nfunction check_metavar(metavar::AbstractString)\n    isempty(metavar)         && serror(\"empty metavar\")\n    startswith(metavar, '-') && serror(\"metavars cannot begin with -\")\n    occursin(r\"\\s\", metavar) && serror(\"illegal metavar name: $metavar (contains whitespace)\")\n    return true\nend\n\nfunction check_metavar(metavar::Vector{<:AbstractString})\n    foreach(check_metavar, metavar)\n    return true\nend\n\nfunction check_group_name(name::AbstractString)\n    isempty(name)         && serror(\"empty group name\")\n    startswith(name, '#') && serror(\"invalid group name (starts with #)\")\n    return true\nend\n\n# add_arg_table! and related\nfunction name_to_fieldnames!(settings::ArgParseSettings, name::ArgName)\n    pos_arg = \"\"\n    long_opts = AbstractString[]\n    short_opts = AbstractString[]\n    aliases = AbstractString[]\n    r(n) = settings.autofix_names ? replace(n, '_' => '-') : n\n    function do_one(n, cmd_check = true)\n        if startswith(n, \"--\")\n            n == \"--\" && serror(\"illegal option name: --\")\n            long_opt_name = r(n[3:end])\n            check_long_opt_name(long_opt_name, settings)\n            push!(long_opts, long_opt_name)\n        elseif startswith(n, '-')\n            n == \"-\" && serror(\"illegal option name: -\")\n            short_opt_name = n[2:end]\n            check_short_opt_name(short_opt_name, settings)\n            push!(short_opts, short_opt_name)\n        else\n            if cmd_check\n                check_cmd_name(n)\n            else\n                check_arg_name(n)\n            end\n            if isempty(pos_arg)\n                pos_arg = n\n            else\n                push!(aliases, n)\n            end\n        end\n    end\n\n    if name isa Vector\n        foreach(do_one, name)\n    else\n        do_one(name, false)\n    end\n    return pos_arg, long_opts, short_opts, aliases\nend\n\nfunction auto_dest_name(pos_arg::AbstractString,\n                        long_opts::Vector{AbstractString},\n                        short_opts::Vector{AbstractString},\n                        autofix_names::Bool)\n    r(n) = autofix_names ? replace(n, '-' => '_') : n\n    isempty(pos_arg) || return r(pos_arg)\n    isempty(long_opts) || return r(long_opts[1])\n    @assert !isempty(short_opts)\n    return short_opts[1]\nend\n\nfunction auto_metavar(dest_name::AbstractString, is_opt::Bool)\n    is_opt || return dest_name\n    prefix = occursin(r\"^[[:alpha:]_]\", dest_name) ? \"\" : \"_\"\n    return prefix * uppercase(dest_name)\nend\n\nfunction get_cmd_prog_hint(arg::ArgParseField)\n    isempty(arg.short_opt_name) || return \"-\" * arg.short_opt_name[1]\n    isempty(arg.long_opt_name) || return \"--\" * arg.long_opt_name[1]\n    return arg.constant\nend\n\n\n\"\"\"\n    add_arg_table!(settings, [arg_name [,arg_options]]...)\n\nThis function is very similar to the macro version [`@add_arg_table!`](@ref). Its syntax is stricter:\ntuples and blocks are not allowed and argument options are explicitly specified as `Dict` objects.\nHowever, since it doesn't involve macros, it offers more flexibility in other respects, e.g. the\n`arg_name` entries need not be explicit, they can be anything which evaluates to a `String` or a\n`Vector{String}`.\n\nExample:\n\n```julia\nadd_arg_table!(settings,\n    [\"--opt1\", \"-o\"],\n    Dict(\n        :help => \"an option with an argument\"\n    ),\n    \"--opt2\",\n    \"arg1\",\n    Dict(\n        :help => \"a positional argument\"\n        :required => true\n    ))\n```\n\"\"\"\nfunction add_arg_table!(settings::ArgParseSettings, table::Union{ArgName,Vector,Dict}...)\n    has_name = false\n    for i = 1:length(table)\n        !has_name && !(table[i] isa ArgName) &&\n            serror(\"option field must be preceded by the arg name\")\n        has_name = true\n    end\n    i = 1\n    while i ≤ length(table)\n        if i+1 ≤ length(table) && !(table[i+1] isa ArgName)\n            add_arg_field!(settings, table[i]; table[i+1]...)\n            i += 2\n        else\n            add_arg_field!(settings, table[i])\n            i += 1\n        end\n    end\n    return settings\nend\n\n\"\"\"\n    @add_arg_table!(settings, table...)\n\nThis macro adds a table of arguments and options to the given `settings`. It can be invoked multiple\ntimes. The arguments groups are determined automatically, or the current default group is used if\nspecified (see the [Argument groups](@ref) section for more details).\n\nThe `table` is a list in which each element can be either `String`, or a tuple or a vector of\n`String`, or an assigmment expression, or a block:\n\n* a `String`, a tuple or a vector introduces a new positional argument or option. Tuples and vectors\n  are only allowed for options or commands, and provide alternative names (e.g. `[\"--opt\", \"-o\"]` or\n  `[\"checkout\", \"co\"]`)\n* assignment expressions (i.e. expressions using `=`, `:=` or `=>`) describe the previous argument\n  behavior (e.g.  `help = \"an option\"` or `required => false`).  See the\n  [Argument entry settings](@ref) section for a complete description\n* blocks (`begin...end` or lists of expressions in parentheses separated by semicolons) are useful\n  to group entries and span multiple lines.\n\nThese rules allow for a variety usage styles, which are discussed in the\n[Argument table styles](@ref) section. In the rest of the documentation, we will mostly use this\nstyle:\n\n```julia\n@add_arg_table! settings begin\n    \"--opt1\", \"-o\"\n        help = \"an option with an argument\"\n    \"--opt2\"\n    \"arg1\"\n        help = \"a positional argument\"\n        required = true\nend\n```\n\nIn the above example, the `table` is put in a single `begin...end` block and the line\n`\"--opt1\", \"-o\"` is parsed as a tuple; indentation is used to help readability.\n\nSee also the function [`add_arg_table!`](@ref).\n\"\"\"\nmacro add_arg_table!(s, x...)\n    _add_arg_table!(s, x...)\nend\n\n# Moved all the code to a function just to make the deprecation work\nfunction _add_arg_table!(s, x...)\n    # transform the tuple into a vector, so that\n    # we can manipulate it\n    x = Any[x...]\n    # escape the ArgParseSettings\n    s = esc(s)\n    z = esc(gensym())\n    # start building the return expression\n    exret = quote\n        $z = $s\n        $z isa ArgParseSettings ||\n            serror(\"first argument to @add_arg_table! must be of type ArgParseSettings\")\n    end\n    # initialize the name and the options expression\n    name = nothing\n    exopt = Any[:Dict]\n\n    # iterate over the arguments\n    i = 1\n    while i ≤ length(x)\n        y = x[i]\n        if Meta.isexpr(y, :block)\n            # found a begin..end block: expand its contents\n            # in-place and restart from the same position\n            splice!(x, i, y.args)\n            continue\n        elseif Meta.isexpr(y, :macrocall) &&\n               ((y.args[1] == GlobalRef(Core, Symbol(\"@doc\"))) ||\n               (Meta.isexpr(y.args[1], :core) && y.args[1].args[1] == Symbol(\"@doc\")))\n            # Was parsed as doc syntax. Split into components\n            splice!(x, i, y.args[2:end])\n            continue\n        elseif (y isa AbstractString) || Meta.isexpr(y, (:vect, :tuple))\n            Meta.isexpr(y, :tuple) && (y.head = :vect) # transform tuples into vectors\n            if Meta.isexpr(y, :vect) && (isempty(y.args) || !all(x->x isa AbstractString, y.args))\n                # heterogeneous elements: splice it in place, just like blocks\n                splice!(x, i, y.args)\n                continue\n            end\n            # found a string, or a vector/tuple of strings:\n            # this must be the option name\n            if name ≢ nothing\n                # there was a previous arg field on hold\n                # first, concretely build the options\n                opt = Expr(:call, exopt...)\n                kopts = Expr(:parameters, Expr(:(...), opt))\n                # then, call add_arg_field!\n                aaf = Expr(:call, :add_arg_field!, kopts, z, name)\n                # store it in the output expression\n                exret = quote\n                    $exret\n                    $aaf\n                end\n            end\n            # put the name on hold, reinitialize the options expression\n            name = y\n            exopt = Any[:Dict]\n            i += 1\n        elseif Meta.isexpr(y, (:(=), :(:=), :kw))\n            # found an assignment: add it to the current options expression\n            name ≢ nothing ||\n                serror(\"malformed table: description fields must be preceded by the arg name\")\n            push!(exopt, Expr(:call, :(=>), Expr(:quote, y.args[1]), esc(y.args[2])))\n            i += 1\n        elseif Meta.isexpr(y, :call) && y.args[1] == :(=>)\n            # found an assignment: add it to the current options expression\n            name ≢ nothing ||\n                serror(\"malformed table: description fields must be preceded by the arg name\")\n            push!(exopt, Expr(:call, :(=>), Expr(:quote, y.args[2]), esc(y.args[3])))\n            i += 1\n        elseif (y isa LineNumberNode) || Meta.isexpr(y, :line)\n            # a line number node, ignore\n            i += 1\n            continue\n        else\n            # anything else: ignore, but issue a warning\n            @warn \"@add_arg_table!: ignoring expression $y\"\n            i += 1\n        end\n    end\n    if name ≢ nothing\n        # there is an arg field on hold\n        # same as above\n        opt = Expr(:call, exopt...)\n        kopts = Expr(:parameters, Expr(:(...), opt))\n        aaf = Expr(:call, :add_arg_field!, kopts, z, name)\n        exret = quote\n            $exret\n            $aaf\n        end\n    end\n\n    # the return value when invoking the macro\n    # will be the ArgParseSettings object\n    exret = quote\n        $exret\n        $z\n    end\n\n    # return the resulting expression\n    exret\nend\n\nfunction get_group(group::AbstractString, arg::ArgParseField, settings::ArgParseSettings)\n    if isempty(group)\n        is_cmd(arg) && return cmd_group\n        is_arg(arg) && return pos_group\n        return opt_group\n    else\n        for ag in settings.args_groups\n            group == ag.name && return ag\n        end\n        serror(\"group $group not found, use add_arg_group! to add it\")\n    end\n    found_a_bug()\nend\n\nfunction add_arg_field!(settings::ArgParseSettings, name::ArgName; desc...)\n    check_name_format(name)\n\n    supplied_opts = keys(desc)\n\n    @defaults desc begin\n        nargs = ArgConsumerType()\n        action = default_action(nargs)\n        arg_type = Any\n        default = nothing\n        constant = nothing\n        required = false\n        range_tester = x->true\n        eval_arg = false\n        dest_name = \"\"\n        help = \"\"\n        metavar = \"\"\n        force_override = !settings.error_on_conflict\n        group = settings.default_group\n    end\n\n    check_type(nargs, Union{ArgConsumerType,Int,Char}, \"nargs must be an Int or a Char\")\n    check_type(action, Union{AbstractString,Symbol}, \"action must be an AbstractString or a Symbol\")\n    check_type(arg_type, Type, \"invalid arg_type\")\n    check_type(required, Bool, \"required must be a Bool\")\n    check_type(range_tester, Function, \"range_tester must be a Function\")\n    check_type(dest_name, AbstractString, \"dest_name must be an AbstractString\")\n    check_type(help, AbstractString, \"help must be an AbstractString\")\n    # Check metavar's type to be either an AbstractString or a\n    # Vector{T<:AbstractString}\n    metavar_error = \"metavar must be an AbstractString or a Vector{<:AbstractString}\"\n    if !(metavar isa AbstractString)\n        check_type(metavar, Vector, metavar_error)\n        check_eltype(metavar, AbstractString, metavar_error)\n        check_type(nargs, Integer, \"nargs must be an integer for multiple metavars\")\n        length(metavar) == nargs || serror(\"metavar array must have length of nargs\")\n    end\n    check_type(force_override, Bool, \"force_override must be a Bool\")\n    check_type(group, Union{AbstractString,Symbol}, \"group must be an AbstractString or a Symbol\")\n\n    nargs isa ArgConsumerType || (nargs = ArgConsumerType(nargs))\n    action isa Symbol || (action = Symbol(action))\n\n    is_opt = name isa Vector ?\n        startswith(first(name), '-') :\n        startswith(name, '-')\n\n    check_action_is_valid(action)\n\n    action == :command && (action = is_opt ? :command_flag : :command_arg)\n\n    check_nargs_and_action(nargs, action)\n\n    new_arg = ArgParseField()\n\n    is_flag = is_flag_action(action)\n\n    if !is_opt\n        is_flag && serror(\"invalid action for positional argument: $action\")\n        nargs.desc == :? && serror(\"invalid 'nargs' for positional argument: '?'\")\n        metavar isa Vector && serror(\"multiple metavars only supported for optional arguments\")\n    end\n\n    pos_arg, long_opts, short_opts, cmd_aliases = name_to_fieldnames!(settings, name)\n\n    if !isempty(cmd_aliases)\n        is_command_action(action) || serror(\"only command arguments can have multiple names (aliases)\")\n    end\n\n    new_arg.dest_name = auto_dest_name(pos_arg, long_opts, short_opts, settings.autofix_names)\n\n    new_arg.long_opt_name = long_opts\n    new_arg.short_opt_name = short_opts\n    new_arg.cmd_aliases = cmd_aliases\n    new_arg.nargs = nargs\n    new_arg.action = action\n\n    group = string(group)\n    if :group ∈ supplied_opts && !isempty(group)\n        check_group_name(group)\n    end\n    arg_group = get_group(group, new_arg, settings)\n    new_arg.group = arg_group.name\n    if arg_group.exclusive && (!is_opt || is_command_action(action))\n        serror(\"group $(new_arg.group) is mutually-exclusive, actions and commands are not allowed\")\n    end\n\n    if action ∈ (:store_const, :append_const) && :constant ∉ supplied_opts\n        serror(\"action $action requires the 'constant' field\")\n    end\n\n    valid_keys = [:nargs, :action, :help, :force_override, :group]\n    if is_flag\n        if action ∈ (:store_const, :append_const)\n            append!(valid_keys, [:default, :constant, :arg_type, :dest_name])\n        elseif action ∈ (:store_true, :store_false, :count_invocations, :command_flag)\n            push!(valid_keys, :dest_name)\n        else\n            action ∈ (:show_help, :show_version) || found_a_bug()\n        end\n    elseif is_opt\n        append!(valid_keys,\n                [:arg_type, :default, :range_tester, :dest_name, :required, :metavar, :eval_arg])\n        nargs.desc == :? && push!(valid_keys, :constant)\n    elseif action ≠ :command_arg\n        append!(valid_keys, [:arg_type, :default, :range_tester, :required, :metavar])\n    end\n    settings.suppress_warnings || warn_extra_opts(supplied_opts, valid_keys)\n\n    if is_command_action(action)\n        if (:dest_name ∈ supplied_opts) && (:dest_name ∈ valid_keys)\n            cmd_name = dest_name\n        else\n            cmd_name = new_arg.dest_name\n        end\n    end\n    if (:dest_name ∈ supplied_opts) && (:dest_name ∈ valid_keys) && (action ≠ :command_flag)\n        new_arg.dest_name = dest_name\n    end\n\n    check_dest_name(dest_name)\n\n    set_if_valid(k, x) = k ∈ valid_keys && setfield!(new_arg, k, x)\n\n    set_if_valid(:arg_type, arg_type)\n    set_if_valid(:default, deepcopy(default))\n    set_if_valid(:constant, deepcopy(constant))\n    set_if_valid(:range_tester, range_tester)\n    set_if_valid(:required, required)\n    set_if_valid(:help, help)\n    set_if_valid(:metavar, metavar)\n    set_if_valid(:eval_arg, eval_arg)\n\n    if !is_flag\n        isempty(new_arg.metavar) && (new_arg.metavar = auto_metavar(new_arg.dest_name, is_opt))\n        check_metavar(new_arg.metavar)\n    end\n\n    if is_command_action(action)\n        new_arg.dest_name = cmd_dest_name\n        new_arg.arg_type = AbstractString\n        new_arg.constant = cmd_name\n        new_arg.metavar = cmd_name\n        cmd_prog_hint = get_cmd_prog_hint(new_arg)\n    end\n\n    if is_flag\n        if action == :store_true\n            new_arg.arg_type = Bool\n            new_arg.default = false\n            new_arg.constant =  true\n        elseif action == :store_false\n            new_arg.arg_type = Bool\n            new_arg.default = true\n            new_arg.constant =  false\n        elseif action == :count_invocations\n            new_arg.arg_type = Int\n            new_arg.default = 0\n        elseif action == :store_const\n            check_default_type(new_arg.default, new_arg.arg_type)\n            check_default_type(new_arg.constant, new_arg.arg_type)\n            new_arg.default = convert_default(new_arg.arg_type, new_arg.default)\n        elseif action == :append_const\n            check_default_type(new_arg.constant, new_arg.arg_type)\n            if :arg_type ∉ supplied_opts\n                new_arg.arg_type = typeof(new_arg.constant)\n            end\n            check_default_type_multi(new_arg.default, new_arg.arg_type)\n            new_arg.default = convert_default_multi(new_arg.arg_type, new_arg.default)\n        elseif action == :command_flag\n            # nothing to do\n        elseif action == :show_help || action == :show_version\n            # nothing to do\n        else\n            found_a_bug()\n        end\n    else\n        arg_type = new_arg.arg_type\n        range_tester = new_arg.range_tester\n        default = new_arg.default\n\n        if !is_multi_action(new_arg.action) && !is_multi_nargs(new_arg.nargs)\n            check_default_type(default, arg_type)\n            check_range_default(default, range_tester)\n            new_arg.default = convert_default(arg_type, default)\n        elseif !is_multi_action(new_arg.action) || !is_multi_nargs(new_arg.nargs)\n            check_default_type_multi(default, arg_type)\n            check_range_default_multi(default, range_tester)\n            new_arg.default = convert_default_multi(arg_type, default)\n        else\n            check_default_type_multi2(default, arg_type)\n            check_range_default_multi2(default, range_tester)\n            new_arg.default = convert_default_multi2(arg_type, default)\n        end\n\n        if is_opt && nargs.desc == :?\n            constant = new_arg.constant\n            check_default_type(constant, arg_type)\n            check_range_default(constant, range_tester)\n            new_arg.constant = convert_default(arg_type, constant)\n        end\n    end\n\n    if action == :command_arg\n        for f in settings.args_table.fields\n            if f.action == :command_arg\n                new_arg.fake = true\n                break\n            end\n        end\n    end\n\n    check_arg_makes_sense(settings, new_arg)\n\n    check_conflicts_with_commands(settings, new_arg, false)\n    if force_override\n        override_duplicates!(settings.args_table.fields, new_arg)\n    else\n        check_for_duplicates(settings.args_table.fields, new_arg)\n    end\n    push!(settings.args_table.fields, new_arg)\n    is_command_action(action) && add_command!(settings, cmd_name, cmd_prog_hint, force_override)\n    return\nend\n\nfunction add_command!(settings::ArgParseSettings,\n                      command::AbstractString,\n                      prog_hint::AbstractString,\n                      force_override::Bool)\n    haskey(settings, command) && serror(\"command $command already added\")\n    if force_override\n        override_conflicts_with_commands!(settings, command)\n    else\n        check_conflicts_with_commands(settings, command)\n    end\n    settings[command] = ArgParseSettings()\n    ss = settings[command]\n    ss.prog = \"$(isempty(settings.prog) ? \"<PROGRAM>\" : settings.prog) $prog_hint\"\n    ss.description = \"\"\n    ss.preformatted_description = settings.preformatted_description\n    ss.epilog = \"\"\n    ss.preformatted_epilog = settings.preformatted_epilog\n    ss.usage = \"\"\n    ss.version = settings.version\n    ss.add_help = settings.add_help\n    ss.add_version = settings.add_version\n    ss.autofix_names = settings.autofix_names\n    ss.fromfile_prefix_chars = settings.fromfile_prefix_chars\n    ss.error_on_conflict = settings.error_on_conflict\n    ss.suppress_warnings = settings.suppress_warnings\n    ss.allow_ambiguous_opts = settings.allow_ambiguous_opts\n    ss.exc_handler = settings.exc_handler\n    ss.exit_after_help = settings.exit_after_help\n\n    return ss\nend\n\nautogen_group_name(desc::AbstractString) = \"#$(hash(desc))\"\n\nadd_arg_group!(settings::ArgParseSettings, desc::AbstractString;\n               exclusive::Bool = false, required::Bool = false) =\n    _add_arg_group!(settings, desc, autogen_group_name(desc), true, exclusive, required)\n\n\n\"\"\"\n    add_arg_group!(settings, description, [name , [set_as_default]]; keywords...)\n\nThis function adds an argument group to the argument table in `settings`. The `description` is a\n`String` used in the help screen as a title for that group. The `name` is a unique name which can be\nprovided to refer to that group at a later time.\n\nGroups can be declared to be mutually exclusive and/or required, see below.\n\nAfter invoking this function, all subsequent invocations of the [`@add_arg_table!`](@ref) macro and\n[`add_arg_table!`](@ref) function will use the new group as the default, unless `set_as_default` is\nset to `false` (the default is `true`, and the option can only be set if providing a `name`).\nTherefore, the most obvious usage pattern is: for each group, add it and populate the argument\ntable of that group. Example:\n\n```julia-repl\njulia> settings = ArgParseSettings();\n\njulia> add_arg_group!(settings, \"custom group\");\n\njulia> @add_arg_table! settings begin\n          \"--opt\"\n          \"arg\"\n       end;\n\njulia> parse_args([\"--help\"], settings)\nusage: <command> [--opt OPT] [-h] [arg]\n\noptional arguments:\n  -h, --help  show this help message and exit\n\ncustom group:\n  --opt OPT\n  arg\n```\n\nAs seen from the example, new groups are always added at the end of existing ones.\n\nThe `name` can also be passed as a `Symbol`. Forbidden names are the standard groups names\n(`\"command\"`, `\"positional\"` and `\"optional\"`) and those beginning with a hash character `'#'`.\n\nIn order to declare a group as mutually exclusive, use the keyword `exclusive = true`. Mutually\nexclusive groups can only contain options, not arguments nor commands, and parsing will fail if more\nthan one option from the group is provided.\n\nA group can be declared as required using the `required = true` keyword, in which case at least one\noption or positional argument or command from the group must be provided.\n\"\"\"\nfunction add_arg_group!(settings::ArgParseSettings,\n                        desc::AbstractString,\n                        tag::Union{AbstractString,Symbol},\n                        set_as_default::Bool = true;\n                        exclusive::Bool = false,\n                        required::Bool = false\n                       )\n    name = string(tag)\n    check_group_name(name)\n    _add_arg_group!(settings, desc, name, set_as_default, exclusive, required)\nend\n\nfunction _add_arg_group!(settings::ArgParseSettings,\n                         desc::AbstractString,\n                         name::AbstractString,\n                         set_as_default::Bool,\n                         exclusive::Bool,\n                         required::Bool\n                        )\n    already_added = any(ag->ag.name==name, settings.args_groups)\n    already_added || push!(settings.args_groups, ArgParseGroup(name, desc, exclusive, required))\n    set_as_default && (settings.default_group = name)\n    return settings\nend\n\n\"\"\"\n    set_default_arg_group!(settings, [name])\n\nSet the default group for subsequent invocations of the [`@add_arg_table!`](@ref) macro and\n[`add_arg_table!`](@ref) function. `name` is a `String`, and must be one of the standard group names\n(`\"command\"`, `\"positional\"` or `\"optional\"`) or one of the user-defined names given in\n`add_arg_group!` (groups with no assigned name cannot be used with this function).\n\nIf `name` is not provided or is the empty string `\"\"`, then the default behavior is reset (i.e.\narguments will be automatically assigned to the standard groups). The `name` can also be passed as a\n`Symbol`.\n\"\"\"\nfunction set_default_arg_group!(settings::ArgParseSettings, name::Union{AbstractString,Symbol} = \"\")\n    name = string(name)\n    startswith(name, '#') && serror(\"invalid group name: $name (begins with #)\")\n    isempty(name) && (settings.default_group = \"\"; return)\n    found = any(ag->ag.name==name, settings.args_groups)\n    found || serror(\"group $name not found\")\n    settings.default_group = name\n    return\nend\n\n# import_settings! & friends\nfunction override_conflicts_with_commands!(settings::ArgParseSettings, new_cmd::AbstractString)\n    ids0 = Int[]\n    for ia in 1:length(settings.args_table.fields)\n        a = settings.args_table.fields[ia]\n        new_cmd == a.dest_name && push!(ids0, ia)\n    end\n    while !isempty(ids0)\n        splice!(settings.args_table.fields, pop!(ids0))\n    end\nend\nfunction override_duplicates!(args::Vector{ArgParseField}, new_arg::ArgParseField)\n    ids0 = Int[]\n    for (ia,a) in enumerate(args)\n        if (a.dest_name == new_arg.dest_name) &&\n            ((a.arg_type ≠ new_arg.arg_type) ||\n             (is_multi_action(a.action) && !is_multi_action(new_arg.action)) ||\n             (!is_multi_action(a.action) && is_multi_action(new_arg.action)))\n            # unsolvable conflict, mark for deletion\n            push!(ids0, ia)\n            continue\n        end\n        if is_arg(a) && is_arg(new_arg) && !(is_cmd(a) && is_cmd(new_arg)) &&\n            a.metavar == new_arg.metavar\n            # unsolvable conflict, mark for deletion\n            push!(ids0, ia)\n            continue\n        end\n\n        # delete conflicting command aliases for different commands\n        if is_cmd(a) && is_cmd(new_arg) && a.constant ≠ new_arg.constant\n            ids = Int[]\n            for (ial1, al1) in enumerate(a.cmd_aliases)\n                if al1 == new_arg.constant\n                    push!(ids, ial1)\n                else\n                    for al2 in new_arg.cmd_aliases\n                        al1 == al2 && push!(ids, ial1)\n                    end\n                end\n            end\n            while !isempty(ids)\n                splice!(a.cmd_aliases, pop!(ids))\n            end\n        end\n\n        if is_arg(a) || is_arg(new_arg)\n            # not an option, skip\n            continue\n        end\n\n        if is_cmd(a) && is_cmd(new_arg) && a.constant == new_arg.constant && !is_arg(a)\n            is_arg(new_arg) && found_a_bug() # this is ensured by check_settings_are_compatible\n            # two command flags with the same command -> should have already been taken care of,\n            # by either check_settings_are_compatible or merge_commands!\n            continue\n        end\n\n        # delete conflicting long options\n        ids = Int[]\n        for il1 = 1:length(a.long_opt_name), l2 in new_arg.long_opt_name\n            l1 = a.long_opt_name[il1]\n            l1 == l2 && push!(ids, il1)\n        end\n        while !isempty(ids)\n            splice!(a.long_opt_name, pop!(ids))\n        end\n\n        # delete conflicting short options\n        ids = Int[]\n        for is1 in 1:length(a.short_opt_name), s2 in new_arg.short_opt_name\n            s1 = a.short_opt_name[is1]\n            s1 == s2 && push!(ids, is1)\n        end\n        while !isempty(ids)\n            splice!(a.short_opt_name, pop!(ids))\n        end\n\n        # if everything was deleted, remove the field altogether\n        # (i.e. mark it for deletion)\n        isempty(a.long_opt_name) && isempty(a.short_opt_name) && push!(ids0, ia)\n    end\n\n    # actually remove the marked fields\n    while !isempty(ids0)\n        splice!(args, pop!(ids0))\n    end\nend\n\nfunction check_settings_are_compatible(settings::ArgParseSettings, other::ArgParseSettings)\n    table = settings.args_table\n    otable = other.args_table\n\n    for a in otable.fields\n        check_conflicts_with_commands(settings, a, true)\n        settings.error_on_conflict && check_for_duplicates(table.fields, a)\n    end\n\n    for (subk, subs) in otable.subsettings\n        settings.error_on_conflict && check_conflicts_with_commands(settings, subk)\n        haskey(settings, subk) && check_settings_are_compatible(settings[subk], subs)\n    end\n    return true\nend\n\nfunction merge_commands!(fields::Vector{ArgParseField}, ofields::Vector{ArgParseField})\n    oids = Int[]\n    for a in fields, ioa = 1:length(ofields)\n        oa = ofields[ioa]\n        if is_cmd(a) && is_cmd(oa) && a.constant == oa.constant\n            is_arg(a) ≠ is_arg(oa) && found_a_bug() # ensured by check_settings_are_compatible\n            for l in oa.long_opt_name\n                l ∈ a.long_opt_name || push!(a.long_opt_name, l)\n            end\n            for s in oa.short_opt_name\n                s ∈ a.short_opt_name || push!(a.short_opt_name, s)\n            end\n            for al in oa.cmd_aliases\n                al ∈ a.cmd_aliases || push!(a.cmd_aliases, al)\n            end\n            a.group = oa.group # note: the group may not be present yet, but it will be\n                               #       added later\n            push!(oids, ioa)\n        end\n    end\n    # we return the merged ofields indices, since we still need to use them for overriding options\n    # before we actually remove them\n    return oids\nend\n\nfunction fix_commands_fields!(fields::Vector{ArgParseField})\n    cmd_found = false\n    for a in fields\n        if is_arg(a) && is_cmd(a)\n            a.fake = cmd_found\n            cmd_found = true\n        end\n    end\nend\n\n\"\"\"\n    import_settings!(settings, other_settings [,args_only])\n\nImports `other_settings` into `settings`, where both are [`ArgParseSettings`](@ref) objects. If\n`args_only` is `true` (this is the default), only the argument table will be imported; otherwise,\nthe default argument group will also be imported, and all general settings except `prog`,\n`description`, `epilog`, `usage` and `version`.\n\nSub-settings associated with commands will also be imported recursively; the `args_only` setting\napplies to those as well. If there are common commands, their sub-settings will be merged.\n\nWhile importing, conflicts may arise: if `settings.error_on_conflict` is `true`, this will result in\nan error, otherwise conflicts will be resolved in favor of `other_settings` (see the\n[Conflicts and overrides](@ref) section for a detailed discussion of how conflicts are handled).\n\nArgument groups will also be imported; if two groups in `settings` and `other_settings` match, they\nare merged (groups match either by name, or, if unnamed, by their description).\n\nNote that the import will have effect immediately: any subsequent modification of `other_settings`\nwill not have any effect on `settings`.\n\nThis function can be used at any time.\n\"\"\"\nfunction import_settings!(settings::ArgParseSettings,\n                          other::ArgParseSettings;\n                          args_only::Bool = true)\n    check_settings_are_compatible(settings, other)\n\n    fields = settings.args_table.fields\n    ofields = deepcopy(other.args_table.fields)\n    merged_oids = merge_commands!(fields, ofields)\n    if !settings.error_on_conflict\n        for a in ofields\n            override_duplicates!(fields, a)\n        end\n        for (subk, subs) in other.args_table.subsettings\n            override_conflicts_with_commands!(settings, subk)\n        end\n    end\n    while !isempty(merged_oids)\n        splice!(ofields, pop!(merged_oids))\n    end\n    append!(fields, ofields)\n    for oag in other.args_groups\n        skip = false\n        for ag in settings.args_groups\n            # TODO: merge groups in some cases\n            if oag.name == ag.name\n                skip = true\n                break\n            end\n        end\n        skip && continue\n        push!(settings.args_groups, deepcopy(oag))\n    end\n\n    fix_commands_fields!(fields)\n\n    if !args_only\n        settings.add_help = other.add_help\n        settings.add_version = other.add_version\n        settings.error_on_conflict = other.error_on_conflict\n        settings.suppress_warnings = other.suppress_warnings\n        settings.exc_handler = other.exc_handler\n        settings.allow_ambiguous_opts = other.allow_ambiguous_opts\n        settings.commands_are_required = other.commands_are_required\n        settings.default_group = other.default_group\n        settings.preformatted_description = other.preformatted_description\n        settings.preformatted_epilog = other.preformatted_epilog\n        settings.fromfile_prefix_chars = other.fromfile_prefix_chars\n        settings.autofix_names = other.autofix_names\n        settings.exit_after_help = other.exit_after_help\n    end\n    for (subk, subs) in other.args_table.subsettings\n        cmd_prog_hint = \"\"\n        for oa in other.args_table.fields\n            if is_cmd(oa) && oa.constant == subk\n                cmd_prog_hint = get_cmd_prog_hint(oa)\n                break\n            end\n        end\n        if !haskey(settings, subk)\n            add_command!(settings, subk, cmd_prog_hint, !settings.error_on_conflict)\n        elseif !isempty(cmd_prog_hint)\n            settings[subk].prog = \"$(settings.prog) $cmd_prog_hint\"\n        end\n        import_settings!(settings[subk], subs, args_only=args_only)\n    end\n    return settings\nend\n\n\"\"\"\n    @project_version\n    @project_version(filename::String...)\n\nReads the version from the Project.toml file at the given filename, at compile time.\nIf no filename is given, defaults to `Base.current_project()`.\nIf multiple strings are given, they will be joined with `joinpath`.\nIntended for use with the [`ArgParseSettings`](@ref) constructor,\nto keep the settings version in sync with the project version.\n\n## Example\n\n```julia\nArgParseSettings(add_version = true, version = @project_version)\n```\n\"\"\"\nmacro project_version(filename::Vararg{String})\n    project_version(isempty(filename) ? Base.current_project() : joinpath(filename...))\nend\n\nfunction project_version(filename::AbstractString)::String\n    re = r\"^version\\s*=\\s*\\\"(.*)\\\"\\s*$\"\n    for line in eachline(filename)\n        if startswith(line, \"[\")\n            break\n        end\n        if !occursin(re, line)\n            continue\n        end\n        return match(re, line)[1]\n    end\n    throw(ArgumentError(\"Could not find a version in the file at $(filename)\"))\nend\n"
  },
  {
    "path": "test/Project.toml",
    "content": "version = \"1.0.0\"\n\n[deps]\nTest = \"8dfed614-e22c-5e08-85e1-65c5234f0b40\"\n"
  },
  {
    "path": "test/argparse_test01.jl",
    "content": "# test 01: minimal options/arguments, auto-generated help/version;\n#          function version of add_arg_table!\n\n@testset \"test 01\" begin\n\nfunction ap_settings1()\n\n    s = ArgParseSettings()\n\n    @add_arg_table! s begin\n        \"--opt1\"               # an option (will take an argument)\n        \"--opt2\", \"-o\"         # another option, with short form\n        \"arg1\"                 # a positional argument\n    end\n\n    s.exc_handler = ArgParse.debug_handler\n\n    return s\nend\n\nfunction ap_settings1b()\n\n    s = ArgParseSettings(exc_handler = ArgParse.debug_handler)\n\n    add_arg_table!(s,\n        \"--opt1\",\n        [\"--opt2\", \"-o\"],\n        \"arg1\")\n\n    return s\nend\n\n\nfor s = [ap_settings1(), ap_settings1b()]\n    ap_test1(args) = parse_args(args, s)\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--opt1 OPT1] [-o OPT2] [arg1]\n\n        positional arguments:\n          arg1\n\n        optional arguments:\n          --opt1 OPT1\n          -o, --opt2 OPT2\n\n        \"\"\"\n\n    @test ap_test1([]) == Dict{String,Any}(\"opt1\"=>nothing, \"opt2\"=>nothing, \"arg1\"=>nothing)\n    @test ap_test1([\"arg\"]) == Dict{String,Any}(\"opt1\"=>nothing, \"opt2\"=>nothing, \"arg1\"=>\"arg\")\n    @test ap_test1([\"--opt1\", \"X\", \"-o=5\", \"--\", \"-arg\"]) == Dict{String,Any}(\"opt1\"=>\"X\", \"opt2\"=>\"5\", \"arg1\"=>\"-arg\")\n    @test ap_test1([\"--opt1\", \"\"]) == Dict{String,Any}(\"opt1\"=>\"\", \"opt2\"=>nothing, \"arg1\"=>nothing)\n    @ap_test_throws ap_test1([\"--opt1\", \"X\", \"-o=5\", \"-arg\"])\n    @test ap_test1([\"--opt1=\", \"--opt2=5\"]) == Dict{String,Any}(\"opt1\"=>\"\", \"opt2\"=>\"5\", \"arg1\"=>nothing)\n    @test ap_test1([\"-o\", \"-2\"]) == Dict{String,Any}(\"opt1\"=>nothing, \"opt2\"=>\"-2\", \"arg1\"=>nothing)\n    @ap_test_throws ap_test1([\"--opt\", \"3\"]) # ambiguous\n    @ap_test_throws ap_test1([\"-o\"])\n    @ap_test_throws ap_test1([\"--opt1\"])\n\n    @aps_test_throws @add_arg_table!(s, \"--opt1\") # long option already added\n    @aps_test_throws @add_arg_table!(s, \"-o\") # short option already added\nend\n\n# test malformed tables\nfunction ap_settings1c()\n\n    @aps_test_throws @add_arg_table! begin\n        \"-a\"\n    end\n\n    s = ArgParseSettings(exc_handler = ArgParse.debug_handler)\n\n    @aps_test_throws add_arg_table!(s, Dict(:action => :store_true), \"-a\")\n    @test_addtable_failure s begin\n        action = :store_true\n        \"-a\"\n    end\n    @test_addtable_failure s begin\n        action => :store_true\n    end\n    @aps_test_throws add_arg_table!(s, \"-a\", Dict(:wat => :store_true))\n    @aps_test_throws @add_arg_table! s begin\n        \"-a\"\n            wat => :store_true\n    end\nend\n\nap_settings1c()\n\nend\n"
  },
  {
    "path": "test/argparse_test02.jl",
    "content": "# test 02: version information, default values, flags,\n#          options with types, optional arguments, variable\n#          number of arguments;\n#          function version of add_arg_table!\n\n@testset \"test 02\" begin\n\nfunction ap_settings2()\n\n    s = ArgParseSettings(description = \"Test 2 for ArgParse.jl\",\n                         epilog = \"Have fun!\",\n                         version = \"Version 1.0\",\n                         add_version = true,\n                         exc_handler = ArgParse.debug_handler)\n\n    @add_arg_table! s begin\n        \"--opt1\"\n            nargs = '?'              # '?' means optional argument\n            arg_type = Int           # only Int arguments allowed\n            default = 0              # this is used when the option is not passed\n            constant = 1             # this is used if --opt1 is paseed with no argument\n            help = \"an option\"\n        \"-O\"\n            arg_type = Symbol\n            default = :xyz\n            help = \"another option\"\n        \"--flag\", \"-f\"\n            action = :store_true   # this makes it a flag\n            help = \"a flag\"\n        \"--karma\", \"-k\"\n            action = :count_invocations  # increase a counter each time the option is given\n            help = \"increase karma\"\n        \"arg1\"\n            nargs = 2                        # eats up two arguments; puts the result in a Vector\n            help = \"first argument, two \" *\n                   \"entries at once\"\n            required = true\n        \"arg2\"\n            nargs = '*'                            # eats up as many arguments as possible before an option\n            default = Any[\"no_arg_given\"]          # since the result will be a Vector{Any}, the default must\n                                                   # also be (or it can be [] or nothing)\n            help = \"second argument, eats up \" *\n                   \"as many items as possible \" *\n                   \"before an option\"\n    end\n\n    return s\nend\n\nfunction ap_settings2b()\n\n    s = ArgParseSettings(description = \"Test 2 for ArgParse.jl\",\n                         epilog = \"Have fun!\",\n                         version = \"Version 1.0\",\n                         add_version = true,\n                         exc_handler = ArgParse.debug_handler)\n\n    add_arg_table!(s,\n        \"--opt1\", Dict(\n            :nargs => '?',             # '?' means optional argument\n            :arg_type => Int,          # only Int arguments allowed\n            :default => 0,             # this is used when the option is not passed\n            :constant => 1,            # this is used if --opt1 is paseed with no argument\n            :help => \"an option\"),\n        [\"-O\"], Dict(\n            :arg_type => Symbol,\n            :default => :xyz,\n            :help => \"another option\"),\n        [\"--flag\", \"-f\"], Dict(\n            :action => :store_true,  # this makes it a flag\n            :help => \"a flag\"),\n        [\"--karma\", \"-k\"], Dict(\n            :action => :count_invocations, # increase a counter each time the option is given\n            :help => \"increase karma\"),\n        \"arg1\", Dict(\n            :nargs => 2,                       # eats up two arguments; puts the result in a Vector\n            :help => \"first argument, two \" *\n                     \"entries at once\",\n            :required => true),\n        \"arg2\", Dict(\n            :nargs => '*',                           # eats up as many arguments as possible before an option\n            :default => Any[\"no_arg_given\"],         # since the result will be a Vector{Any}, the default must\n                                                   # also be (or it can be [] or nothing)\n            :help => \"second argument, eats up \" *\n                     \"as many items as possible \" *\n                     \"before an option\")\n    )\n\n    return s\nend\n\nfunction ap_settings2c()\n\n    s = ArgParseSettings(description = \"Test 2 for ArgParse.jl\",\n                         epilog = \"Have fun!\",\n                         version = \"Version 1.0\",\n                         add_version = true,\n                         exc_handler = ArgParse.debug_handler)\n\n    @add_arg_table!(s\n        , \"--opt1\"\n        ,     nargs = '?'              # '?' means optional argument\n        ,     arg_type = Int           # only Int arguments allowed\n        ,     default = 0              # this is used when the option is not passed\n        ,     constant = 1             # this is used if --opt1 is paseed with no argument\n        ,     help = \"an option\"\n        , \"-O\"\n        ,     arg_type = Symbol\n        ,     default = :xyz\n        ,     help = \"another option\"\n        , [\"--flag\", \"-f\"]\n        ,     action = :store_true   # this makes it a flag\n        ,     help = \"a flag\"\n        , [\"--karma\", \"-k\"]\n        ,     action = :count_invocations  # increase a counter each time the option is given\n        ,     help = \"increase karma\"\n        , \"arg1\"\n        ,     nargs = 2                        # eats up two arguments; puts the result in a Vector\n        ,     help = \"first argument, two \" *\n                     \"entries at once\"\n        ,     required = true\n        , \"arg2\"\n        ,     nargs = '*'                            # eats up as many arguments as possible before an option\n        ,     default = Any[\"no_arg_given\"]          # since the result will be a Vector{Any}, the default must\n                                                     # also be (or it can be [] or nothing)\n        ,     help = \"second argument, eats up \" *\n                     \"as many items as possible \" *\n                     \"before an option\"\n        )\n\n    return s\nend\n\nfunction ap_settings2d()\n\n    s = ArgParseSettings(description = \"Test 2 for ArgParse.jl\",\n                         epilog = \"Have fun!\",\n                         version = \"Version 1.0\",\n                         add_version = true,\n                         exc_handler = ArgParse.debug_handler)\n\n    @add_arg_table! s begin\n        (\"--opt1\";\n              nargs = '?';              # '?' means optional argument\n              arg_type = Int;           # only Int arguments allowed\n              default = 0;              # this is used when the option is not passed\n              constant = 1;             # this is used if --opt1 is paseed with no argument\n              help = \"an option\"),\n        (\"-O\";\n              arg_type = Symbol;\n              default = :xyz;\n              help = \"another option\"),\n        ([\"--flag\", \"-f\"];\n              action = :store_true;     # this makes it a flag\n              help = \"a flag\")\n        ([\"--karma\", \"-k\"];\n              action = :count_invocations; # increase a counter each time the option is given\n              help = \"increase karma\")\n        (\"arg1\";\n              nargs = 2;                       # eats up two arguments; puts the result in a Vector\n              help = \"first argument, two \" *\n                     \"entries at once\";\n              required = true)\n        (\"arg2\";\n              nargs = '*';                            # eats up as many arguments as possible before an option\n              default = Any[\"no_arg_given\"];          # since the result will be a Vector{Any}, the default must\n                                                      # also be (or it can be [] or nothing)\n              help = \"second argument, eats up \" *\n                     \"as many items as possible \" *\n                     \"before an option\")\n    end\n\n    return s\nend\n\nfunction ap_settings2e()\n\n    s = ArgParseSettings(description = \"Test 2 for ArgParse.jl\",\n                         epilog = \"Have fun!\",\n                         version = \"Version 1.0\",\n                         add_version = true,\n                         exc_handler = ArgParse.debug_handler)\n\n    @add_arg_table!(s,\n        \"--opt1\",\n        begin\n            nargs = '?'              # '?' means optional argument\n            arg_type = Int           # only Int arguments allowed\n            default = 0              # this is used when the option is not passed\n            constant = 1             # this is used if --opt1 is paseed with no argument\n            help = \"an option\"\n        end,\n        \"-O\",\n        begin\n            arg_type = Symbol\n            default = :xyz\n            help = \"another option\"\n        end,\n        [\"--flag\", \"-f\"],\n        begin\n            action = :store_true   # this makes it a flag\n            help = \"a flag\"\n        end,\n        [\"--karma\", \"-k\"],\n        begin\n            action = :count_invocations  # increase a counter each time the option is given\n            help = \"increase karma\"\n        end,\n        \"arg1\",\n        begin\n            nargs = 2                        # eats up two arguments; puts the result in a Vector\n            help = \"first argument, two \" *\n                   \"entries at once\"\n            required = true\n        end,\n        \"arg2\",\n        begin\n            nargs = '*'                            # eats up as many arguments as possible before an option\n            default = Any[\"no_arg_given\"]          # since the result will be a Vector{Any}, the default must\n                                                   # also be (or it can be [] or nothing)\n            help = \"second argument, eats up \" *\n                   \"as many items as possible \" *\n                   \"before an option\"\n        end)\n\n    return s\nend\n\nfor s = [ap_settings2(), ap_settings2b(), ap_settings2c(), ap_settings2d(), ap_settings2e()]\n    ap_test2(args) = parse_args(args, s)\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--opt1 [OPT1]] [-O O] [-f] [-k] arg1 arg1\n                                [arg2...]\n\n        Test 2 for ArgParse.jl\n\n        positional arguments:\n          arg1           first argument, two entries at once\n          arg2           second argument, eats up as many items as possible\n                         before an option (default: Any[\"no_arg_given\"])\n\n        optional arguments:\n          --opt1 [OPT1]  an option (type: $Int, default: 0, without arg: 1)\n          -O O           another option (type: $Symbol, default: :xyz)\n          -f, --flag     a flag\n          -k, --karma    increase karma\n\n        Have fun!\n\n        \"\"\"\n\n    @test stringversion(s) == \"Version 1.0\\n\"\n\n    @ap_test_throws ap_test2([])\n    @test ap_test2([\"X\", \"Y\"]) == Dict{String,Any}(\"opt1\"=>0, \"O\"=>:xyz, \"flag\"=>false, \"karma\"=>0, \"arg1\"=>Any[\"X\", \"Y\"], \"arg2\"=>Any[\"no_arg_given\"])\n    @test ap_test2([\"X\", \"Y\", \"-k\", \"-f\", \"Z\", \"--karma\", \"--opt\"]) == Dict{String,Any}(\"opt1\"=>1, \"O\"=>:xyz, \"flag\"=>true, \"karma\"=>2, \"arg1\"=>Any[\"X\", \"Y\"], \"arg2\"=>Any[\"Z\"])\n    @test ap_test2([\"X\", \"Y\", \"--opt\", \"-k\", \"-f\", \"Z\", \"--karma\"]) == Dict{String,Any}(\"opt1\"=>1, \"O\"=>:xyz, \"flag\"=>true, \"karma\"=>2, \"arg1\"=>Any[\"X\", \"Y\"], \"arg2\"=>Any[\"Z\"])\n    @test ap_test2([\"X\", \"Y\", \"--opt\", \"--karma\", \"-O\", \"XYZ\", \"-f\", \"Z\", \"-k\"]) == Dict{String,Any}(\"opt1\"=>1, \"O\"=>:XYZ, \"flag\"=>true, \"karma\"=>2, \"arg1\"=>Any[\"X\", \"Y\"], \"arg2\"=>Any[\"Z\"])\n    @test ap_test2([\"--opt\", \"-3\", \"X\", \"Y\", \"-k\", \"-f\", \"Z\", \"-O\", \"a b c\", \"--karma\"]) == Dict{String,Any}(\"opt1\"=>-3, \"O\"=>Symbol(\"a b c\"), \"flag\"=>true, \"karma\"=>2, \"arg1\"=>Any[\"X\", \"Y\"], \"arg2\"=>Any[\"Z\"])\n    @ap_test_throws ap_test2([\"--opt\"])\n    @ap_test_throws ap_test2([\"--opt=\"])\n    @ap_test_throws ap_test2([\"--opt\", \"\", \"X\", \"Y\"])\n    @ap_test_throws ap_test2([\"--opt\", \"1e-2\", \"X\", \"Y\"])\n\n    @aps_test_throws @add_arg_table!(s, \"required_arg_after_optional_args\", required = true)\n    # wrong default\n    @aps_test_throws @add_arg_table!(s, \"--opt\", arg_type = Int, default = 1.5)\n    @aps_test_throws @add_arg_table!(s, \"--opt3\", arg_type = Function, default = \"string\")\n    # wrong range tester\n    @aps_test_throws @add_arg_table!(s, \"--opt\", arg_type = Int, range_tester = x->string(x), default = 1)\n    @aps_test_throws @add_arg_table!(s, \"--opt\", arg_type = Int, range_tester = x->sqrt(x)<1, default = -1)\nend\n\nend\n"
  },
  {
    "path": "test/argparse_test03.jl",
    "content": "# test 03: dest_name, metavar, range_tester, alternative\n#          actions, custom parser\n\nstruct CustomType\nend\n\n@testset \"test 03\" begin\n\nfunction ArgParse.parse_item(::Type{CustomType}, x::AbstractString)\n    @assert x == \"custom\"\n    return CustomType()\nend\n\nBase.show(io::IO, ::Type{CustomType}) = print(io, \"CustomType\")\nBase.show(io::IO, c::CustomType) = print(io, \"CustomType()\")\n\nfunction ap_settings3()\n\n    s = ArgParseSettings(\"Test 3 for ArgParse.jl\",\n                         exc_handler = ArgParse.debug_handler)\n\n    @add_arg_table! s begin\n        \"--opt1\"\n            action = :append_const   # appends 'constant' to 'dest_name'\n            arg_type = String\n            constant = \"O1\"\n            dest_name = \"O_stack\"    # this changes the destination\n            help = \"append O1\"\n        \"--opt2\"\n            action = :append_const\n            arg_type = String\n            constant = \"O2\"\n            dest_name = \"O_stack\"    # same dest_name as opt1, different constant\n            help = \"append O2\"\n        \"-k\"\n            action = :store_const    # stores constant if given, default otherwise\n            default = 0\n            constant = 42\n            help = \"provide the answer\"\n        \"-u\"\n            action = :store_const    # stores constant if given, default otherwise\n            default = 0\n            constant = 42.0\n            help = \"provide the answer as floating point\"\n        \"--array\"\n            default = [7, 3, 2]\n            arg_type = Vector{Int}\n            eval_arg = true          # enables evaluation of the argument. NOTE: security risk!\n            help = \"create an array\"\n        \"--custom\"\n            default = CustomType()\n            arg_type = CustomType    # uses the user-defined version of ArgParse.parse_item\n            help = \"the only accepted argument is \\\"custom\\\"\"\n        \"--oddint\"\n            default = 1\n            arg_type = Int\n            range_tester = x->(isodd(x) || error(\"not odd\")) # range error ≡ false\n            help = \"an odd integer\"\n        \"--collect\"\n            action = :append_arg\n            arg_type = Int\n            metavar = \"C\"\n            help = \"collect things\"\n        \"--awkward-option\"\n            nargs = '+'                         # eats up as many argument as found (at least 1)\n            action = :append_arg                # argument chunks are appended when the option is\n                                                # called repeatedly\n            dest_name = \"awk\"\n            range_tester = (x->x==\"X\"||x==\"Y\")  # each argument must be either \"X\" or \"Y\"\n            default = [[\"X\"]]\n            metavar = \"XY\"\n            help = \"either X or Y; all XY's are \" *\n                   \"stored in chunks\"\n    end\n\n    return s\nend\n\nlet s = ap_settings3()\n    ap_test3(args) = parse_args(args, s)\n\n    ## ugly workaround for the change of printing Vectors in julia 1.6,\n    ## from Array{Int,1} to Vector{Int}\n    array_help_lines = if string(Vector{Any}) == \"Vector{Any}\"\n        \"\"\"\n          --array ARRAY         create an array (type: Vector{$Int}, default:\n                                $([7, 3, 2]))\n        \"\"\"\n    else\n        \"\"\"\n          --array ARRAY         create an array (type: Array{$Int,1},\n                                default: $([7, 3, 2]))\n        \"\"\"\n    end\n    array_help_lines = array_help_lines[1:end-1] # remove an extra newline\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--opt1] [--opt2] [-k] [-u] [--array ARRAY]\n                                [--custom CUSTOM] [--oddint ODDINT]\n                                [--collect C] [--awkward-option XY [XY...]]\n\n        Test 3 for ArgParse.jl\n\n        optional arguments:\n          --opt1                append O1\n          --opt2                append O2\n          -k                    provide the answer\n          -u                    provide the answer as floating point\n        $array_help_lines\n          --custom CUSTOM       the only accepted argument is \"custom\" (type:\n                                CustomType, default: CustomType())\n          --oddint ODDINT       an odd integer (type: $Int, default: 1)\n          --collect C           collect things (type: $Int)\n          --awkward-option XY [XY...]\n                                either X or Y; all XY's are stored in chunks\n                                (default: $(Vector{Any})[[\"X\"]])\n\n        \"\"\"\n\n    @test ap_test3([]) == Dict{String,Any}(\"O_stack\"=>String[], \"k\"=>0, \"u\"=>0, \"array\"=>[7, 3, 2], \"custom\"=>CustomType(), \"oddint\"=>1, \"collect\"=>[], \"awk\"=>Any[Any[\"X\"]])\n    @test ap_test3([\"--opt1\", \"--awk\", \"X\", \"X\", \"--opt2\", \"--opt2\", \"-k\", \"--coll\", \"5\", \"-u\", \"--array=[4]\", \"--custom\", \"custom\", \"--collect\", \"3\", \"--awkward-option=Y\", \"X\", \"--opt1\", \"--oddint\", \"-1\"]) ==\n    Dict{String,Any}(\"O_stack\"=>String[\"O1\", \"O2\", \"O2\", \"O1\"], \"k\"=>42, \"u\"=>42.0, \"array\"=>[4], \"custom\"=>CustomType(), \"oddint\"=>-1, \"collect\"=>[5, 3], \"awk\"=>Any[Any[\"X\"], Any[\"X\", \"X\"], Any[\"Y\", \"X\"]])\n    @ap_test_throws ap_test3([\"X\"])\n    @ap_test_throws ap_test3([\"--awk\", \"Z\"])\n    @ap_test_throws ap_test3([\"--awk\", \"-2\"])\n    @ap_test_throws ap_test3([\"--array\", \"7\"])\n    @ap_test_throws ap_test3([\"--custom\", \"default\"])\n    @ap_test_throws ap_test3([\"--oddint\", \"0\"])\n    @ap_test_throws ap_test3([\"--collect\", \"0.5\"])\n\n    # invalid option name\n    @aps_test_throws @add_arg_table!(s, \"-2\", action = :store_true)\n    # wrong constants\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :store_const, arg_type = Int, default = 1, constant = 1.5)\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :append_const, arg_type = Int, constant = 1.5)\n    # wrong defaults\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :append_arg, arg_type = Int, default = String[\"hello\"])\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :append_arg, nargs = '+', arg_type = Int, default = Vector{Float64}[[1.5]])\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :store_arg, nargs = '+', arg_type = Int, default = [1.5])\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :store_arg, nargs = '+', arg_type = Int, default = 1)\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :append_arg, arg_type = Int, range_tester=x->x<=1, default = Int[0, 1, 2])\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :append_arg, nargs = '+', arg_type = Int, range_tester=x->x<=1, default = Vector{Int}[[1,1],[0,2]])\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :store_arg, nargs = '+', range_tester = x->x<=1, default = [1.5])\n    # no constants\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :store_const, arg_type = Int, default = 1)\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :append_const, arg_type = Int)\n    # incompatible action\n    @aps_test_throws @add_arg_table!(s, \"--opt3\", action = :store_const, arg_type = String, constant = \"O3\", dest_name = \"O_stack\", help = \"append O3\")\n    # wrong range tester\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :append_arg, arg_type = Int, range_tester=x->string(x), default = Int[0, 1, 2])\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :append_arg, nargs = '+', arg_type = Int, range_tester=x->string(x), default = Vector{Int}[[1,1],[0,2]])\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :store_arg, nargs = '+', range_tester = x->string(x), default = [1.5])\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :store_arg, nargs = '+', range_tester = x->sqrt(x)<2, default = [-1.5])\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :append_arg, nargs = '+', arg_type = Int, range_tester=x->sqrt(x)<2, default = Vector{Int}[[1,1],[0,-2]])\n\n    # allow ambiguous options\n    s.allow_ambiguous_opts = true\n    @add_arg_table!(s, \"-2\", action = :store_true)\n    @test ap_test3([]) == Dict{String,Any}(\"O_stack\"=>String[], \"k\"=>0, \"u\"=>0, \"array\"=>[7, 3, 2], \"custom\"=>CustomType(), \"oddint\"=>1, \"collect\"=>[], \"awk\"=>Vector{Any}[[\"X\"]], \"2\"=>false)\n    @test ap_test3([\"-2\"]) == Dict{String,Any}(\"O_stack\"=>String[], \"k\"=>0, \"u\"=>0, \"array\"=>[7, 3, 2], \"custom\"=>CustomType(), \"oddint\"=>1, \"collect\"=>[], \"awk\"=>Vector{Any}[[\"X\"]], \"2\"=>true)\n    @test ap_test3([\"--awk\", \"X\", \"-2\"]) == Dict{String,Any}(\"O_stack\"=>String[], \"k\"=>0, \"u\"=>0, \"array\"=>[7, 3, 2], \"custom\"=>CustomType(), \"oddint\"=>1, \"collect\"=>[], \"awk\"=>Vector{Any}[[\"X\"], [\"X\"]], \"2\"=>true)\n    @ap_test_throws ap_test3([\"--awk\", \"X\", \"-3\"])\n\nend\n\nend\n"
  },
  {
    "path": "test/argparse_test04.jl",
    "content": "# test 04: manual help/version, import another parser\n\n@testset \"test 04\" begin\n\nfunction ap_settings4()\n\n    s0 = ArgParseSettings()  # a \"parent\" structure e.g. one with some useful set of rules\n                             # which we want to extend\n\n    # So we just add a simple table\n    @add_arg_table! s0 begin\n        \"--parent-flag\", \"-o\"\n            action = \"store_true\"\n            help = \"parent flag\"\n        \"--flag\"\n            action = \"store_true\"\n            help = \"another parent flag\"\n        \"parent-argument\"\n            help = \"parent argument\"\n        \"will-be-overridden\"\n            metavar = \"ARG\"\n    end\n\n    s = ArgParseSettings(\"Test 4 for ArgParse.jl\",\n                         add_help = false,           # disable auto-add of --help option\n                         version = \"Version 1.0\",    # we set the version info, but --version won't be added\n                         error_on_conflict = false,  # do not error-out when trying to override an option\n                         exc_handler = ArgParse.debug_handler)\n\n    import_settings!(s, s0)        # now s has all of s0 arguments (except help/version)\n\n    @add_arg_table! s begin\n        \"-o\"                       # this will partially override s0's --parent-flag\n            action = :store_true\n            help = \"child flag\"\n        \"--flag\"                   # this will fully override s0's --flag\n            action = :store_true\n            help = \"another child flag\"\n        \"-?\", \"--HELP\", \"--¡ḧëļṕ\"                # (almost) all characters allowed\n            action = :show_help                  # will invoke the help generator\n            help = \"this will help you\"\n        \"-v\", \"--VERSION\"\n            action = :show_version               # will show version information\n            help = \"show version information \" *\n                   \"and exit\"\n        \"child-argument\"            # same metavar as \"will-be-overridden\"\n            metavar = \"ARG\"\n            help = \"child argument\"\n    end\n\n    return s\nend\n\nfunction ap_settings4b()\n\n    # same as ap_settings4(), but imports all settings\n\n    s0 = ArgParseSettings(add_help = false,\n                          error_on_conflict = false,\n                          exc_handler = ArgParse.debug_handler)\n\n    # So we just add a simple table\n    @add_arg_table! s0 begin\n        \"--parent-flag\", \"-o\"\n            action = \"store_true\"\n            help = \"parent flag\"\n        \"--flag\"\n            action = \"store_true\"\n            help = \"another parent flag\"\n        \"parent-argument\"\n            help = \"parent argument\"\n        \"will-be-overridden\"\n            metavar = \"ARG\"\n    end\n\n    s = ArgParseSettings(\"Test 4 for ArgParse.jl\",\n                         version = \"Version 1.0\")\n\n    import_settings!(s, s0, args_only=false)\n\n    @add_arg_table! s begin\n        \"-o\"\n            action = :store_true\n            help = \"child flag\"\n        \"--flag\"\n            action = :store_true\n            help = \"another child flag\"\n        \"-?\", \"--HELP\", \"--¡ḧëļṕ\"\n            action = :show_help\n            help = \"this will help you\"\n        \"-v\", \"--VERSION\"\n            action = :show_version\n            help = \"show version information \" *\n                   \"and exit\"\n        \"child-argument\"\n            metavar = \"ARG\"\n            help = \"child argument\"\n    end\n\n    return s\nend\n\n\nfor s = [ap_settings4(), ap_settings4b()]\n    ap_test4(args) = parse_args(args, s)\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--parent-flag] [-o] [--flag] [-?] [-v]\n                                [parent-argument] [ARG]\n\n        Test 4 for ArgParse.jl\n\n        positional arguments:\n          parent-argument      parent argument\n          ARG                  child argument\n\n        optional arguments:\n          --parent-flag        parent flag\n          -o                   child flag\n          --flag               another child flag\n          -?, --HELP, --¡ḧëļṕ  this will help you\n          -v, --VERSION        show version information and exit\n\n        \"\"\"\n\n    @test stringversion(s) == \"Version 1.0\\n\"\n\n    @test ap_test4([]) == Dict{String,Any}(\"parent-flag\"=>false, \"o\"=>false, \"flag\"=>false, \"parent-argument\"=>nothing, \"child-argument\"=>nothing)\n    @test ap_test4([\"-o\", \"X\"]) == Dict{String,Any}(\"parent-flag\"=>false, \"o\"=>true, \"flag\"=>false, \"parent-argument\"=>\"X\", \"child-argument\"=>nothing)\n    @ap_test_throws ap_test4([\"-h\"])\n\n    # same metavar as another argument\n    s.error_on_conflict = true\n    @aps_test_throws @add_arg_table!(s, \"other-arg\", metavar=\"parent-argument\")\nend\n\n\nfunction ap_settings4_base()\n\n    s = ArgParseSettings(\"Test 4 for ArgParse.jl\",\n                         add_help = false,\n                         version = \"Version 1.0\",\n                         exc_handler = ArgParse.debug_handler)\n\n    @add_arg_table! s begin\n        \"-o\"\n            action = :store_true\n            help = \"child flag\"\n        \"--flag\"\n            action = :store_true\n            help = \"another child flag\"\n    end\n\n    return s\nend\n\nfunction ap_settings4_conflict1()\n\n    s0 = ArgParseSettings()\n\n    @add_arg_table! s0 begin\n        \"--parent-flag\", \"-o\"\n            action = \"store_true\"\n            help = \"parent flag\"\n    end\n\n    return s0\nend\n\nfunction ap_settings4_conflict2()\n\n    s0 = ArgParseSettings()\n\n    @add_arg_table! s0 begin\n        \"--flag\"\n            action = \"store_true\"\n            help = \"another parent flag\"\n    end\n\n    return s0\nend\n\nlet s = ap_settings4_base()\n\n    for s0 = [ap_settings4_conflict1(), ap_settings4_conflict2()]\n        @aps_test_throws import_settings!(s, s0)\n    end\nend\n\nend\n"
  },
  {
    "path": "test/argparse_test05.jl",
    "content": "# test 05: commands & subtables\n\n@testset \"test 05\" begin\n\nfunction ap_settings5()\n\n    s = ArgParseSettings(\"Test 5 for ArgParse.jl\",\n                         exc_handler = ArgParse.debug_handler,\n                         exit_after_help = false)\n\n    @add_arg_table! s begin\n        \"run\"\n            action = :command\n            help = \"start running mode\"\n        \"jump\", \"ju\", \"J\"\n            action = :command\n            help = \"start jumping mode\"\n    end\n\n    @add_arg_table! s[\"run\"] begin\n        \"--speed\"\n            arg_type = Float64\n            default = 10.0\n            help = \"running speed, in Å/month\"\n    end\n\n    s[\"jump\"].description = \"Jump mode\"\n    s[\"jump\"].commands_are_required = false\n    s[\"jump\"].autofix_names = true\n\n    @add_arg_table! s[\"jump\"] begin\n        \"--higher\"\n            action = :store_true\n            help = \"enhance jumping\"\n        \"--somersault\", \"-s\"\n            action = :command\n            dest_name = \"som\"\n            help = \"somersault jumping mode\"\n        \"--clap-feet\", \"-c\"\n            action = :command\n            help = \"clap feet jumping mode\"\n    end\n\n    s[\"jump\"][\"som\"].description = \"Somersault jump mode\"\n\n    @add_arg_table! s[\"jump\"][\"som\"] begin\n        \"-t\"\n            nargs = '?'\n            arg_type = Int\n            default = 1\n            constant = 1\n            help = \"twist a number of times\"\n        \"-b\"\n            action = :store_true\n            help = \"blink\"\n    end\n\n    return s\nend\n\nlet s = ap_settings5()\n    ap_test5(args; kw...) = parse_args(args, s; kw...)\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) {run|jump}\n\n        Test 5 for ArgParse.jl\n\n        commands:\n          run   start running mode\n          jump  start jumping mode (aliases: ju, J)\n\n        \"\"\"\n\n    @test stringhelp(s[\"run\"]) == \"\"\"\n        usage: $(basename(Base.source_path())) run [--speed SPEED]\n\n        optional arguments:\n          --speed SPEED  running speed, in Å/month (type: Float64, default:\n                         10.0)\n\n        \"\"\"\n\n    @test stringhelp(s[\"jump\"]) == \"\"\"\n        usage: $(basename(Base.source_path())) jump [--higher] [-s|-c]\n\n        Jump mode\n\n        commands:\n          -s, --somersault  somersault jumping mode\n          -c, --clap-feet   clap feet jumping mode\n\n        optional arguments:\n          --higher          enhance jumping\n\n        \"\"\"\n\n    @test stringhelp(s[\"jump\"][\"som\"]) == \"\"\"\n        usage: $(basename(Base.source_path())) jump -s [-t [T]] [-b]\n\n        Somersault jump mode\n\n        optional arguments:\n          -t [T]  twist a number of times (type: $Int, default: 1, without\n                  arg: 1)\n          -b      blink\n\n        \"\"\"\n\n    @ap_test_throws ap_test5([])\n    @noout_test ap_test5([\"--help\"]) ≡ nothing\n    @test ap_test5([\"run\", \"--speed\", \"3\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"run\", \"run\"=>Dict{String,Any}(\"speed\"=>3.0))\n    @noout_test ap_test5([\"jump\", \"--help\"]) ≡ nothing\n    @test ap_test5([\"jump\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"jump\"=>Dict{String,Any}(\"higher\"=>false, \"%COMMAND%\"=>nothing))\n    @test ap_test5([\"jump\", \"--higher\", \"--clap\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"jump\"=>Dict{String,Any}(\"higher\"=>true, \"%COMMAND%\"=>\"clap_feet\", \"clap_feet\"=>Dict{String,Any}()))\n    @test ap_test5([\"ju\", \"--higher\", \"--clap\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"jump\"=>Dict{String,Any}(\"higher\"=>true, \"%COMMAND%\"=>\"clap_feet\", \"clap_feet\"=>Dict{String,Any}()))\n    @test ap_test5([\"J\", \"--higher\", \"--clap\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"jump\"=>Dict{String,Any}(\"higher\"=>true, \"%COMMAND%\"=>\"clap_feet\", \"clap_feet\"=>Dict{String,Any}()))\n    @noout_test ap_test5([\"jump\", \"--higher\", \"--clap\", \"--help\"]) ≡ nothing\n    @noout_test ap_test5([\"jump\", \"--higher\", \"--clap\", \"--help\"], as_symbols = true) ≡ nothing\n    @ap_test_throws ap_test5([\"jump\", \"--clap\", \"--higher\"])\n    @test ap_test5([\"jump\", \"--somersault\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"jump\"=>Dict{String,Any}(\"higher\"=>false, \"%COMMAND%\"=>\"som\", \"som\"=>Dict{String,Any}(\"t\"=>1, \"b\"=>false)))\n    @test ap_test5([\"jump\", \"-s\", \"-t\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"jump\"=>Dict{String,Any}(\"higher\"=>false, \"%COMMAND%\"=>\"som\", \"som\"=>Dict{String,Any}(\"t\"=>1, \"b\"=>false)))\n    @test ap_test5([\"jump\", \"-st\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"jump\"=>Dict{String,Any}(\"higher\"=>false, \"%COMMAND%\"=>\"som\", \"som\"=>Dict{String,Any}(\"t\"=>1, \"b\"=>false)))\n    @test ap_test5([\"jump\", \"-sbt\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"jump\"=>Dict{String,Any}(\"higher\"=>false, \"%COMMAND%\"=>\"som\", \"som\"=>Dict{String,Any}(\"t\"=>1, \"b\"=>true)))\n    @test ap_test5([\"jump\", \"-s\", \"-t2\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"jump\"=>Dict{String,Any}(\"higher\"=>false, \"%COMMAND%\"=>\"som\", \"som\"=>Dict{String,Any}(\"t\"=>2, \"b\"=>false)))\n    @test ap_test5([\"jump\", \"-sbt2\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"jump\"=>Dict{String,Any}(\"higher\"=>false, \"%COMMAND%\"=>\"som\", \"som\"=>Dict{String,Any}(\"t\"=>2, \"b\"=>true)))\n    @test ap_test5([\"ju\", \"-sbt2\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"jump\"=>Dict{String,Any}(\"higher\"=>false, \"%COMMAND%\"=>\"som\", \"som\"=>Dict{String,Any}(\"t\"=>2, \"b\"=>true)))\n    @test ap_test5([\"J\", \"-sbt2\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"jump\"=>Dict{String,Any}(\"higher\"=>false, \"%COMMAND%\"=>\"som\", \"som\"=>Dict{String,Any}(\"t\"=>2, \"b\"=>true)))\n    @noout_test ap_test5([\"jump\", \"-sbht2\"]) ≡ nothing\n    @ap_test_throws ap_test5([\"jump\", \"-st2b\"])\n    @ap_test_throws ap_test5([\"jump\", \"-stb\"])\n    @ap_test_throws ap_test5([\"jump\", \"-sb-\"])\n    @ap_test_throws ap_test5([\"jump\", \"-s-b\"])\n    @ap_test_throws ap_test5([\"ju\", \"-s-b\"])\n    @test ap_test5([\"jump\", \"--higher\"], as_symbols = true) == Dict{Symbol,Any}(:_COMMAND_=>:jump, :jump=>Dict{Symbol,Any}(:higher=>true, :_COMMAND_=>nothing))\n    @test ap_test5([\"run\", \"--speed\", \"3\"], as_symbols = true) == Dict{Symbol,Any}(:_COMMAND_=>:run, :run=>Dict{Symbol,Any}(:speed=>3.0))\n\n    # argument after command\n    @aps_test_throws @add_arg_table!(s, \"arg_after_command\")\n    # same name as command\n    @aps_test_throws @add_arg_table!(s, \"run\")\n    @aps_test_throws @add_arg_table!(s[\"jump\"], \"-c\")\n    @aps_test_throws @add_arg_table!(s[\"jump\"], \"--somersault\")\n    # same dest_name as command\n    @aps_test_throws @add_arg_table!(s[\"jump\"], \"--som\")\n    @aps_test_throws @add_arg_table!(s[\"jump\"], \"-s\", dest_name = \"som\")\n    # same name as command alias\n    @aps_test_throws @add_arg_table!(s, \"ju\")\n    @aps_test_throws @add_arg_table!(s, \"J\")\n    # new command with the same name as another one\n    @aps_test_throws @add_arg_table!(s, [\"run\", \"R\"], action = :command)\n    @aps_test_throws @add_arg_table!(s, \"jump\", action = :command)\n    # new command with the same name as another one's alias\n    @aps_test_throws @add_arg_table!(s, \"ju\", action = :command)\n    @aps_test_throws @add_arg_table!(s, \"J\", action = :command)\n    # new command with an alias which is the same as another command\n    @aps_test_throws @add_arg_table!(s, [\"fast\", \"run\"], action = :command)\n    @aps_test_throws @add_arg_table!(s, [\"R\", \"jump\"], action = :command)\n    # new command with an alias which is already in use\n    @aps_test_throws @add_arg_table!(s, [\"R\", \"ju\"], action = :command)\n    @aps_test_throws @add_arg_table!(s, [\"R\", \"S\", \"J\"], action = :command)\n\n    # alias overriding by a command name\n    @add_arg_table!(s, \"J\", action = :command, force_override = true, help = \"the J command\")\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) {run|jump|J}\n\n        Test 5 for ArgParse.jl\n\n        commands:\n          run   start running mode\n          jump  start jumping mode (aliases: ju)\n          J     the J command\n\n        \"\"\"\n\n    # alias overriding by a command alias\n    @add_arg_table!(s, [\"S\", \"ju\"], action = :command, force_override = true, help = \"the S command\")\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) {run|jump|J|S}\n\n        Test 5 for ArgParse.jl\n\n        commands:\n          run   start running mode\n          jump  start jumping mode\n          J     the J command\n          S     the S command (aliases: ju)\n\n        \"\"\"\n\n    # cannot override a command name\n    @aps_test_throws @add_arg_table!(s, [\"J\", \"R\"], action = :command, force_override = true)\n    @aps_test_throws @add_arg_table!(s, [\"R\", \"J\"], action = :command, force_override = true)\n\n    # conflict between dest_name and a reserved Symbol\n    @add_arg_table!(s, \"--COMMAND\", dest_name=\"_COMMAND_\")\n    @aps_test_throws ap_test5([\"run\", \"--speed\", \"3\"], as_symbols = true)\nend\n\nfunction ap_settings5b()\n\n    s0 = ArgParseSettings()\n\n    s = ArgParseSettings(error_on_conflict = false,\n                         exc_handler = ArgParse.debug_handler,\n                         exit_after_help = false)\n\n    @add_arg_table! s0 begin\n        \"run\", \"R\"\n            action = :command\n            help = \"start running mode\"\n        \"jump\", \"ju\"\n            action = :command\n            help = \"start jumping mode\"\n        \"--time\"\n            arg_type = String\n            default = \"now\"\n            metavar = \"T\"\n            help = \"time at which to \" *\n                   \"perform the command\"\n    end\n\n    @add_arg_table! s0[\"run\"] begin\n        \"--speed\"\n            arg_type = Float64\n            default = 10.\n            help = \"running speed, in Å/month\"\n    end\n\n    s0[\"jump\"].description = \"Jump mode\"\n    s0[\"jump\"].commands_are_required = false\n    s0[\"jump\"].autofix_names = true\n    s0[\"jump\"].add_help = false\n\n    add_arg_group!(s0[\"jump\"], \"modifiers\", \"modifiers\")\n    set_default_arg_group!(s0[\"jump\"])\n\n    @add_arg_table! s0[\"jump\"] begin\n        \"--higher\"\n            action = :store_true\n            help = \"enhance jumping\"\n            group = \"modifiers\"\n        \"--somersault\"\n            action = :command\n            dest_name = \"som\"\n            help = \"somersault jumping mode\"\n        \"--clap-feet\", \"-c\"\n            action = :command\n            help = \"clap feet jumping mode\"\n    end\n\n    add_arg_group!(s0[\"jump\"], \"other\")\n    @add_arg_table! s0[\"jump\"] begin\n        \"--help\"\n            action = :show_help\n            help = \"show this help message \" *\n                   \"and exit\"\n    end\n\n    s0[\"jump\"][\"som\"].description = \"Somersault jump mode\"\n\n    @add_arg_table! s begin\n        \"jump\", \"run\", \"J\"              # The \"run\" alias will be overridden\n            action = :command\n            help = \"start jumping mode\"\n        \"fly\", \"R\"                      # The \"R\" alias will be overridden\n            action = :command\n            help = \"start flying mode\"\n        # next opt will be overridden (same dest_name as s0's --time,\n        # incompatible arg_type)\n        \"-T\"\n            dest_name = \"time\"\n            arg_type = Int\n    end\n\n    s[\"jump\"].autofix_names = true\n    s[\"jump\"].add_help = false\n\n    add_arg_group!(s[\"jump\"], \"modifiers\", \"modifiers\")\n    @add_arg_table! s[\"jump\"] begin\n        \"--lower\"\n            action = :store_false\n            dest_name = \"higher\"\n            help = \"reduce jumping\"\n    end\n\n    set_default_arg_group!(s[\"jump\"])\n\n    @add_arg_table! s[\"jump\"] begin\n        \"--clap-feet\"\n            action = :command\n            help = \"clap feet jumping mode\"\n        \"--som\", \"-s\" # will be overridden (same dest_name as s0 command)\n            action = :store_true\n            help = \"overridden\"\n        \"--somersault\" # will be overridden (same option as s0 command)\n            action = :store_true\n            help = \"overridden\"\n    end\n\n    @add_arg_table! s[\"fly\"] begin\n        \"--glade\"\n            action = :store_true\n            help = \"glade mode\"\n    end\n\n    s[\"jump\"][\"clap_feet\"].add_version = true\n\n    @add_arg_table! s[\"jump\"][\"clap_feet\"] begin\n        \"--whistle\"\n            action = :store_true\n    end\n\n    import_settings!(s, s0)\n\n    return s\nend\n\nlet s = ap_settings5b()\n    ap_test5b(args) = parse_args(args, s)\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--time T] {jump|fly|run}\n\n        commands:\n          jump      start jumping mode (aliases: J, ju)\n          fly       start flying mode\n          run       start running mode (aliases: R)\n\n        optional arguments:\n          --time T  time at which to perform the command (default: \"now\")\n\n        \"\"\"\n\n    @test stringhelp(s[\"jump\"]) == \"\"\"\n        usage: $(basename(Base.source_path())) jump [--lower] [--higher] [--help]\n                                {-c|--somersault}\n\n        commands:\n          -c, --clap-feet  clap feet jumping mode\n          --somersault     somersault jumping mode\n\n        modifiers:\n          --lower          reduce jumping\n          --higher         enhance jumping\n\n        other:\n          --help           show this help message and exit\n\n        \"\"\"\n\n    @ap_test_throws ap_test5b([])\n    @test ap_test5b([\"fly\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"fly\", \"time\"=>\"now\", \"fly\"=>Dict{String,Any}(\"glade\"=>false))\n    @test ap_test5b([\"jump\", \"--lower\", \"--clap\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"time\"=>\"now\",\n        \"jump\"=>Dict{String,Any}(\"%COMMAND%\"=>\"clap_feet\", \"higher\"=>false, \"clap_feet\"=>Dict{String,Any}(\"whistle\"=>false)))\n    @test ap_test5b([\"ju\", \"--lower\", \"--clap\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"time\"=>\"now\",\n        \"jump\"=>Dict{String,Any}(\"%COMMAND%\"=>\"clap_feet\", \"higher\"=>false, \"clap_feet\"=>Dict{String,Any}(\"whistle\"=>false)))\n    @test ap_test5b([\"J\", \"--lower\", \"--clap\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"jump\", \"time\"=>\"now\",\n        \"jump\"=>Dict{String,Any}(\"%COMMAND%\"=>\"clap_feet\", \"higher\"=>false, \"clap_feet\"=>Dict{String,Any}(\"whistle\"=>false)))\n    @noout_test ap_test5b([\"jump\", \"--lower\", \"--help\"]) ≡ nothing\n    @noout_test ap_test5b([\"jump\", \"--lower\", \"--clap\", \"--version\"]) ≡ nothing\n    @ap_test_throws ap_test5b([\"jump\"])\n    @test ap_test5b([\"run\", \"--speed=3\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"run\", \"time\"=>\"now\", \"run\"=>Dict{String,Any}(\"speed\"=>3.0))\n    @test ap_test5b([\"R\", \"--speed=3\"]) == Dict{String,Any}(\"%COMMAND%\"=>\"run\", \"time\"=>\"now\", \"run\"=>Dict{String,Any}(\"speed\"=>3.0))\nend\n\nlet\n    s1 = @add_arg_table!(ArgParseSettings(), \"run\", action = :command)\n    s2 = @add_arg_table!(ArgParseSettings(), \"--run\", action = :store_true)\n    @aps_test_throws import_settings!(s1, s2)\n    @aps_test_throws import_settings!(s2, s1) # this fails since error_on_conflict=true\n    s2 = @add_arg_table!(ArgParseSettings(), [\"R\", \"run\"], action = :command)\n    @aps_test_throws import_settings!(s1, s2)\n    @aps_test_throws import_settings!(s2, s1) # this fails since error_on_conflict=true\nend\n\nend\n"
  },
  {
    "path": "test/argparse_test06.jl",
    "content": "# test 06: argument groups\n\n@testset \"test 06\" begin\n\nfunction ap_settings6()\n\n    s = ArgParseSettings(\"Test 6 for ArgParse.jl\",\n                         exc_handler = ArgParse.debug_handler)\n\n    add_arg_group!(s, \"stack options\")\n    @add_arg_table! s begin\n        \"--opt1\"\n            action = :append_const\n            arg_type = String\n            constant = \"O1\"\n            dest_name = \"O_stack\"\n            help = \"append O1 to the stack\"\n        \"--opt2\"\n            action = :append_const\n            arg_type = String\n            constant = \"O2\"\n            dest_name = \"O_stack\"\n            help = \"append O2 to the stack\"\n    end\n\n    add_arg_group!(s, \"weird options\", \"weird\")\n\n    set_default_arg_group!(s, \"weird\")\n\n    @add_arg_table! s begin\n        \"--awkward-option\"\n            nargs = '+'\n            action = :append_arg\n            dest_name = \"awk\"\n            arg_type = String\n            range_tester = (x->x==\"X\"||x==\"Y\")\n            metavar = \"XY\"\n            help = \"either X or Y; all XY's are \" *\n                   \"stored in chunks\"\n    end\n\n    set_default_arg_group!(s)\n\n    @add_arg_table! s begin\n        \"-k\"\n            action = :store_const\n            default = 0\n            constant = 42\n            help = \"provide the answer\"\n        \"--şİłłÿ\"\n            nargs = 3\n            help = \"an option with a silly name, \" *\n                   \"which expects 3 arguments\"\n            metavar = \"☺\"\n            group = \"weird\"\n    end\n\n    set_default_arg_group!(s, \"weird\")\n\n    @add_arg_table! s begin\n        \"--rest\"\n            nargs = 'R'\n            help = \"an option which will consume \" *\n                   \"all following arguments\"\n    end\n\n    return s\nend\n\nlet s = ap_settings6()\n    ap_test6(args) = parse_args(args, s)\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--opt1] [--opt2]\n                                [--awkward-option XY [XY...]] [-k]\n                                [--şİłłÿ ☺ ☺ ☺] [--rest [REST...]]\n\n        Test 6 for ArgParse.jl\n\n        optional arguments:\n          -k                    provide the answer\n\n        stack options:\n          --opt1                append O1 to the stack\n          --opt2                append O2 to the stack\n\n        weird options:\n          --awkward-option XY [XY...]\n                                either X or Y; all XY's are stored in chunks\n          --şİłłÿ ☺ ☺ ☺         an option with a silly name, which expects 3\n                                arguments\n          --rest [REST...]      an option which will consume all following\n                                arguments\n\n        \"\"\"\n\n    @test ap_test6([]) == Dict{String,Any}(\"O_stack\"=>String[], \"k\"=>0, \"awk\"=>Vector{Any}[], \"şİłłÿ\"=>Any[], \"rest\"=>[])\n    @test ap_test6([\"--opt1\", \"--awk\", \"X\", \"X\", \"--opt2\", \"--opt2\", \"-k\", \"--awkward-option=Y\", \"X\", \"--opt1\", \"--şİł=-1\", \"-2\", \"-3\"]) ==\n        Dict{String,Any}(\"O_stack\"=>String[\"O1\", \"O2\", \"O2\", \"O1\"], \"k\"=>42, \"awk\"=>Any[Any[\"X\", \"X\"], Any[\"Y\", \"X\"]], \"şİłłÿ\"=>[\"-1\", \"-2\", \"-3\"], \"rest\"=>[])\n    @test ap_test6([\"--opt1\", \"--awk\", \"X\", \"X\", \"--opt2\", \"--opt2\", \"--r\", \"-k\", \"--awkward-option=Y\", \"X\", \"--opt1\", \"--şİł\", \"-1\", \"-2\", \"-3\"]) ==\n        Dict{String,Any}(\"O_stack\"=>String[\"O1\", \"O2\", \"O2\"], \"k\"=>0, \"awk\"=>Any[Any[\"X\", \"X\"]], \"şİłłÿ\"=>[], \"rest\"=>Any[\"-k\", \"--awkward-option=Y\", \"X\", \"--opt1\", \"--şİł\", \"-1\", \"-2\", \"-3\"])\n    @test ap_test6([\"--opt1\", \"--awk\", \"X\", \"X\", \"--opt2\", \"--opt2\", \"--r=-k\", \"--awkward-option=Y\", \"X\", \"--opt1\", \"--şİł\", \"-1\", \"-2\", \"-3\"]) ==\n        Dict{String,Any}(\"O_stack\"=>String[\"O1\", \"O2\", \"O2\"], \"k\"=>0, \"awk\"=>Any[Any[\"X\", \"X\"]], \"şİłłÿ\"=>[], \"rest\"=>Any[\"-k\", \"--awkward-option=Y\", \"X\", \"--opt1\", \"--şİł\", \"-1\", \"-2\", \"-3\"])\n    @ap_test_throws ap_test6([\"X\"])\n    @ap_test_throws ap_test6([\"--awk\"])\n    @ap_test_throws ap_test6([\"--awk\", \"Z\"])\n    @ap_test_throws ap_test6([\"--şİł\", \"-1\", \"-2\"])\n    @ap_test_throws ap_test6([\"--şİł\", \"-1\", \"-2\", \"-3\", \"-4\"])\n\n    # invalid groups\n    @aps_test_throws add_arg_group!(s, \"invalid commands\", \"\")\n    @aps_test_throws add_arg_group!(s, \"invalid commands\", \"#invalid\")\n    @aps_test_throws @add_arg_table!(s, \"--opt\", action = :store_true, group = \"none\")\nend\n\nend\n"
  },
  {
    "path": "test/argparse_test07.jl",
    "content": "# test 07: required options, line breaks in desc/epilog\n\n@testset \"test 07\" begin\n\nfunction ap_settings7()\n\n    s = ArgParseSettings(description = \"Test 7 for ArgParse.jl\\n\\nTesting oxymoronic options\",\n                         exc_handler = ArgParse.debug_handler)\n\n    @add_arg_table! s begin\n        \"--oxymoronic\", \"-x\"\n            required = true\n            help = \"a required option\"\n        \"--opt\"\n            required = false\n            help = \"a true option\"\n        \"--flag\", \"-f\"\n            action = :store_true\n            help = \"a flag\"\n        \"-o\"\n            required = true\n            help = \"yet another oxymoronic option\"\n    end\n\n    s.epilog = \"\"\"\n        Example:\\n\n        \\n\n        \\ua0\\ua0<program> --oxymoronic X -o 1\\n\n        \\n\n        Not a particularly enlightening example, but\n        on the other hand this program does not really\n        do anything useful.\n        \"\"\"\n\n    return s\nend\n\nlet s = ap_settings7()\n    ap_test7(args) = parse_args(args, s)\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) -x OXYMORONIC [--opt OPT] [-f] -o O\n\n        Test 7 for ArgParse.jl\n        Testing oxymoronic options\n\n        optional arguments:\n          -x, --oxymoronic OXYMORONIC\n                                a required option\n          --opt OPT             a true option\n          -f, --flag            a flag\n          -o O                  yet another oxymoronic option\n\n        Example:\n\n          <program> --oxymoronic X -o 1\n\n        Not a particularly enlightening example, but on the other hand this\n        program does not really do anything useful.\n\n        \"\"\"\n\n    @ap_test_throws ap_test7([])\n    @test ap_test7([\"--oxymoronic=A\", \"-o=B\"]) == Dict{String,Any}(\"oxymoronic\"=>\"A\", \"opt\"=>nothing, \"o\"=>\"B\", \"flag\"=>false)\n    @ap_test_throws ap_test7([\"--oxymoronic=A\", \"--opt=B\"])\n    @ap_test_throws ap_test7([\"--opt=A, -o=B\"])\n    s.suppress_warnings = true\n    add_arg_table!(s, \"-g\", Dict(:action=>:store_true, :required=>true))\n    @test ap_test7([\"--oxymoronic=A\", \"-o=B\"]) == Dict{String,Any}(\"oxymoronic\"=>\"A\", \"opt\"=>nothing, \"o\"=>\"B\", \"flag\"=>false, \"g\"=>false)\nend\n\nend\n"
  },
  {
    "path": "test/argparse_test08.jl",
    "content": "# test 08: read args from file, read version from project\n\n@testset \"test 08\" begin\n\nfunction ap_settings8a()\n\n    s = ArgParseSettings(fromfile_prefix_chars=['@'])\n\n    @add_arg_table! s begin\n        \"--opt1\"               # an option (will take an argument)\n        \"--opt2\", \"-o\"         # another option, with short form\n        \"arg1\"                 # a positional argument\n    end\n\n    s.exc_handler = ArgParse.debug_handler\n\n    return s\nend\n\nfunction ap_settings8b()  # unicode\n\n    s = ArgParseSettings(fromfile_prefix_chars=\"@∘\")\n\n    @add_arg_table! s begin\n        \"--opt1\"               # an option (will take an argument)\n        \"--opt2\", \"-o\"         # another option, with short form\n        \"arg1\"                 # a positional argument\n    end\n\n    s.exc_handler = ArgParse.debug_handler\n\n    return s\nend\n\nlet s = ap_settings8a()\n    ap_test8(args) = parse_args(args, s)\n\n    @test ap_test8([\"@args-file1\"]) == Dict(\n        \"opt1\"=>nothing, \"opt2\"=>\"y\", \"arg1\"=>nothing)\n    @test ap_test8([\"@args-file1\", \"arg\"]) == Dict(\n        \"opt1\"=>nothing, \"opt2\"=>\"y\", \"arg1\"=>\"arg\")\n    @test ap_test8([\"@args-file2\"]) == Dict(\n        \"opt1\"=>\"x\", \"opt2\"=>\"y\", \"arg1\"=>nothing)\n    @test ap_test8([\"@args-file2\", \"arg\"]) == Dict(\n        \"opt1\"=>\"x\", \"opt2\"=>\"y\", \"arg1\"=>\"arg\")\nend\n\nlet s = ap_settings8b()\n    ap_test8(args) = parse_args(args, s)\n\n    @test ap_test8([\"∘args-file1\"]) == Dict(\n        \"opt1\"=>nothing, \"opt2\"=>\"y\", \"arg1\"=>nothing)\n    @test ap_test8([\"@args-file1\", \"arg\"]) == Dict(\n        \"opt1\"=>nothing, \"opt2\"=>\"y\", \"arg1\"=>\"arg\")\n    @test ap_test8([\"∘args-file2\"]) == Dict(\n        \"opt1\"=>\"x\", \"opt2\"=>\"y\", \"arg1\"=>nothing)\n    @test ap_test8([\"@args-file2\", \"arg\"]) == Dict(\n        \"opt1\"=>\"x\", \"opt2\"=>\"y\", \"arg1\"=>\"arg\")\nend\n\n# not allowed\n@ap_test_throws ArgParseSettings(fromfile_prefix_chars=['-'])\n@ap_test_throws ArgParseSettings(fromfile_prefix_chars=['Å'])\n@ap_test_throws ArgParseSettings(fromfile_prefix_chars=['8'])\n\n# default project version\n@test stringversion(ArgParseSettings(\n    add_version = true, \n    version = @project_version\n)) == \"1.0.0\\n\"\n\n# project version from filepath\n@test stringversion(ArgParseSettings(\n    add_version = true, \n    version = @project_version \"Project.toml\"\n)) == \"1.0.0\\n\"\n\n# project version from expression that returns a filepath\n@test stringversion(ArgParseSettings(\n    add_version = true, \n    version = @project_version(\".\", \"Project.toml\")\n)) == \"1.0.0\\n\"\n\n# throws an error if the file doesn't contain a version\n@test_throws ArgumentError ArgParse.project_version(\"args-file1\")\n\nend\n"
  },
  {
    "path": "test/argparse_test09.jl",
    "content": "# test 09: preformatted desc/epilog\n\n@testset \"test 09\" begin\n\nfunction ap_settings9()\n\n    s = ArgParseSettings(description = \"\"\"\n                         Test 9 for ArgParse.jl\n                         Testing preformatted description/epilog\n\n                             1\n                            1 1\n                           1 2 1\n                          1 3 3 1\n                         \"\"\",\n                         preformatted_description=true,\n                         exc_handler = ArgParse.debug_handler)\n\n    @add_arg_table! s begin\n        \"--opt\"\n            required = true\n            help = \"a required option\"\n    end\n\n    s.epilog = \"\"\"\n               Example:\n\n                 <program> --opt X\n\n               - one\n               - two\n               - three\n               \"\"\"\n    s.preformatted_epilog = true\n\n    return s\nend\n\nlet s = ap_settings9()\n    ap_test7(args) = parse_args(args, s)\n\n    @test stringhelp(s) == \"\"\"\n                           usage: $(basename(Base.source_path())) --opt OPT\n\n                           Test 9 for ArgParse.jl\n                           Testing preformatted description/epilog\n\n                               1\n                              1 1\n                             1 2 1\n                            1 3 3 1\n\n                           optional arguments:\n                             --opt OPT  a required option\n\n                           Example:\n\n                             <program> --opt X\n\n                           - one\n                           - two\n                           - three\n\n                           \"\"\"\n\n    @ap_test_throws ap_test7([])\n    @test ap_test7([\"--opt=A\"]) == Dict{String,Any}(\"opt\"=>\"A\")\nend\n\nend\n"
  },
  {
    "path": "test/argparse_test10.jl",
    "content": "# test 10: multiple metavars\n#          function version of add_arg_table!\n\n@testset \"test 10\" begin\n\nfunction ap_settings10()\n\n    s = ArgParseSettings(description = \"Test 10 for ArgParse.jl\",\n                         epilog = \"Have fun!\",\n                         version = \"Version 1.0\",\n                         add_version = true,\n                         exc_handler = ArgParse.debug_handler)\n\n    @add_arg_table! s begin\n        \"--opt1\"\n            nargs => 2                             # exactly 2 arguments must be specified\n            arg_type => Int                        # only Int arguments allowed\n            default => [0, 1]                      # this is used when the option is not passed\n            metavar => [\"A\", \"B\"]                  # two metavars for two arguments\n            help => \"an option\"\n        \"--flag\", \"-f\"\n            action := :store_true                  # this makes it a flag\n            help := \"a flag\"\n        \"--karma\", \"-k\"\n            action => :count_invocations           # increase a counter each time the option is given\n            help => \"increase karma\"\n        \"arg1\"\n            nargs => 2                             # eats up two arguments; puts the result in a Vector\n            help => \"first argument, two \" *\n                   \"entries at once\"\n            required => true\n        \"arg2\"\n            nargs => '*'                           # eats up as many arguments as possible before an option\n            default => Any[\"no_arg_given\"]         # since the result will be a Vector{Any}, the default must\n                                                   # also be (or it can be [] or nothing)\n            help => \"second argument, eats up \" *\n                    \"as many items as possible \" *\n                    \"before an option\"\n    end\n\n    return s\nend\n\nfunction ap_settings10b()\n\n    s = ArgParseSettings(description = \"Test 10 for ArgParse.jl\",\n                         epilog = \"Have fun!\",\n                         version = \"Version 1.0\",\n                         add_version = true,\n                         exc_handler = ArgParse.debug_handler)\n\n    add_arg_table!(s,\n        \"--opt1\", Dict(\n            :nargs => 2,                       # exactly 2 arguments\n            :arg_type => Int,                  # only Int arguments allowed\n            :default => [0, 1],                # this is used when the option is not passed\n            :metavar => [\"A\", \"B\"],            # two metavars for two arguments\n            :help => \"an option\"),\n        [\"--flag\", \"-f\"], Dict(\n            :action => :store_true,            # this makes it a flag\n            :help => \"a flag\"),\n        [\"--karma\", \"-k\"], Dict(\n            :action => :count_invocations,     # increase a counter each time the option is given\n            :help => \"increase karma\"),\n        \"arg1\", Dict(\n            :nargs => 2,                       # eats up two arguments; puts the result in a Vector\n            :help => \"first argument, two \" *\n                     \"entries at once\",\n            :required => true),\n        \"arg2\", Dict(\n            :nargs => '*',                           # eats up as many arguments as possible before an option\n            :default => Any[\"no_arg_given\"],         # since the result will be a Vector{Any}, the default must\n                                                     # also be (or it can be [] or nothing)\n            :help => \"second argument, eats up \" *\n                     \"as many items as possible \" *\n                     \"before an option\")\n    )\n\n    return s\nend\n\n# test to ensure length of vector is the same as nargs\n\nfunction ap_settings10c(in_nargs)\n\n    s = ArgParseSettings(description = \"Test 10 for ArgParse.jl\",\n                         epilog = \"Have fun!\",\n                         version = \"Version 1.0\",\n                         add_version = true,\n                         exc_handler = ArgParse.debug_handler)\n\n    add_arg_table!(s,\n        \"--opt1\", Dict(\n            :nargs => in_nargs,\n            :arg_type => Int,\n            :default => [0, 1],\n            :metavar => [\"A\", \"B\"])\n    )\n\n    return true\nend\n\n@test ap_settings10c(2)\n@aps_test_throws ap_settings10c(1)\n@aps_test_throws ap_settings10c(3)\n@aps_test_throws ap_settings10c('*')\n@aps_test_throws ap_settings10c('?')\n@aps_test_throws ap_settings10c('+')\n@aps_test_throws ap_settings10c('A')\n@aps_test_throws ap_settings10c('R')\n@aps_test_throws ap_settings10c('0')\n\n# Test to ensure multiple metavars cannot be used on positional args\n\nfunction ap_settings10d()\n    s = ArgParseSettings(description = \"Test 10 for ArgParse.jl\",\n                         epilog = \"Have fun!\",\n                         version = \"Version 1.0\",\n                         add_version = true,\n                         exc_handler = ArgParse.debug_handler)\n\n    add_arg_table!(s,\n        \"opt1\", Dict(\n            :nargs => 2,\n            :arg_type => Int,\n            :metavar => [\"A\", \"B\"])\n    )\n\n    return true\nend\n\n@aps_test_throws ap_settings10d()\n\nfor s = [ap_settings10(), ap_settings10b()]\n    ap_test10(args) = parse_args(args, s)\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--opt1 A B] [-f] [-k] arg1 arg1 [arg2...]\n\n        Test 10 for ArgParse.jl\n\n        positional arguments:\n          arg1         first argument, two entries at once\n          arg2         second argument, eats up as many items as possible\n                       before an option (default: Any[\"no_arg_given\"])\n\n        optional arguments:\n          --opt1 A B   an option (type: $Int, default: $([0, 1]))\n          -f, --flag   a flag\n          -k, --karma  increase karma\n\n        Have fun!\n\n        \"\"\"\n\n    @test stringversion(s) == \"Version 1.0\\n\"\n\n    @ap_test_throws ap_test10([])\n    @test ap_test10([\"X\", \"Y\"]) == Dict{String,Any}(\"opt1\"=>[0, 1], \"flag\"=>false, \"karma\"=>0, \"arg1\"=>Any[\"X\", \"Y\"], \"arg2\"=>Any[\"no_arg_given\"])\n    @test ap_test10([\"X\", \"Y\", \"-k\", \"-f\", \"Z\", \"--karma\", \"--opt1\", \"2\", \"3\"]) == Dict{String,Any}(\"opt1\"=>[2, 3], \"flag\"=>true, \"karma\"=>2, \"arg1\"=>Any[\"X\", \"Y\"], \"arg2\"=>Any[\"Z\"])\n    @test ap_test10([\"--opt1\", \"-3\", \"-5\", \"X\", \"Y\", \"-k\", \"-f\", \"Z\", \"--karma\"]) == Dict{String,Any}(\"opt1\"=>[-3, -5], \"flag\"=>true, \"karma\"=>2, \"arg1\"=>Any[\"X\", \"Y\"], \"arg2\"=>Any[\"Z\"])\n    @ap_test_throws ap_test10([\"--opt\"])\n    @ap_test_throws ap_test10([\"--opt=\"])\n    @ap_test_throws ap_test10([\"--opt\", \"\", \"X\", \"Y\"])\n    @ap_test_throws ap_test10([\"--opt\", \"1e-2\", \"X\", \"Y\"])\n    @ap_test_throws ap_test10([\"X\", \"Y\", \"--opt1\", \"1\", \"a\"])\n    @ap_test_throws ap_test10([\"X\", \"Y\", \"--opt1\", \"1\"])\n    @ap_test_throws ap_test10([\"X\", \"Y\", \"--opt1\", \"a\", \"b\"])\n\n    @aps_test_throws @add_arg_table!(s, \"required_arg_after_optional_args\", required = true)\n    # wrong default\n    @aps_test_throws @add_arg_table!(s, \"--opt\", arg_type = Int, default = 1.5)\n    # wrong range tester\n    @aps_test_throws @add_arg_table!(s, \"--opt\", arg_type = Int, range_tester = x->string(x), default = 1)\n    @aps_test_throws @add_arg_table!(s, \"--opt\", arg_type = Int, range_tester = x->sqrt(x)<1, default = -1)\nend\n\nend\n"
  },
  {
    "path": "test/argparse_test11.jl",
    "content": "@testset \"test 11\" begin\n\n    ARGS = split(\"say hello --to world\")\n\n    s = ArgParseSettings()\n\n    @add_arg_table! s begin\n        \"say\"\n            action = :command\n    end\n\n    @add_arg_table! s[\"say\"] begin\n        \"what\"\n            help = \"a positional argument\"\n            required = true\n        \"--to\"\n            help = \"an option with an argument\"\n    end\n\n    args = parse_args(ARGS, s, as_symbols=true)\n\n    # make sure keys in args[:say] dict are of type Symbol\n    # when as_symbols=true\n    for (arg, val) in args[:say]\n        @test typeof(arg) == Symbol\n    end\n\nend\n"
  },
  {
    "path": "test/argparse_test12.jl",
    "content": "# test 12: mutually exclusive and required argument groups\n\n@testset \"test 12\" begin\n\nfunction ap_settings12()\n\n    s = ArgParseSettings(\"Test 12 for ArgParse.jl\",\n                         exc_handler = ArgParse.debug_handler)\n\n    add_arg_group!(s, \"mutually exclusive options\", exclusive=true)\n    @add_arg_table! s begin\n        \"--maybe\", \"-M\"\n            action = :store_true\n            help = \"maybe...\"\n        \"--maybe-not\", \"-N\"\n            action = :store_true\n            help = \"maybe not...\"\n    end\n\n    add_arg_group!(s, \"required mutually exclusive options\", \"reqexc\", exclusive=true, required=true)\n    @add_arg_table! s begin\n        \"--either\", \"-E\"\n            action = :store_true\n            help = \"choose the `either` option\"\n    end\n\n    add_arg_group!(s, \"required arguments\", required=true)\n    @add_arg_table! s begin\n        \"--enhance\", \"-+\"\n            action = :store_true\n            help = \"set the enhancement option\"\n        \"arg1\"\n            nargs = 2                        # eats up two arguments; puts the result in a Vector\n            help = \"first argument, two \" *\n                   \"entries at once\"\n    end\n\n    set_default_arg_group!(s, \"reqexc\")\n    @add_arg_table! s begin\n        \"--or\", \"-O\"\n            action = :store_arg\n            arg_type = Int\n            default = 0\n            help = \"set the `or` option\"\n    end\n\n    set_default_arg_group!(s)\n    @add_arg_table! s begin\n        \"-k\"\n            action = :store_const\n            default = 0\n            constant = 42\n            help = \"provide the answer\"\n        \"--or-perhaps\"\n            action = :store_arg\n            arg_type = String\n            default = \"\"\n            help = \"set the `or-perhaps` option\"\n            group = \"reqexc\"\n    end\n\n    return s\nend\n\nlet s = ap_settings12()\n    ap_test12(args) = parse_args(args, s)\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) {-E | -O OR | --or-perhaps OR-PERHAPS} [-M |\n                                -N] [-+] [-k] [arg1 arg1]\n\n        Test 12 for ArgParse.jl\n\n        optional arguments:\n          -k                    provide the answer\n\n        mutually exclusive options:\n          -M, --maybe           maybe...\n          -N, --maybe-not       maybe not...\n\n        required mutually exclusive options:\n          -E, --either          choose the `either` option\n          -O, --or OR           set the `or` option (type: $(Int), default: 0)\n          --or-perhaps OR-PERHAPS\n                                set the `or-perhaps` option (default: \\\"\\\")\n\n        required arguments:\n          -+, --enhance         set the enhancement option\n          arg1                  first argument, two entries at once\n\n        \"\"\"\n\n    @ap_test_throws ap_test12([])\n    @test ap_test12([\"-E\", \"-+\"]) ==\n        Dict{String,Any}(\"k\"=>0, \"maybe\"=>false, \"maybe-not\"=>false, \"either\"=>true, \"or\"=>0, \"or-perhaps\"=>\"\", \"enhance\"=>true, \"arg1\"=>[])\n    @test ap_test12([\"-E\", \"-+\", \"--either\"]) ==\n        Dict{String,Any}(\"k\"=>0, \"maybe\"=>false, \"maybe-not\"=>false, \"either\"=>true, \"or\"=>0, \"or-perhaps\"=>\"\", \"enhance\"=>true, \"arg1\"=>[])\n    @test ap_test12([\"A\", \"B\", \"--either\"]) ==\n        Dict{String,Any}(\"k\"=>0, \"maybe\"=>false, \"maybe-not\"=>false, \"either\"=>true, \"or\"=>0, \"or-perhaps\"=>\"\", \"enhance\"=>false, \"arg1\"=>[\"A\", \"B\"])\n    @test ap_test12([\"--enhance\", \"A\", \"B\", \"--or\", \"55\", \"-k\"]) ==\n        Dict{String,Any}(\"k\"=>42, \"maybe\"=>false, \"maybe-not\"=>false, \"either\"=>false, \"or\"=>55, \"or-perhaps\"=>\"\", \"enhance\"=>true, \"arg1\"=>[\"A\", \"B\"])\n    @test ap_test12([\"A\", \"B\", \"-Mk+O55\", \"-M\"]) ==\n        Dict{String,Any}(\"k\"=>42, \"maybe\"=>true, \"maybe-not\"=>false, \"either\"=>false, \"or\"=>55, \"or-perhaps\"=>\"\", \"enhance\"=>true, \"arg1\"=>[\"A\", \"B\"])\n    @test ap_test12([\"--enhance\", \"A\", \"B\", \"--or=55\", \"-k\", \"--maybe-not\"]) ==\n        Dict{String,Any}(\"k\"=>42, \"maybe\"=>false, \"maybe-not\"=>true, \"either\"=>false, \"or\"=>55, \"or-perhaps\"=>\"\", \"enhance\"=>true, \"arg1\"=>[\"A\", \"B\"])\n    @test ap_test12([\"--enhance\", \"A\", \"B\", \"--or-perhaps\", \"--either\", \"-k\", \"--maybe-not\"]) ==\n        Dict{String,Any}(\"k\"=>42, \"maybe\"=>false, \"maybe-not\"=>true, \"either\"=>false, \"or\"=>0, \"or-perhaps\"=>\"--either\", \"enhance\"=>true, \"arg1\"=>[\"A\", \"B\"])\n\n    # combinations of missing arguments and too many arguments from the same group\n    @ap_test_throws ap_test12([\"-M\", \"--enhance\", \"A\", \"B\", \"--or\", \"55\", \"-k\", \"--maybe-not\"])\n    @ap_test_throws ap_test12([\"--maybe\", \"--enhance\", \"A\", \"B\", \"--or\", \"55\", \"-k\", \"-N\"])\n    @ap_test_throws ap_test12([\"--enhance\", \"A\", \"B\", \"-MkNO=55\"])\n    @ap_test_throws ap_test12([\"--maybe\", \"--enhance\", \"A\", \"B\", \"-N\"])\n    @ap_test_throws ap_test12([\"-+NE\", \"--or-perhaps=?\"])\n    @ap_test_throws ap_test12([\"-ME\", \"A\", \"A\", \"--or-perhaps=?\"])\n    @ap_test_throws ap_test12([\"-MO55\", \"A\", \"A\", \"--or-perhaps=?\"])\n    @ap_test_throws ap_test12([\"--enhanced\", \"-+MkO55\", \"A\", \"A\", \"--or-perhaps=?\"])\n    # invalid arguments in mutually exclusive groups\n    @aps_test_throws @add_arg_table!(s, \"arg2\", action = :store_arg, group = \"reqexc\")\n    set_default_arg_group!(s, \"reqexc\")\n    @aps_test_throws @add_arg_table!(s, \"arg2\", action = :store_arg)\nend\n\nend\n"
  },
  {
    "path": "test/argparse_test13.jl",
    "content": "# test 13: help_width and help_alignment_width settings\n\n@testset \"test 13\" begin\n\nfunction ap_settings13()\n\n    s = ArgParseSettings(description = \"Test 13 for ArgParse.jl. This description is made unnecessarily long for the sake of testing the help_text_width setting.\",\n                         epilog = \"This epilog is also made unnecessarily long for the same reason as the description, i.e., testing the help_text_width setting.\",\n                         exc_handler = ArgParse.debug_handler)\n\n    @add_arg_table! s begin\n        \"--option1\"\n            arg_type = Int\n            default = 0\n            help = \"an option, not used for much really, \" *\n                   \"indeed it is not actually used for anything. \" *\n                   \"That is why its name is so undescriptive.\"\n        \"-O\", \"--long-option\"\n            arg_type = Symbol\n            default = :xyz\n            help = \"another option, this time it has a fancy name \" *\n                   \"and yet it is still completely useless.\"\n        \"arg1\"\n            help = \"first argument\"\n            required = true\n        \"arg2\"\n            default = \"no arg2 given\"\n            help = \"second argument\"\n    end\n\n    return s\nend\n\nlet s = ap_settings13()\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--option1 OPTION1] [-O LONG-OPTION] arg1\n                                [arg2]\n\n        Test 13 for ArgParse.jl. This description is made unnecessarily long\n        for the sake of testing the help_text_width setting.\n\n        positional arguments:\n          arg1                  first argument\n          arg2                  second argument (default: \"no arg2 given\")\n\n        optional arguments:\n          --option1 OPTION1     an option, not used for much really, indeed it\n                                is not actually used for anything. That is why\n                                its name is so undescriptive. (type: $Int,\n                                default: 0)\n          -O, --long-option LONG-OPTION\n                                another option, this time it has a fancy name\n                                and yet it is still completely useless. (type:\n                                Symbol, default: :xyz)\n\n        This epilog is also made unnecessarily long for the same reason as the\n        description, i.e., testing the help_text_width setting.\n\n        \"\"\"\n\n    s.help_width = 120\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--option1 OPTION1] [-O LONG-OPTION] arg1 [arg2]\n\n        Test 13 for ArgParse.jl. This description is made unnecessarily long for the sake of testing the help_text_width\n        setting.\n\n        positional arguments:\n          arg1                  first argument\n          arg2                  second argument (default: \"no arg2 given\")\n\n        optional arguments:\n          --option1 OPTION1     an option, not used for much really, indeed it is not actually used for anything. That is why\n                                its name is so undescriptive. (type: $Int, default: 0)\n          -O, --long-option LONG-OPTION\n                                another option, this time it has a fancy name and yet it is still completely useless. (type:\n                                Symbol, default: :xyz)\n\n        This epilog is also made unnecessarily long for the same reason as the description, i.e., testing the help_text_width\n        setting.\n\n        \"\"\"\n\n    s.help_width = 50\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--option1 OPTION1]\n                                [-O LONG-OPTION] arg1\n                                [arg2]\n\n        Test 13 for ArgParse.jl. This description is made\n        unnecessarily long for the sake of testing the\n        help_text_width setting.\n\n        positional arguments:\n          arg1                  first argument\n          arg2                  second argument (default:\n                                \"no arg2 given\")\n\n        optional arguments:\n          --option1 OPTION1     an option, not used for\n                                much really, indeed it is\n                                not actually used for\n                                anything. That is why its\n                                name is so undescriptive.\n                                (type: $Int, default: 0)\n          -O, --long-option LONG-OPTION\n                                another option, this time\n                                it has a fancy name and\n                                yet it is still completely\n                                useless. (type: Symbol,\n                                default: :xyz)\n\n        This epilog is also made unnecessarily long for\n        the same reason as the description, i.e., testing\n        the help_text_width setting.\n\n        \"\"\"\n\n    s.help_width = 100\n    s.help_alignment_width = 50\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--option1 OPTION1] [-O LONG-OPTION] arg1 [arg2]\n\n        Test 13 for ArgParse.jl. This description is made unnecessarily long for the sake of testing the\n        help_text_width setting.\n\n        positional arguments:\n          arg1                           first argument\n          arg2                           second argument (default: \"no arg2 given\")\n\n        optional arguments:\n          --option1 OPTION1              an option, not used for much really, indeed it is not actually used\n                                         for anything. That is why its name is so undescriptive. (type:\n                                         $Int, default: 0)\n          -O, --long-option LONG-OPTION  another option, this time it has a fancy name and yet it is still\n                                         completely useless. (type: Symbol, default: :xyz)\n\n        This epilog is also made unnecessarily long for the same reason as the description, i.e., testing\n        the help_text_width setting.\n\n        \"\"\"\n\n    s.help_width = 50\n    s.help_alignment_width = 4\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--option1 OPTION1]\n            [-O LONG-OPTION] arg1 [arg2]\n\n        Test 13 for ArgParse.jl. This description is made\n        unnecessarily long for the sake of testing the\n        help_text_width setting.\n\n        positional arguments:\n          arg1\n            first argument\n          arg2\n            second argument (default: \"no arg2 given\")\n\n        optional arguments:\n          --option1 OPTION1\n            an option, not used for much really, indeed it\n            is not actually used for anything. That is why\n            its name is so undescriptive. (type: $Int,\n            default: 0)\n          -O, --long-option LONG-OPTION\n            another option, this time it has a fancy name\n            and yet it is still completely useless. (type:\n            Symbol, default: :xyz)\n\n        This epilog is also made unnecessarily long for\n        the same reason as the description, i.e., testing\n        the help_text_width setting.\n\n        \"\"\"\n\nend\n\nend\n"
  },
  {
    "path": "test/argparse_test14.jl",
    "content": "# test 14: default values converted to arg_type\n\n@testset \"test 14\" begin\n\nfunction ap_settings14()\n\n    s = ArgParseSettings(description = \"Test 14 for ArgParse.jl\",\n                         exc_handler = ArgParse.debug_handler)\n\n    @add_arg_table! s begin\n        \"--opt1\"\n            nargs = '?'\n            arg_type = Int\n            default = 0.0\n            constant = 1.0\n            help = \"an option\"\n        \"-O\"\n            arg_type = Symbol\n            default = \"xyz\"\n            help = \"another option\"\n        \"--opt2\"\n            nargs = '+'\n            arg_type = Int\n            default = [0.0]\n            help = \"another option, many args\"\n        \"--opt3\"\n            action = :append_arg\n            arg_type = Int\n            default = [0.0]\n            help = \"another option, appends arg\"\n        \"--opt4\"\n            action = :append_arg\n            nargs = '+'\n            arg_type = Int\n            default = [[0.0]]\n            help = \"another option, appends many args\"\n    end\n\n    return s\nend\n\nlet s = ap_settings14()\n    ap_test14(args) = parse_args(args, s)\n\n    @test stringhelp(s) == \"\"\"\n        usage: $(basename(Base.source_path())) [--opt1 [OPT1]] [-O O]\n                                [--opt2 OPT2 [OPT2...]] [--opt3 OPT3]\n                                [--opt4 OPT4 [OPT4...]]\n\n        Test 14 for ArgParse.jl\n\n        optional arguments:\n          --opt1 [OPT1]         an option (type: $(Int), default: 0, without\n                                arg: 1)\n          -O O                  another option (type: Symbol, default: :xyz)\n          --opt2 OPT2 [OPT2...]\n                                another option, many args (type: $(Int),\n                                default: [0])\n          --opt3 OPT3           another option, appends arg (type: $(Int),\n                                default: [0])\n          --opt4 OPT4 [OPT4...]\n                                another option, appends many args (type:\n                                $(Int), default: $([[0]]))\n\n        \"\"\"\n\n    @test ap_test14([]) == Dict{String,Any}(\"opt1\"=>0, \"O\"=>:xyz, \"opt2\"=>[0], \"opt3\"=>[0], \"opt4\"=>[[0]])\n    @test ap_test14([\"--opt1\"]) == Dict{String,Any}(\"opt1\"=>1, \"O\"=>:xyz, \"opt2\"=>[0], \"opt3\"=>[0], \"opt4\"=>[[0]])\n    @test ap_test14([\"--opt1\", \"33\", \"--opt2\", \"5\", \"7\"]) == Dict{String,Any}(\"opt1\"=>33, \"O\"=>:xyz, \"opt2\"=>[5, 7], \"opt3\"=>[0], \"opt4\"=>[[0]])\n    @test ap_test14([\"--opt3\", \"5\", \"--opt3\", \"7\"]) == Dict{String,Any}(\"opt1\"=>0, \"O\"=>:xyz, \"opt2\"=>[0], \"opt3\"=>[0, 5, 7], \"opt4\"=>[[0]])\n    @test ap_test14([\"--opt4\", \"5\", \"7\", \"--opt4\", \"11\", \"13\", \"17\"]) == Dict{String,Any}(\"opt1\"=>0, \"O\"=>:xyz, \"opt2\"=>[0], \"opt3\"=>[0], \"opt4\"=>[[0], [5, 7], [11, 13, 17]])\nend\n\nend\n"
  },
  {
    "path": "test/args-file1",
    "content": "--opt2=y\n"
  },
  {
    "path": "test/args-file2",
    "content": "@args-file1\n--opt1=x\n"
  },
  {
    "path": "test/common.jl",
    "content": "using ArgParse\nusing Test\n\nmacro ap_test_throws(args)\n    :(@test_throws ArgParseError $(esc(args)))\nend\n\nmacro aps_test_throws(args)\n    :(@test_throws ArgParseSettingsError $(esc(args)))\nend\n\nmacro noout_test(args)\n    quote\n        mktemp() do _,io\n            redirect_stdout(io) do\n                @test $(esc(args))\n            end\n        end\n    end\nend\n\nmacro test_addtable_failure(ex...)\n    ex = [nothing, ex...]\n    ex = Expr(:call, :macroexpand, @__MODULE__, Expr(:quote, Expr(:macrocall, Symbol(\"@add_arg_table!\"), ex...)))\n    err = @static VERSION ≥ v\"1.7.0-DEV.937\" ? ArgParseSettingsError : LoadError\n    quote\n        @test_throws $err $ex\n    end\nend\n\nmacro tostring(ex)\n    @assert ex.head == :call\n    f = esc(ex.args[1])\n    a = map(esc, ex.args[2:end])\n    newcall = Expr(:call, f, :io, a...)\n    quote\n        io = IOBuffer()\n        $newcall\n        String(take!(io))\n    end\nend\n\nstringhelp(s::ArgParseSettings) = @tostring ArgParse.show_help(s, exit_when_done = false)\nstringversion(s::ArgParseSettings) = @tostring ArgParse.show_version(s, exit_when_done = false)\n"
  },
  {
    "path": "test/runtests.jl",
    "content": "module ArgParseTests\n\ninclude(\"common.jl\")\n\nfor i = 1:14\n    try\n        s_i = lpad(string(i), 2, \"0\")\n        include(\"argparse_test$s_i.jl\")\n    catch err\n        println()\n        rethrow(err)\n    end\nend\nprintln()\n\nend\n"
  }
]