From ad4a3f028a9db7697e3c4d572acf3d95996cda74 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Mon, 27 Sep 2021 00:09:10 +0200
Subject: [PATCH] git subrepo pull packages/CLI11

subrepo:
  subdir:   "packages/CLI11"
  merged:   "b440890ea"
upstream:
  origin:   "git@github.com:CLIUtils/CLI11.git"
  branch:   "master"
  commit:   "b440890ea"
git-subrepo:
  version:  "0.4.3"
  origin:   "git@github.com:ingydotnet/git-subrepo.git"
  commit:   "2f68596"
---
 packages/CLI11/.all-contributorsrc            |  36 ++
 packages/CLI11/.appveyor.yml                  |   2 +-
 packages/CLI11/.ci/azure-build.yml            |   1 -
 packages/CLI11/.ci/azure-test.yml             |   2 -
 packages/CLI11/.ci/build_doxygen.sh           |   1 -
 packages/CLI11/.ci/make_and_test.sh           |   4 +-
 packages/CLI11/.ci/run_codecov.sh             |   2 +-
 packages/CLI11/.clang-tidy                    |   1 -
 packages/CLI11/.cmake-format.yaml             |   6 +
 packages/CLI11/.github/CONTRIBUTING.md        |  20 +-
 .../.github/actions/quick_cmake/action.yml    |   9 +-
 packages/CLI11/.github/workflows/build.yml    |   5 +-
 packages/CLI11/.github/workflows/tests.yml    | 112 ++--
 packages/CLI11/.gitrepo                       |   4 +-
 packages/CLI11/.pre-commit-config.yaml        |  53 +-
 packages/CLI11/.pre-commit-nodocker.yaml      |  27 -
 packages/CLI11/.remarkrc                      |   7 +
 packages/CLI11/CHANGELOG.md                   | 446 ++++++++------
 packages/CLI11/CLI11.CPack.Description.txt    |   1 -
 packages/CLI11/CLI11.hpp.in                   |   4 +-
 packages/CLI11/CMakeLists.txt                 | 284 ++++-----
 packages/CLI11/CPPLINT.cfg                    |   1 -
 packages/CLI11/README.md                      | 569 +++++++++---------
 packages/CLI11/book/CMakeLists.txt            |  13 +-
 packages/CLI11/book/README.md                 |  30 +-
 packages/CLI11/book/SUMMARY.md                |   1 -
 .../CLI11/book/chapters/advanced-topics.md    |  61 +-
 .../book/chapters/an-advanced-example.md      |   2 -
 packages/CLI11/book/chapters/basics.md        |   1 -
 packages/CLI11/book/chapters/config.md        |  86 ++-
 packages/CLI11/book/chapters/flags.md         |   9 +-
 packages/CLI11/book/chapters/formatting.md    |  11 +-
 packages/CLI11/book/chapters/internals.md     |   2 -
 packages/CLI11/book/chapters/options.md       |  92 +--
 packages/CLI11/book/chapters/subcommands.md   |   3 +-
 packages/CLI11/book/chapters/toolkits.md      |   8 +-
 packages/CLI11/book/chapters/validators.md    |   3 -
 packages/CLI11/book/code/CMakeLists.txt       |  12 +-
 .../CLI11/cmake/CLI11GeneratePkgConfig.cmake  |   5 +-
 packages/CLI11/cmake/CodeCoverage.cmake       | 229 ++++---
 packages/CLI11/docs/CMakeLists.txt            |  19 +-
 packages/CLI11/docs/mainpage.md               |   6 +-
 packages/CLI11/examples/CMakeLists.txt        | 313 +++++-----
 .../CLI11/examples/callback_passthrough.cpp   |   2 +-
 packages/CLI11/examples/config_app.cpp        |  50 ++
 packages/CLI11/examples/custom_parse.cpp      |  39 ++
 packages/CLI11/examples/digit_args.cpp        |   2 +-
 packages/CLI11/examples/enum.cpp              |   2 +-
 packages/CLI11/examples/enum_ostream.cpp      |   2 +-
 packages/CLI11/examples/formatter.cpp         |   2 +-
 packages/CLI11/examples/groups.cpp            |   2 +-
 .../CLI11/examples/inter_argument_order.cpp   |   2 +-
 packages/CLI11/examples/json.cpp              |   2 +-
 packages/CLI11/examples/modhelp.cpp           |   2 +-
 packages/CLI11/examples/nested.cpp            |   6 +-
 packages/CLI11/examples/option_groups.cpp     |   2 +-
 packages/CLI11/examples/positional_arity.cpp  |   2 +-
 .../CLI11/examples/positional_validation.cpp  |   2 +-
 packages/CLI11/examples/prefix_command.cpp    |   2 +-
 packages/CLI11/examples/ranges.cpp            |   4 +-
 packages/CLI11/examples/retired.cpp           |   2 +-
 packages/CLI11/examples/shapes.cpp            |   2 +-
 packages/CLI11/examples/simple.cpp            |   2 +-
 packages/CLI11/examples/subcom_help.cpp       |   2 +-
 .../examples/subcom_in_files/subcommand_a.cpp |   2 +-
 .../examples/subcom_in_files/subcommand_a.hpp |   2 +-
 .../subcom_in_files/subcommand_main.cpp       |   2 +-
 .../CLI11/examples/subcom_partitioned.cpp     |   2 +-
 packages/CLI11/examples/subcommands.cpp       |   2 +-
 packages/CLI11/examples/validators.cpp        |   2 +-
 packages/CLI11/include/CLI/App.hpp            | 170 +++---
 packages/CLI11/include/CLI/CLI.hpp            |   2 +-
 packages/CLI11/include/CLI/Config.hpp         | 130 ++--
 packages/CLI11/include/CLI/ConfigFwd.hpp      |  49 +-
 packages/CLI11/include/CLI/Error.hpp          |   2 +-
 packages/CLI11/include/CLI/Formatter.hpp      |   2 +-
 packages/CLI11/include/CLI/FormatterFwd.hpp   |   2 +-
 packages/CLI11/include/CLI/Macros.hpp         |   4 +-
 packages/CLI11/include/CLI/Option.hpp         |  39 +-
 packages/CLI11/include/CLI/Split.hpp          |   2 +-
 packages/CLI11/include/CLI/StringTools.hpp    |  66 +-
 packages/CLI11/include/CLI/Timer.hpp          |   2 +-
 packages/CLI11/include/CLI/TypeTools.hpp      |   4 +-
 packages/CLI11/include/CLI/Validators.hpp     |  69 ++-
 packages/CLI11/include/CLI/Version.hpp        |   8 +-
 packages/CLI11/scripts/MakeSingleHeader.py    |  18 +-
 packages/CLI11/scripts/UpdateDownloadProj.py  |  29 -
 packages/CLI11/scripts/mdlint_style.rb        |   8 +
 packages/CLI11/test_package/example.cpp       |   2 +-
 packages/CLI11/tests/AppTest.cpp              |  61 +-
 packages/CLI11/tests/BoostOptionTypeTest.cpp  |   2 +-
 packages/CLI11/tests/CMakeLists.txt           | 219 +++----
 packages/CLI11/tests/ComplexTypeTest.cpp      |   2 +-
 packages/CLI11/tests/ConfigFileTest.cpp       | 465 +++++++++++++-
 packages/CLI11/tests/CreationTest.cpp         |   6 +-
 packages/CLI11/tests/DeprecatedTest.cpp       | 213 +------
 packages/CLI11/tests/FormatterTest.cpp        |   2 +-
 packages/CLI11/tests/HelpTest.cpp             |  21 +-
 packages/CLI11/tests/HelpersTest.cpp          |  20 +-
 packages/CLI11/tests/NewParseTest.cpp         | 149 +----
 packages/CLI11/tests/OptionGroupTest.cpp      |  14 +-
 packages/CLI11/tests/OptionTypeTest.cpp       |  90 ++-
 packages/CLI11/tests/OptionalTest.cpp         |   2 +-
 packages/CLI11/tests/SetTest.cpp              |  20 +-
 packages/CLI11/tests/SimpleTest.cpp           |   2 +-
 packages/CLI11/tests/StringParseTest.cpp      |  30 +-
 packages/CLI11/tests/SubcommandTest.cpp       | 103 +++-
 packages/CLI11/tests/TimerTest.cpp            |   2 +-
 packages/CLI11/tests/TransformTest.cpp        |   2 +-
 packages/CLI11/tests/TrueFalseTest.cpp        |   2 +-
 packages/CLI11/tests/WindowsTest.cpp          |   2 +-
 packages/CLI11/tests/app_helper.hpp           |   2 +-
 packages/CLI11/tests/informational.cpp        |   2 +-
 packages/CLI11/tests/link_test_1.cpp          |   2 +-
 packages/CLI11/tests/link_test_2.cpp          |   2 +-
 packages/CLI11/tests/main.cpp                 |   2 +-
 packages/CLI11/tests/mesonTest/main.cpp       |   2 +-
 117 files changed, 2722 insertions(+), 1975 deletions(-)
 create mode 100644 packages/CLI11/.cmake-format.yaml
 delete mode 100644 packages/CLI11/.pre-commit-nodocker.yaml
 create mode 100644 packages/CLI11/.remarkrc
 create mode 100644 packages/CLI11/examples/config_app.cpp
 create mode 100644 packages/CLI11/examples/custom_parse.cpp
 delete mode 100755 packages/CLI11/scripts/UpdateDownloadProj.py
 create mode 100644 packages/CLI11/scripts/mdlint_style.rb

diff --git a/packages/CLI11/.all-contributorsrc b/packages/CLI11/.all-contributorsrc
index f699ad2b0..7de67853e 100644
--- a/packages/CLI11/.all-contributorsrc
+++ b/packages/CLI11/.all-contributorsrc
@@ -440,6 +440,42 @@
       "contributions": [
         "doc"
       ]
+    },
+    {
+      "login": "paddy-hack",
+      "name": "Olaf Meeuwissen",
+      "avatar_url": "https://avatars.githubusercontent.com/u/6804372?v=4",
+      "profile": "https://github.com/paddy-hack",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "dryleev",
+      "name": "dryleev",
+      "avatar_url": "https://avatars.githubusercontent.com/u/83670813?v=4",
+      "profile": "https://github.com/dryleev",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "AnticliMaxtic",
+      "name": "Max",
+      "avatar_url": "https://avatars.githubusercontent.com/u/43995389?v=4",
+      "profile": "https://github.com/AnticliMaxtic",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "alexdewar",
+      "name": "Alex Dewar",
+      "avatar_url": "https://avatars.githubusercontent.com/u/23149834?v=4",
+      "profile": "https://profiles.sussex.ac.uk/p281168-alex-dewar/publications",
+      "contributions": [
+        "code"
+      ]
     }
   ],
   "contributorsPerLine": 7,
diff --git a/packages/CLI11/.appveyor.yml b/packages/CLI11/.appveyor.yml
index a4ae11883..18915a174 100644
--- a/packages/CLI11/.appveyor.yml
+++ b/packages/CLI11/.appveyor.yml
@@ -1,4 +1,4 @@
-version: 1.9.1.{build}
+version: 2.1.1.{build}
 
 branches:
   only:
diff --git a/packages/CLI11/.ci/azure-build.yml b/packages/CLI11/.ci/azure-build.yml
index 06d60cec9..f51620c52 100644
--- a/packages/CLI11/.ci/azure-build.yml
+++ b/packages/CLI11/.ci/azure-build.yml
@@ -8,4 +8,3 @@ steps:
 - script: cmake --build .
   displayName: 'Build'
   workingDirectory: build
-
diff --git a/packages/CLI11/.ci/azure-test.yml b/packages/CLI11/.ci/azure-test.yml
index ec1d1f556..cf89a9995 100644
--- a/packages/CLI11/.ci/azure-test.yml
+++ b/packages/CLI11/.ci/azure-test.yml
@@ -8,5 +8,3 @@ steps:
   inputs:
     testResultsFormat: 'cTest'
     testResultsFiles: '**/Test.xml'
-
-
diff --git a/packages/CLI11/.ci/build_doxygen.sh b/packages/CLI11/.ci/build_doxygen.sh
index 4474f696a..bd877d53e 100644
--- a/packages/CLI11/.ci/build_doxygen.sh
+++ b/packages/CLI11/.ci/build_doxygen.sh
@@ -23,4 +23,3 @@ export PATH="${DEPS_DIR}/doxygen/build/bin:${PATH}"
 cd "${TRAVIS_BUILD_DIR}"
 
 set +evx
-
diff --git a/packages/CLI11/.ci/make_and_test.sh b/packages/CLI11/.ci/make_and_test.sh
index af8de340f..07df22e88 100755
--- a/packages/CLI11/.ci/make_and_test.sh
+++ b/packages/CLI11/.ci/make_and_test.sh
@@ -1,14 +1,14 @@
 #!/usr/bin/env bash
 echo -en "travis_fold:start:script.build\\r"
 echo "Building..."
-STD=$1
+STD="$1"
 shift
 set -evx
 
 
 mkdir -p build
 cd build
-cmake .. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE=ON -DCMAKE_CXX_STANDARD=$STD -DCLI11_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER_LAUNCHER=ccache $@
+cmake .. -DCLI11_WARNINGS_AS_ERRORS=ON -DCLI11_SINGLE_FILE=ON -DCMAKE_CXX_STANDARD="$STD" -DCLI11_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER_LAUNCHER=ccache $@
 cmake --build . -- -j2
 
 set +evx
diff --git a/packages/CLI11/.ci/run_codecov.sh b/packages/CLI11/.ci/run_codecov.sh
index 28d149a53..fbc199ca5 100755
--- a/packages/CLI11/.ci/run_codecov.sh
+++ b/packages/CLI11/.ci/run_codecov.sh
@@ -4,7 +4,7 @@ echo -en "travis_fold:start:script.build\\r"
 echo "Building..."
 set -evx
 
-cd ${TRAVIS_BUILD_DIR}
+cd "${TRAVIS_BUILD_DIR}"
 mkdir -p build
 cd build
 cmake .. -DCLI11_SINGLE_FILE_TESTS=OFF -DCLI11_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=Coverage
diff --git a/packages/CLI11/.clang-tidy b/packages/CLI11/.clang-tidy
index 09875c87a..075f35dc5 100644
--- a/packages/CLI11/.clang-tidy
+++ b/packages/CLI11/.clang-tidy
@@ -22,4 +22,3 @@ HeaderFilterRegex: '.*hpp'
 CheckOptions:
 - key:             google-readability-braces-around-statements.ShortStatementLines
   value:           '3'
-
diff --git a/packages/CLI11/.cmake-format.yaml b/packages/CLI11/.cmake-format.yaml
new file mode 100644
index 000000000..543ddf19f
--- /dev/null
+++ b/packages/CLI11/.cmake-format.yaml
@@ -0,0 +1,6 @@
+format:
+  line_width: 99
+
+# Causes a few issues - can be solved later, possibly.
+markup:
+  enable_markup: false
diff --git a/packages/CLI11/.github/CONTRIBUTING.md b/packages/CLI11/.github/CONTRIBUTING.md
index fcee45d43..330d8b15b 100644
--- a/packages/CLI11/.github/CONTRIBUTING.md
+++ b/packages/CLI11/.github/CONTRIBUTING.md
@@ -1,8 +1,11 @@
+# Contributing
+
 Thanks for considering to write a Pull Request (PR) for CLI11! Here are a few guidelines to get you started:
 
 Make sure you are comfortable with the license; all contributions are licensed under the original license.
 
 ## Adding functionality
+
 Make sure any new functions you add are are:
 
 * Documented by `///` documentation for Doxygen
@@ -12,7 +15,7 @@ Make sure any new functions you add are are:
 
 In general, make sure the addition is well thought out and does not increase the complexity of CLI11 needlessly.
 
-## Things you should know:
+## Things you should know
 
 * Once you make the PR, tests will run to make sure your code works on all supported platforms
 * The test coverage is also measured, and that should remain 100%
@@ -20,10 +23,9 @@ In general, make sure the addition is well thought out and does not increase the
 * Everything must pass clang-tidy as well, run with `-DCLI11_CLANG_TIDY=ON` (if you set `-DCLI11_CLANG_TIDY_OPTIONS="-fix"`, make sure you use a single threaded build process, or just build one example target).
 * Your changes must also conform to most of the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) rules checked by [cpplint](https://github.com/cpplint/cpplint). For unused cpplint filters and justifications, see [CPPLINT.cfg](/CPPLINT.cfg).
 
-
 ## Pre-commit
 
-Format is handled by pre-commit. You should install it:
+Format is handled by pre-commit. You should install it (or use [pipx](https://pypa.github.io/pipx/)):
 
 ```bash
 python3 -m pip install pre-commit
@@ -31,13 +33,12 @@ python3 -m pip install pre-commit
 
 Then, you can run it on the items you've added to your staging area, or all files:
 
-```
+```bash
 pre-commit run
 # OR
 pre-commit run --all-files
 ```
 
-
 And, if you want to always use it, you can install it as a git hook (hence the name, pre-commit):
 
 ```bash
@@ -72,9 +73,12 @@ yarn all-contributors add username code,bug
 Remember to replace the emoji in the readme, being careful not to replace the ones in all-contributors if any overlap.
 
 Steps:
+
 * Update changelog if needed
 * Update the version in `.appveyor.yml` and `include/CLI/Version.hpp`.
 * Find and replace in README:
-    * Replace " 🆕" and "🆕 " with "" (ignores the description line)
-    * Check for `\/\/$` (vi syntax) to catch leftover `// 🆕`
-    * Replace "🚧" with "🆕" (manually ignore the description line)
+  * Replace " 🆕" and "🆕 " with "" (ignores the description line)
+  * Check for `\/\/$` (vi syntax) to catch leftover `// 🆕`
+  * Replace "🚧" with "🆕" (manually ignore the description line)
+* Make a release in the GitHub UI, use a name such as "Version X.Y(.Z): Title"
+* Currently, the release action wipes the title after you release, so remember to edit the title back to the original name after the `CLI11.hpp` file gets uploaded.
diff --git a/packages/CLI11/.github/actions/quick_cmake/action.yml b/packages/CLI11/.github/actions/quick_cmake/action.yml
index da721a78c..28a82780c 100644
--- a/packages/CLI11/.github/actions/quick_cmake/action.yml
+++ b/packages/CLI11/.github/actions/quick_cmake/action.yml
@@ -5,14 +5,21 @@ inputs:
     description: 'Other arguments'
     required: false
     default: ''
+  cmake-version:
+    description: 'The CMake version to run'
+    required: true
 
 runs:
   using: composite
   steps:
+    - name: CMake ${{ inputs.cmake-version }}
+      uses: jwlawson/actions-setup-cmake@v1.11
+      with:
+        cmake-version: "${{ inputs.cmake-version }}"
     - run: |
         mkdir -p build-tmp
         touch build-tmp/tmp
         rm -r build-tmp/*
-        (cd build-tmp && cmake .. ${{ inputs.args}})
+        (cd build-tmp && cmake .. ${{ inputs.args }})
         rm -r build-tmp
       shell: bash
diff --git a/packages/CLI11/.github/workflows/build.yml b/packages/CLI11/.github/workflows/build.yml
index d3f8043a5..11ed11ca4 100644
--- a/packages/CLI11/.github/workflows/build.yml
+++ b/packages/CLI11/.github/workflows/build.yml
@@ -37,10 +37,13 @@ jobs:
     - name: Make header
       run: cmake --build build --target CLI11-generate-single-file
 
+    - name: Copy file to main folder
+      run: cp build/include/CLI11.hpp CLI11.hpp
+
     - uses: actions/upload-artifact@v2
       with:
         name: CLI11.hpp
-        path: build/include/CLI11.hpp
+        path: CLI11.hpp
 
     - uses: actions/upload-artifact@v2
       with:
diff --git a/packages/CLI11/.github/workflows/tests.yml b/packages/CLI11/.github/workflows/tests.yml
index 60f10f962..020ba3b2b 100644
--- a/packages/CLI11/.github/workflows/tests.yml
+++ b/packages/CLI11/.github/workflows/tests.yml
@@ -15,7 +15,7 @@ jobs:
     steps:
     - uses: actions/checkout@v2
     - uses: actions/setup-python@v2
-    - uses: pre-commit/action@v2.0.2
+    - uses: pre-commit/action@v2.0.3
 
   cuda-build:
     name: CUDA build only
@@ -28,7 +28,7 @@ jobs:
     - name: Add wget
       run: apt-get update && apt-get install -y wget
     - name: Setup cmake
-      uses: jwlawson/actions-setup-cmake@v1.8
+      uses: jwlawson/actions-setup-cmake@v1.11
     - name: Configure
       run: cmake -S . -B build -DCLI11_CUDA_TESTS=ON
     - name: Build
@@ -40,143 +40,111 @@ jobs:
     steps:
     - uses: actions/checkout@v2
 
-    - name: CMake 3.4
-      uses: jwlawson/actions-setup-cmake@v1.8
+    - name: Check CMake 3.4
       with:
         cmake-version: "3.4"
-    - name: Check CMake 3.4
       uses: ./.github/actions/quick_cmake
 
-    - name: CMake 3.5
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.5"
     - name: Check CMake 3.5
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.5"
       if: success() || failure()
 
-    - name: CMake 3.6
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.6"
     - name: Check CMake 3.6
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.6"
       if: success() || failure()
 
-    - name: CMake 3.7
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.7"
     - name: Check CMake 3.7
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.7"
       if: success() || failure()
 
-    - name: CMake 3.8
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.8"
     - name: Check CMake 3.8
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.8"
       if: success() || failure()
 
-    - name: CMake 3.9
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.9"
     - name: Check CMake 3.9
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.9"
       if: success() || failure()
 
-    - name: CMake 3.10
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.10"
     - name: Check CMake 3.10
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.10"
       if: success() || failure()
 
-    - name: CMake 3.11
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.11"
     - name: Check CMake 3.11 (full)
       uses: ./.github/actions/quick_cmake
       with:
+        cmake-version: "3.11"
         args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON
       if: success() || failure()
 
-    - name: CMake 3.12
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.12"
     - name: Check CMake 3.12
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.12"
       if: success() || failure()
 
-    - name: CMake 3.13
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.13"
     - name: Check CMake 3.13
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.13"
       if: success() || failure()
 
-    - name: CMake 3.14
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.14"
     - name: Check CMake 3.14
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.14"
       if: success() || failure()
 
-    - name: CMake 3.15
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.15"
     - name: Check CMake 3.15
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.15"
       if: success() || failure()
 
-    - name: CMake 3.16
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.16"
     - name: Check CMake 3.16
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.16"
       if: success() || failure()
 
-    - name: CMake 3.17
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.17"
     - name: Check CMake 3.17
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.17"
       if: success() || failure()
 
-    - name: CMake 3.18
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.18"
     - name: Check CMake 3.18
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.18"
       if: success() || failure()
 
-    - name: CMake 3.19
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.19"
-    - name: Check CMake 3.19 (full)
+    - name: Check CMake 3.19
       uses: ./.github/actions/quick_cmake
       with:
-        args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON
+        cmake-version: "3.19"
       if: success() || failure()
 
-    - name: CMake 3.20
-      uses: jwlawson/actions-setup-cmake@v1.8
-      with:
-        cmake-version: "3.20"
     - name: Check CMake 3.20
       uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.20"
       if: success() || failure()
 
-
+    - name: Check CMake 3.21 (full)
+      uses: ./.github/actions/quick_cmake
+      with:
+        cmake-version: "3.21"
+        args: -DCLI11_SANITIZERS=ON -DCLI11_BUILD_EXAMPLES_JSON=ON
+      if: success() || failure()
diff --git a/packages/CLI11/.gitrepo b/packages/CLI11/.gitrepo
index 732e03b96..6e7179c30 100644
--- a/packages/CLI11/.gitrepo
+++ b/packages/CLI11/.gitrepo
@@ -6,7 +6,7 @@
 [subrepo]
 	remote = git@github.com:CLIUtils/CLI11.git
 	branch = master
-	commit = 4af78beef777e313814b4daff70e2da9171a385a
-	parent = 015d2fd5332b347d28c47c8dfe3f401382724178
+	commit = b440890eaf29d526e13997f67c2e0288c7c3c60f
+	parent = 4bd033645f2c3c03bdf1682e34ec57bbd2b5dd21
 	cmdver = 0.4.3
 	method = merge
diff --git a/packages/CLI11/.pre-commit-config.yaml b/packages/CLI11/.pre-commit-config.yaml
index f48801a6e..00d77d22f 100644
--- a/packages/CLI11/.pre-commit-config.yaml
+++ b/packages/CLI11/.pre-commit-config.yaml
@@ -1,20 +1,27 @@
+ci:
+  autoupdate_commit_msg: "chore(deps): pre-commit.ci autoupdate"
+  autofix_commit_msg: "style: pre-commit.ci fixes"
+  skip:
+    - docker-clang-format
+
 
 repos:
 - repo: https://github.com/psf/black
-  rev: 20.8b1
+  rev: 21.9b0
   hooks:
   - id: black
 
 - repo: https://github.com/pre-commit/pre-commit-hooks
-  rev: v3.4.0
+  rev: v4.0.1
   hooks:
   - id: check-added-large-files
-  - id: mixed-line-ending
-  - id: trailing-whitespace
-  - id: check-merge-conflict
   - id: check-case-conflict
+  - id: check-merge-conflict
   - id: check-symlinks
   - id: check-yaml
+  - id: end-of-file-fixer
+  - id: mixed-line-ending
+  - id: trailing-whitespace
 
 - repo: local
   hooks:
@@ -27,3 +34,39 @@ repos:
     args:
     - -style=file
     - -i
+
+- repo: https://github.com/cheshirekow/cmake-format-precommit
+  rev: v0.6.13
+  hooks:
+  - id: cmake-format
+    additional_dependencies: [pyyaml]
+
+- repo: https://github.com/markdownlint/markdownlint
+  rev: v0.11.0
+  hooks:
+  - id: markdownlint
+    args: ["--style=scripts/mdlint_style.rb"]
+
+- repo: local
+  hooks:
+  - id: remarklint
+    name: remarklint
+    language: node
+    entry: remark
+    types: [markdown]
+    args: ["--frail", "--quiet"]
+    additional_dependencies: [remark, remark-lint, remark-cli, remark-preset-lint-recommended, remark-lint-list-item-indent, remark-lint-no-undefined-references]
+
+- repo: local
+  hooks:
+  - id: disallow-caps
+    name: Disallow improper capitalization
+    language: pygrep
+    entry: PyBind|Numpy|Cmake|CCache|PyTest|Github
+    exclude: .pre-commit-config.yaml
+
+- repo: https://github.com/codespell-project/codespell
+  rev: v2.1.0
+  hooks:
+  - id: codespell
+    args: ["-L", "atleast,ans,doub,inout"]
diff --git a/packages/CLI11/.pre-commit-nodocker.yaml b/packages/CLI11/.pre-commit-nodocker.yaml
deleted file mode 100644
index 5fcaf3e53..000000000
--- a/packages/CLI11/.pre-commit-nodocker.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-repos:
-- repo: https://github.com/psf/black
-  rev: 19.3b0
-  hooks:
-  - id: black
-- repo: https://github.com/pre-commit/pre-commit-hooks
-  rev: v2.3.0
-  hooks:
-  - id: check-added-large-files
-  - id: mixed-line-ending
-  - id: trailing-whitespace
-  - id: check-merge-conflict
-  - id: check-case-conflict
-  - id: check-symlinks
-  - id: check-yaml
-- repo: local
-  hooks:
-  - id: clang-format
-    name: Clang Format
-    language: system
-    types:
-    - c++
-    entry: clang-format
-    args:
-    - -style=file
-    - -i
diff --git a/packages/CLI11/.remarkrc b/packages/CLI11/.remarkrc
new file mode 100644
index 000000000..73cad8328
--- /dev/null
+++ b/packages/CLI11/.remarkrc
@@ -0,0 +1,7 @@
+{
+  "plugins": [
+    "remark-preset-lint-recommended",
+    ["remark-lint-list-item-indent", "space"],
+    ["remark-lint-no-undefined-references", {"allow": ["^1"]}]
+  ]
+}
diff --git a/packages/CLI11/CHANGELOG.md b/packages/CLI11/CHANGELOG.md
index d2a59b478..41c193814 100644
--- a/packages/CLI11/CHANGELOG.md
+++ b/packages/CLI11/CHANGELOG.md
@@ -1,28 +1,76 @@
-## Version 2.0: In progress
+# Changelog
+
+## Version 2.1: Names and callbacks
+
+The name restrictions for options and subcommands are now much looser, allowing
+a wider variety of characters than before, even spaces can be used (use quotes
+to include a space in most shells). The default configuration parser was
+improved, allowing your configuration to sit in a larger file. And option
+callbacks have a few new settings, allowing them to be run even if the option
+is not passed, or every time the option is parsed.
+
+* Option/subcommand name restrictions have been relaxed. Most characters are now allowed. [#627][]
+* The config parser can accept streams, specify a specific section, and inline comment characters are supported [#630][]
+* `force_callback` & `trigger_on_parse` added, allowing a callback to always run on parse even if not present or every time the option is parsed[#631][]
+* Bugfix(cmake): Only add `CONFIGURE_DEPENDS` if CLI11 is the main project [#633][]
+* Bugfix(cmake): Ensure the cmake/pkg-config files install to a arch independent path [#635][]
+* Bugfix: The single header file generation was missing the include guard. [#620][]
+
+[#620]: https://github.com/CLIUtils/CLI11/pull/620
+[#627]: https://github.com/CLIUtils/CLI11/pull/627
+[#630]: https://github.com/CLIUtils/CLI11/pull/630
+[#631]: https://github.com/CLIUtils/CLI11/pull/631
+[#633]: https://github.com/CLIUtils/CLI11/pull/633
+[#635]: https://github.com/CLIUtils/CLI11/pull/635
+
+### Version 2.1.1: Quick Windows fix
+
+* A collision with `min`/`max` macros on Windows has been fixed. [#642][]
+
+[#642]: https://github.com/CLIUtils/CLI11/pull/642
+
+## Version 2.0: Simplification
+
+This version focuses on cleaning up deprecated functionality, and some minor
+default changes. The config processing is TOML compliant now. Atomics and
+complex numbers are directly supported, along with other container
+improvements. A new version flag option has finally been added. Subcommands are
+significantly improved with new features and bugfixes for corner cases.  This
+release contains a lot of backend cleanup, including a complete overhaul of the
+testing system and single file generation system.
 
 * Built-in config format is TOML compliant now [#435][]
-    * Support multiline TOML [#528][]
-* Support short/positional options in config mode [#443][]
-* More powerful containers, `%%` separator [#423][]
-* Add a version flag easily [#452][]
-* Support atomic types [#520][]
+  * Support multiline TOML [#528][]
+  * Support for configurable quotes [#599][]
+  * Support short/positional options in config mode [#443][]
+* More powerful containers, support for `%%` separator [#423][]
+* Support atomic types [#520][] and complex types natively [#423][]
 * Add a type validator `CLI::TypeValidator<TYPE>` [#526][]
+* Add a version flag easily [#452][], with help message [#601][]
 * Support `->silent()` on subcommands. [#529][]
 * Add alias section to help for subcommands [#545][]
-* Redesigned MakeSingleFiles to have a higher level of manual control, to support future features. [#546][]
-* Moved testing from GTest to Catch2 [#574][]
-
+* Allow quotes to specify a program name [#605][]
+* Backend: redesigned MakeSingleFiles to have a higher level of manual control, to support future features. [#546][]
+* Backend: moved testing from GTest to Catch2 [#574][]
+* Bugfix: avoid duplicated and missed calls to the final callback [#584][]
+* Bugfix: support embedded newlines in more places [#592][]
 * Bugfix: avoid listing helpall as a required flag [#530][]
 * Bugfix: avoid a clash with WINDOWS define [#563][]
-
-* Removed deprecated set commands, use validators instead. [#565][]
-
+* Bugfix: the help flag didn't get processed when a config file was required [#606][]
+* Bugfix: fix description of non-configurable subcommands in config [#604][]
 * Build: support pkg-config [#523][]
 
+> ### Converting from CLI11 1.9
+>
+> * Removed deprecated set commands, use validators instead. [#565][]
+> * The final "defaulted" bool has been removed, use `->capture_default_str()`
+>   instead. Use `app.option_defaults()->always_capture_default()` to set this for
+>   all future options. [#597][]
+> * Use `add_option` on a complex number instead of `add_complex`, which has been removed.
 
+[#423]: https://github.com/CLIUtils/CLI11/pull/423
 [#435]: https://github.com/CLIUtils/CLI11/pull/435
 [#443]: https://github.com/CLIUtils/CLI11/pull/443
-[#423]: https://github.com/CLIUtils/CLI11/pull/423
 [#452]: https://github.com/CLIUtils/CLI11/pull/452
 [#520]: https://github.com/CLIUtils/CLI11/pull/520
 [#523]: https://github.com/CLIUtils/CLI11/pull/523
@@ -35,30 +83,14 @@
 [#563]: https://github.com/CLIUtils/CLI11/pull/563
 [#565]: https://github.com/CLIUtils/CLI11/pull/565
 [#574]: https://github.com/CLIUtils/CLI11/pull/574
-
-
-
-
-### Version 1.9.1: Backporting fixes
-
-This is a patch version that backports fixes from the development of 2.0.
-
-* Support relative inclusion [#475][]
-* Fix cases where spaces in paths could break CMake support [#471][]
-* Fix an issue with string conversion [#421][]
-* Cross-compiling improvement for Conan.io [#430][]
-* Fix option group default propagation [#450][]
-* Fix for C++20 [#459][]
-* Support compiling with RTTI off [#461][]
-
-[#421]: https://github.com/CLIUtils/CLI11/pull/421
-[#430]: https://github.com/CLIUtils/CLI11/pull/430
-[#450]: https://github.com/CLIUtils/CLI11/pull/450
-[#459]: https://github.com/CLIUtils/CLI11/pull/459
-[#461]: https://github.com/CLIUtils/CLI11/pull/461
-[#471]: https://github.com/CLIUtils/CLI11/pull/471
-[#475]: https://github.com/CLIUtils/CLI11/pull/475
-
+[#584]: https://github.com/CLIUtils/CLI11/pull/584
+[#592]: https://github.com/CLIUtils/CLI11/pull/592
+[#597]: https://github.com/CLIUtils/CLI11/pull/597
+[#599]: https://github.com/CLIUtils/CLI11/pull/599
+[#601]: https://github.com/CLIUtils/CLI11/pull/601
+[#604]: https://github.com/CLIUtils/CLI11/pull/604
+[#605]: https://github.com/CLIUtils/CLI11/pull/605
+[#606]: https://github.com/CLIUtils/CLI11/pull/606
 
 ## Version 1.9: Config files and cleanup
 
@@ -98,11 +130,11 @@ configuration options were added to facilitate a wider variety of apps.  GCC
 * Build: GCC 4.7 is no longer supported, due mostly to GoogleTest. GCC 4.8+ is now required. [#160][]
 * Build: Restructured significant portions of CMake build system [#394][]
 
-> ### Converting from CLI11 1.8:
+> ### Converting from CLI11 1.8
 >
 > * Some deprecated methods dropped
->     - `add_set*` should be replaced with `->check`/`->transform` and `CLI::IsMember` since 1.8
->     - `get_defaultval` was replaced by `get_default_str`  in 1.8
+>   * `add_set*` should be replaced with `->check`/`->transform` and `CLI::IsMember` since 1.8
+>   * `get_defaultval` was replaced by `get_default_str`  in 1.8
 > * The true/false 4th argument to `add_option` is expected to be removed in 2.0, use `->capture_default_str()` since 1.8
 
 [#160]: https://github.com/CLIUtils/CLI11/pull/160
@@ -118,7 +150,6 @@ configuration options were added to facilitate a wider variety of apps.  GCC
 [#307]: https://github.com/CLIUtils/CLI11/pull/307
 [#309]: https://github.com/CLIUtils/CLI11/pull/309
 [#310]: https://github.com/CLIUtils/CLI11/pull/310
-[#312]: https://github.com/CLIUtils/CLI11/pull/312
 [#313]: https://github.com/CLIUtils/CLI11/pull/313
 [#317]: https://github.com/CLIUtils/CLI11/pull/317
 [#318]: https://github.com/CLIUtils/CLI11/pull/318
@@ -126,6 +157,7 @@ configuration options were added to facilitate a wider variety of apps.  GCC
 [#325]: https://github.com/CLIUtils/CLI11/pull/325
 [#333]: https://github.com/CLIUtils/CLI11/pull/333
 [#336]: https://github.com/CLIUtils/CLI11/pull/336
+[#341]: https://github.com/CLIUtils/CLI11/pull/341
 [#342]: https://github.com/CLIUtils/CLI11/pull/342
 [#348]: https://github.com/CLIUtils/CLI11/pull/348
 [#349]: https://github.com/CLIUtils/CLI11/pull/349
@@ -136,42 +168,63 @@ configuration options were added to facilitate a wider variety of apps.  GCC
 [#360]: https://github.com/CLIUtils/CLI11/pull/360
 [#362]: https://github.com/CLIUtils/CLI11/pull/362
 [#365]: https://github.com/CLIUtils/CLI11/pull/365
+[#370]: https://github.com/CLIUtils/CLI11/pull/370
 [#373]: https://github.com/CLIUtils/CLI11/pull/373
 [#374]: https://github.com/CLIUtils/CLI11/pull/374
 [#382]: https://github.com/CLIUtils/CLI11/pull/382
+[#387]: https://github.com/CLIUtils/CLI11/pull/387
 [#390]: https://github.com/CLIUtils/CLI11/pull/390
 [#394]: https://github.com/CLIUtils/CLI11/pull/394
 [#400]: https://github.com/CLIUtils/CLI11/pull/400
 
+### Version 1.9.1: Backporting fixes
+
+This is a patch version that backports fixes from the development of 2.0.
+
+* Support relative inclusion [#475][]
+* Fix cases where spaces in paths could break CMake support [#471][]
+* Fix an issue with string conversion [#421][]
+* Cross-compiling improvement for Conan.io [#430][]
+* Fix option group default propagation [#450][]
+* Fix for C++20 [#459][]
+* Support compiling with RTTI off [#461][]
+
+[#421]: https://github.com/CLIUtils/CLI11/pull/421
+[#430]: https://github.com/CLIUtils/CLI11/pull/430
+[#450]: https://github.com/CLIUtils/CLI11/pull/450
+[#459]: https://github.com/CLIUtils/CLI11/pull/459
+[#461]: https://github.com/CLIUtils/CLI11/pull/461
+[#471]: https://github.com/CLIUtils/CLI11/pull/471
+[#475]: https://github.com/CLIUtils/CLI11/pull/475
 
 ## Version 1.8: Transformers, default strings, and flags
 
 Set handling has been completely replaced by a new backend that works as a Validator or Transformer. This provides a single interface instead of the 16 different functions in App. It also allows ordered collections to be used, custom functions for filtering, and better help and error messages. You can also use a collection of pairs (like `std::map`) to transform the match into an output. Also new are inverted flags, which can cancel or reduce the count of flags, and can also support general flag types. A new `add_option_fn` lets you more easily program CLI11 options with the types you choose. Vector options now support a custom separator. Apps can now be composed with unnamed subcommand support. The final bool "defaults" flag when creating options has been replaced by `->capture_default_str()` (ending an old limitation in construction made this possible); the old method is still available but may be removed in future versions.
 
-* Replaced default help capture: `.add_option("name", value, "", True)` becomes `.add_option("name", value)->capture_default_str()` [#242]
-* Added `.always_capture_default()` [#242]
-* New `CLI::IsMember` validator replaces set validation [#222]
-* IsMember also supports container of pairs, transform allows modification of result [#228]
-* Added new Transformers, `CLI::AsNumberWithUnit` and `CLI::AsSizeValue` [#253]
-* Much more powerful flags with different values [#211], general types [#235]
-* `add_option` now supports bool due to unified bool handling [#211]
-* Support for composable unnamed subcommands [#216]
-* Reparsing is better supported with `.remaining_for_passthrough()` [#265]
-* Custom vector separator using `->delimiter(char)` [#209], [#221], [#240]
-* Validators added for IP4 addresses and positive numbers [#210] and numbers [#262]
-* Minimum required Boost for optional Optionals has been corrected to 1.61 [#226]
-* Positionals can stop options from being parsed with `app.positionals_at_end()` [#223]
-* Added `validate_positionals` [#262]
-* Positional parsing is much more powerful [#251], duplicates supported []#247]
-* Validators can be negated with `!` [#230], and now handle tname functions [#228]
-* Better enum support and streaming helper [#233] and [#228]
-* Cleanup for shadow warnings [#232]
-* Better alignment on multiline descriptions [#269]
-* Better support for aarch64 [#266]
-* Respect `BUILD_TESTING` only if CLI11 is the main project; otherwise, `CLI11_TESTING` must be used [#277]
-* Drop auto-detection of experimental optional and boost::optional; must be enabled explicitly (too fragile) [#277] [#279]
-
-> ### Converting from CLI11 1.7:
+* Replaced default help capture: `.add_option("name", value, "", True)` becomes `.add_option("name", value)->capture_default_str()` [#242][]
+* Added `.always_capture_default()` [#242][]
+* New `CLI::IsMember` validator replaces set validation [#222][]
+* `IsMember` also supports container of pairs, transform allows modification of result [#228][]
+* Added new Transformers, `CLI::AsNumberWithUnit` and `CLI::AsSizeValue` [#253][]
+* Much more powerful flags with different values [#211][], general types [#235][]
+* `add_option` now supports bool due to unified bool handling [#211][]
+* Support for composable unnamed subcommands [#216][]
+* Reparsing is better supported with `.remaining_for_passthrough()` [#265][]
+* Custom vector separator using `->delimiter(char)` [#209][], [#221][], [#240][]
+* Validators added for IP4 addresses and positive numbers [#210][] and numbers [#262][]
+* Minimum required Boost for optional Optionals has been corrected to 1.61 [#226][]
+* Positionals can stop options from being parsed with `app.positionals_at_end()` [#223][]
+* Added `validate_positionals` [#262][]
+* Positional parsing is much more powerful [#251][], duplicates supported [#247][]
+* Validators can be negated with `!` [#230][], and now handle tname functions [#228][]
+* Better enum support and streaming helper [#233][] and [#228][]
+* Cleanup for shadow warnings [#232][]
+* Better alignment on multiline descriptions [#269][]
+* Better support for aarch64 [#266][]
+* Respect `BUILD_TESTING` only if CLI11 is the main project; otherwise, `CLI11_TESTING` must be used [#277][]
+* Drop auto-detection of experimental optional and boost::optional; must be enabled explicitly (too fragile) [#277][] [#279][]
+
+> ### Converting from CLI11 1.7
 >
 > * `.add_option(..., true)` should be replaced by `.add_option(...)->capture_default_str()` or `app.option_defaults()->always_capture_default()` can be used
 > * `app.add_set("--name", value, {"choice1", "choice2"})` should become `app.add_option("--name", value)->check(CLI::IsMember({"choice1", "choice2"}))`
@@ -207,47 +260,33 @@ Set handling has been completely replaced by a new backend that works as a Valid
 [#277]: https://github.com/CLIUtils/CLI11/pull/277
 [#279]: https://github.com/CLIUtils/CLI11/pull/279
 
-
-## Version 1.7.1: Quick patch
-
-This version provides a quick patch for a (correct) warning from GCC 8 for the windows options code.
-
-
-* Fix for Windows style option parsing [#201]
-* Improve `add_subcommand` when throwing an exception [#204]
-* Better metadata for Conan package [#202]
-
-[#201]: https://github.com/CLIUtils/CLI11/pull/201
-[#202]: https://github.com/CLIUtils/CLI11/pull/202
-[#204]: https://github.com/CLIUtils/CLI11/pull/204
-
 ## Version 1.7: Parse breakup
 
 The parsing procedure now maps much more sensibly to complex, nested subcommand structures. Each phase of the parsing happens on all subcommands before moving on with the next phase of the parse. This allows several features, like required environment variables, to work properly even through subcommand boundaries.
 Passing the same subcommand multiple times is better supported. Several new features were added as well, including Windows style option support, parsing strings directly, and ignoring underscores in names. Adding a set that you plan to change later must now be done with `add_mutable_set`.
 
-* Support Windows style options with `->allow_windows_style_options`. [#187] On by default on Windows. [#190]
-* Added `parse(string)` to split up and parse a command-line style string directly. [#186]
-* Added `ignore_underscore` and related functions, to ignore underscores when matching names. [#185]
-* The default INI Config will now add quotes to strings with spaces [#195]
-* The default message now will mention the help-all flag also if present [#197]
-* Added `->description` to set Option descriptions [#199]
-* Mutating sets (introduced in Version 1.6) now have a clear add method, `add_mutable_set*`, since the set reference should not expire [#200]
-* Subcommands now track how many times they were parsed in a parsing process. `count()` with no arguments will return the number of times a subcommand was encountered. [#179]
-* Parsing is now done in phases: `shortcurcuits`, `ini`, `env`, `callbacks`, and `requirements`; all subcommands complete a phase before moving on. [#179]
-* Calling parse multiple times is now officially supported without `clear` (automatic). [#179]
-* Dropped the mostly undocumented `short_circuit` property, as help flag parsing is a bit more complex, and the default callback behavior of options now works properly. [#179]
-* Use the standard `BUILD_TESTING` over `CLI11_TESTING` if defined [#183]
-* Cleanup warnings [#191]
-* Remove deprecated names: `set_footer`, `set_name`, `set_callback`, and `set_type_name`. Use without the `set_` instead. [#192]
-
-> ### Converting from CLI11 1.6:
+* Support Windows style options with `->allow_windows_style_options`. [#187][] On by default on Windows. [#190][]
+* Added `parse(string)` to split up and parse a command-line style string directly. [#186][]
+* Added `ignore_underscore` and related functions, to ignore underscores when matching names. [#185][]
+* The default INI Config will now add quotes to strings with spaces [#195][]
+* The default message now will mention the help-all flag also if present [#197][]
+* Added `->description` to set Option descriptions [#199][]
+* Mutating sets (introduced in Version 1.6) now have a clear add method, `add_mutable_set*`, since the set reference should not expire [#200][]
+* Subcommands now track how many times they were parsed in a parsing process. `count()` with no arguments will return the number of times a subcommand was encountered. [#178][]
+* Parsing is now done in phases: `shortcurcuits`, `ini`, `env`, `callbacks`, and `requirements`; all subcommands complete a phase before moving on. [#178][]
+* Calling parse multiple times is now officially supported without `clear` (automatic). [#178][]
+* Dropped the mostly undocumented `short_circuit` property, as help flag parsing is a bit more complex, and the default callback behavior of options now works properly. [#179][]
+* Use the standard `BUILD_TESTING` over `CLI11_TESTING` if defined [#183][]
+* Cleanup warnings [#191][]
+* Remove deprecated names: `set_footer`, `set_name`, `set_callback`, and `set_type_name`. Use without the `set_` instead. [#192][]
+
+> ### Converting from CLI11 1.6
 >
 > * `->short_circuit()` is no longer needed, just remove it if you were using it - raising an exception will happen in the proper place now without it.
 > * `->add_set*` becomes `->add_mutable_set*` if you were using the editable set feature
 > * `footer`, `name`, `callback`, and `type_name` must be used instead of the `set_*` versions (deprecated previously).
 
-[#179]: https://github.com/CLIUtils/CLI11/pull/179
+[#178]: https://github.com/CLIUtils/CLI11/pull/178
 [#183]: https://github.com/CLIUtils/CLI11/pull/183
 [#185]: https://github.com/CLIUtils/CLI11/pull/185
 [#186]: https://github.com/CLIUtils/CLI11/pull/186
@@ -260,48 +299,21 @@ Passing the same subcommand multiple times is better supported. Several new feat
 [#199]: https://github.com/CLIUtils/CLI11/pull/199
 [#200]: https://github.com/CLIUtils/CLI11/pull/200
 
-## Version 1.6.2: Help-all
-
-This version fixes some formatting bugs with help-all. It also adds fixes for several warnings, including an experimental optional error on Clang 7. Several smaller fixes.
-
-* Fixed help-all formatting [#163]
-    * Printing help-all on nested command now fixed (App)
-    * Missing space after help-all restored (Default formatter)
-    * More detail printed on help all (Default formatter)
-    * Help-all subcommands get indented with inner blank lines removed (Default formatter)
-    * `detail::find_and_replace` added to utilities
-* Fixed CMake install as subproject with `CLI11_INSTALL` flag. [#156]
-* Fixed warning about local variable hiding class member with MSVC [#157]
-* Fixed compile error with default settings on Clang 7 and libc++ [#158]
-* Fixed special case of `--help` on subcommands (general fix planned for 1.7) [#168]
-* Removing an option with links  [#179]
-
-[#156]: https://github.com/CLIUtils/CLI11/issues/156
-[#157]: https://github.com/CLIUtils/CLI11/issues/157
-[#158]: https://github.com/CLIUtils/CLI11/issues/158
-[#163]: https://github.com/CLIUtils/CLI11/pull/163
-[#168]: https://github.com/CLIUtils/CLI11/issues/168
-[#179]: https://github.com/CLIUtils/CLI11/pull/179
-
+### Version 1.7.1: Quick patch
 
-## Version 1.6.1: Platform fixes
-
-This version provides a few fixes for special cases, such as mixing with `Windows.h` and better defaults
-for systems like Hunter. The one new feature is the ability to produce "branded" single file output for
-providing custom namespaces or custom macro names.
+This version provides a quick patch for a (correct) warning from GCC 8 for the windows options code.
 
-* Added fix and test for including Windows.h [#145]
-* No longer build single file by default if main project, supports systems stuck on Python 2.6 [#149], [#151]
-* Branding support for single file output [#150]
+* Fix for Windows style option parsing [#201][]
+* Improve `add_subcommand` when throwing an exception [#204][]
+* Better metadata for Conan package [#202][]
 
-[#145]: https://github.com/CLIUtils/CLI11/pull/145
-[#149]: https://github.com/CLIUtils/CLI11/pull/149
-[#150]: https://github.com/CLIUtils/CLI11/pull/150
-[#151]: https://github.com/CLIUtils/CLI11/pull/151
+[#201]: https://github.com/CLIUtils/CLI11/pull/201
+[#202]: https://github.com/CLIUtils/CLI11/pull/202
+[#204]: https://github.com/CLIUtils/CLI11/pull/204
 
 ## Version 1.6: Formatting help
 
-Added a new formatting system [#109]. You can now set the formatter on Apps. This has also simplified the internals of Apps and Options a bit by separating most formatting code.
+Added a new formatting system [#109][]. You can now set the formatter on Apps. This has also simplified the internals of Apps and Options a bit by separating most formatting code.
 
 * Added `CLI::Formatter` and `formatter` slot for apps, inherited.
 * `FormatterBase` is the minimum required.
@@ -317,10 +329,9 @@ Changes to the help system (most normal users will not notice this):
 * Protected function `_has_help_positional` removed.
 * `format_help` can now be chained.
 * Added getters for the missing parts of options (help no longer uses any private parts).
-* Help flags now use new `short_circuit` property to simplify parsing. [#121]
+* Help flags now use new `short_circuit` property to simplify parsing. [#121][]
 
-
-New for Config file reading and writing [#121]:
+New for Config file reading and writing [#121][]:
 
 * Overridable, bidirectional Config.
 * ConfigINI provided and used by default.
@@ -328,10 +339,9 @@ New for Config file reading and writing [#121]:
 * Has `config_formatter()` and `get_config_formatter()`.
 * Dropped prefix argument from `config_to_str`.
 * Added `ConfigItem`.
-* Added an example of a custom config format using [nlohmann/json]. [#138]
-
+* Added an example of a custom config format using [nlohmann/json][]. [#138][]
 
-Validators are now much more powerful [#118], all built in validators upgraded to the new form:
+Validators are now much more powerful [#118][], all built in validators upgraded to the new form:
 
 * A subclass of `CLI::Validator` is now also accepted.
 * They now can set the type name to things like `PATH` and `INT in [1-4]`.
@@ -340,29 +350,29 @@ Validators are now much more powerful [#118], all built in validators upgraded t
 
 Other changes:
 
-* Fixing `parse(args)`'s `args` setting and ordering after parse. [#141]
-* Replaced `set_custom_option` with `type_name` and `type_size` instead of `set_custom_option`. Methods return `this`. [#136]
-* Dropped `set_` on Option's `type_name`, `default_str`, and `default_val`. [#136]
-* Removed `set_` from App's `failure_message`, `footer`, `callback`, and `name`. [#136]
-* Fixed support `N<-1` for `type_size`. [#140]
-* Added `->each()` to make adding custom callbacks easier. [#126]
-* Allow empty options `add_option("-n",{})` to be edited later with `each` [#142]
+* Fixing `parse(args)`'s `args` setting and ordering after parse. [#141][]
+* Replaced `set_custom_option` with `type_name` and `type_size` instead of `set_custom_option`. Methods return `this`. [#136][]
+* Dropped `set_` on Option's `type_name`, `default_str`, and `default_val`. [#136][]
+* Removed `set_` from App's `failure_message`, `footer`, `callback`, and `name`. [#136][]
+* Fixed support `N<-1` for `type_size`. [#140][]
+* Added `->each()` to make adding custom callbacks easier. [#126][]
+* Allow empty options `add_option("-n",{})` to be edited later with `each` [#142][]
 * Added filter argument to `get_subcommands`, `get_options`; use empty filter `{}` to avoid filtering.
 * Added `get_groups()` to get groups.
-* Better support for manual options with `get_option`, `set_results`, and `empty`. [#119]
-* `lname` and `sname` have getters, added `const get_parent`. [#120]
-* Using `add_set` will now capture L-values for sets, allowing further modification. [#113]
+* Better support for manual options with `get_option`, `set_results`, and `empty`. [#119][]
+* `lname` and `sname` have getters, added `const get_parent`. [#120][]
+* Using `add_set` will now capture L-values for sets, allowing further modification. [#113][]
 * Dropped duplicate way to run `get_type_name` (`get_typeval`).
-* Removed `requires` in favor of `needs` (deprecated in last version). [#112]
-* Const added to argv. [#126]
+* Removed `requires` in favor of `needs` (deprecated in last version). [#112][]
+* Const added to argv. [#126][]
 
 Backend and testing changes:
 
-* Internally, `type_name` is now a lambda function; for sets, this reads the set live. [#116]
-* Cleaner tests without `app.reset()` (and `reset` is now `clear`). [#141]
-* Better CMake policy handling. [#110]
-* Includes are properly sorted. [#120]
-* Testing (only) now uses submodules. [#111]
+* Internally, `type_name` is now a lambda function; for sets, this reads the set live. [#116][]
+* Cleaner tests without `app.reset()` (and `reset` is now `clear`). [#141][]
+* Better CMake policy handling. [#110][]
+* Includes are properly sorted. [#120][]
+* Testing (only) now uses submodules. [#111][]
 
 [#109]: https://github.com/CLIUtils/CLI11/pull/109
 [#110]: https://github.com/CLIUtils/CLI11/pull/110
@@ -375,7 +385,7 @@ Backend and testing changes:
 [#120]: https://github.com/CLIUtils/CLI11/pull/120
 [#121]: https://github.com/CLIUtils/CLI11/pull/121
 [#126]: https://github.com/CLIUtils/CLI11/pull/126
-[#127]: https://github.com/CLIUtils/CLI11/pull/127
+[#136]: https://github.com/CLIUtils/CLI11/pull/136
 [#138]: https://github.com/CLIUtils/CLI11/pull/138
 [#140]: https://github.com/CLIUtils/CLI11/pull/140
 [#141]: https://github.com/CLIUtils/CLI11/pull/141
@@ -383,33 +393,43 @@ Backend and testing changes:
 
 [nlohmann/json]: https://github.com/nlohmann/json
 
-### Version 1.5.4: Optionals
-This version fixes the optional search in the single file version; some macros were not yet defined when it did the search. You can define the `CLI11_*_OPTIONAL` macros to 0 if needed to eliminate the search.
-
-### Version 1.5.3: Compiler compatibility
-This version fixes older AppleClang compilers by removing the optimization for casting. The minimum version of Boost Optional supported has been clarified to be 1.58. CUDA 7.0 NVCC is now supported.
+### Version 1.6.1: Platform fixes
 
-### Version 1.5.2: LICENSE in single header mode
+This version provides a few fixes for special cases, such as mixing with `Windows.h` and better defaults
+for systems like Hunter. The one new feature is the ability to produce "branded" single file output for
+providing custom namespaces or custom macro names.
 
-This is a quick patch release that makes LICENSE part of the single header file, making it easier to include. Minor cleanup from codacy. No significant code changes from 1.5.1.
+* Added fix and test for including Windows.h [#145][]
+* No longer build single file by default if main project, supports systems stuck on Python 2.6 [#149][], [#151][]
+* Branding support for single file output [#150][]
 
-### Version 1.5.1: Access
+[#145]: https://github.com/CLIUtils/CLI11/pull/145
+[#149]: https://github.com/CLIUtils/CLI11/pull/149
+[#150]: https://github.com/CLIUtils/CLI11/pull/150
+[#151]: https://github.com/CLIUtils/CLI11/pull/151
 
-This patch release adds better access to the App programmatically, to assist with writing custom converters to other formats. It also improves the help output, and uses a new feature in CLI11 1.5 to fix an old "quirk" in the way unlimited options and positionals interact.
+### Version 1.6.2: Help-all
 
-* Make mixing unlimited positionals and options more intuitive [#102]
-* Add missing getters `get_options` and `get_description` to App [#105]
-* The app name now can be set, and will override the auto name if present [#105]
-* Add `(REQUIRED)` for required options [#104]
-* Print simple name for Needs/Excludes [#104]
-* Use Needs instead of Requires in help print [#104]
-* Groups now are listed in the original definition order [#106]
+This version fixes some formatting bugs with help-all. It also adds fixes for several warnings, including an experimental optional error on Clang 7. Several smaller fixes.
 
-[#102]: https://github.com/CLIUtils/CLI11/issues/102
-[#104]: https://github.com/CLIUtils/CLI11/pull/104
-[#105]: https://github.com/CLIUtils/CLI11/pull/105
-[#106]: https://github.com/CLIUtils/CLI11/pull/106
+* Fixed help-all formatting [#163][]
+  * Printing help-all on nested command now fixed (App)
+  * Missing space after help-all restored (Default formatter)
+  * More detail printed on help all (Default formatter)
+  * Help-all subcommands get indented with inner blank lines removed (Default formatter)
+  * `detail::find_and_replace` added to utilities
+* Fixed CMake install as subproject with `CLI11_INSTALL` flag. [#156][]
+* Fixed warning about local variable hiding class member with MSVC [#157][]
+* Fixed compile error with default settings on Clang 7 and libc++ [#158][]
+* Fixed special case of `--help` on subcommands (general fix planned for 1.7) [#168][]
+* Removing an option with links  [#179][]
 
+[#156]: https://github.com/CLIUtils/CLI11/issues/156
+[#157]: https://github.com/CLIUtils/CLI11/issues/157
+[#158]: https://github.com/CLIUtils/CLI11/issues/158
+[#163]: https://github.com/CLIUtils/CLI11/pull/163
+[#168]: https://github.com/CLIUtils/CLI11/issues/168
+[#179]: https://github.com/CLIUtils/CLI11/pull/179
 
 ## Version 1.5: Optionals
 
@@ -417,24 +437,24 @@ This version introduced support for optionals, along with clarification and exam
 
 Note: This is the final release with `requires`, please switch to `needs`.
 
-* Fix unlimited short options eating two values before checking for positionals when no space present [#90]
-* Symmetric exclude text when excluding options, exclude can be called multiple times [#64]
-* Support for `std::optional`, `std::experimental::optional`, and `boost::optional` added if `__has_include` is supported [#95]
-* All macros/CMake variables now start with `CLI11_` instead of just `CLI_` [#95]
-* The internal stream was not being cleared before use in some cases. Fixed. [#95]
-* Using an enum now requires explicit conversion overload [#97]
-* The separator `--` now is removed when it ends unlimited arguments [#100]
+* Fix unlimited short options eating two values before checking for positionals when no space present [#90][]
+* Symmetric exclude text when excluding options, exclude can be called multiple times [#64][]
+* Support for `std::optional`, `std::experimental::optional`, and `boost::optional` added if `__has_include` is supported [#95][]
+* All macros/CMake variables now start with `CLI11_` instead of just `CLI_` [#95][]
+* The internal stream was not being cleared before use in some cases. Fixed. [#95][]
+* Using an enum now requires explicit conversion overload [#97][]
+* The separator `--` now is removed when it ends unlimited arguments [#100][]
 
 Other, non-user facing changes:
 
-* Added `Macros.hpp` with better C++ mode discovery [#95]
+* Added `Macros.hpp` with better C++ mode discovery [#95][]
 * Deprecated macros added for all platforms
-* C++17 is now tested on supported platforms [#95]
-* Informational printout now added to CTest [#95]
-* Better single file generation [#95]
+* C++17 is now tested on supported platforms [#95][]
+* Informational printout now added to CTest [#95][]
+* Better single file generation [#95][]
 * Added support for GTest on MSVC 2017 (but not in C++17 mode, will need next version of GTest)
-* Types now have a specific size, separate from the expected number - cleaner and more powerful internally [#92]
-* Examples now run as part of testing [#99]
+* Types now have a specific size, separate from the expected number - cleaner and more powerful internally [#92][]
+* Examples now run as part of testing [#99][]
 
 [#64]: https://github.com/CLIUtils/CLI11/issues/64
 [#90]: https://github.com/CLIUtils/CLI11/issues/90
@@ -444,22 +464,50 @@ Other, non-user facing changes:
 [#99]: https://github.com/CLIUtils/CLI11/pull/99
 [#100]: https://github.com/CLIUtils/CLI11/pull/100
 
+### Version 1.5.1: Access
+
+This patch release adds better access to the App programmatically, to assist with writing custom converters to other formats. It also improves the help output, and uses a new feature in CLI11 1.5 to fix an old "quirk" in the way unlimited options and positionals interact.
+
+* Make mixing unlimited positionals and options more intuitive [#102][]
+* Add missing getters `get_options` and `get_description` to App [#105][]
+* The app name now can be set, and will override the auto name if present [#105][]
+* Add `(REQUIRED)` for required options [#104][]
+* Print simple name for Needs/Excludes [#104][]
+* Use Needs instead of Requires in help print [#104][]
+* Groups now are listed in the original definition order [#106][]
+
+[#102]: https://github.com/CLIUtils/CLI11/issues/102
+[#104]: https://github.com/CLIUtils/CLI11/pull/104
+[#105]: https://github.com/CLIUtils/CLI11/pull/105
+[#106]: https://github.com/CLIUtils/CLI11/pull/106
+
+### Version 1.5.2: LICENSE in single header mode
+
+This is a quick patch release that makes LICENSE part of the single header file, making it easier to include. Minor cleanup from codacy. No significant code changes from 1.5.1.
+
+### Version 1.5.3: Compiler compatibility
+
+This version fixes older AppleClang compilers by removing the optimization for casting. The minimum version of Boost Optional supported has been clarified to be 1.58. CUDA 7.0 NVCC is now supported.
+
+### Version 1.5.4: Optionals
+
+This version fixes the optional search in the single file version; some macros were not yet defined when it did the search. You can define the `CLI11_*_OPTIONAL` macros to 0 if needed to eliminate the search.
 
 ## Version 1.4: More feedback
 
 This version adds lots of smaller fixes and additions after the refactor in version 1.3. More ways to download and use CLI11 in CMake have been added. INI files have improved support.
 
-* Lexical cast is now more strict than before [#68] and fails on overflow [#84]
+* Lexical cast is now more strict than before [#68][] and fails on overflow [#84][]
 * Added `get_parent()` to access the parent from a subcommand
-* Added `ExistingPath` validator  [#73]
-* `app.allow_ini_extras()` added to allow extras in INI files [#70]
+* Added `ExistingPath` validator  [#73][]
+* `app.allow_ini_extras()` added to allow extras in INI files [#70][]
 * Multiline INI comments now supported
-* Descriptions can now be written with `config_to_str` [#66]
-* Double printing of error message fixed [#77]
-* Renamed `requires` to `needs` to avoid C++20 keyword [#75], [#82]
-* MakeSingleHeader now works if outside of git [#78]
-* Adding install support for CMake [#79], improved support for `find_package` [#83], [#84]
-* Added support for Conan.io [#83]
+* Descriptions can now be written with `config_to_str` [#66][]
+* Double printing of error message fixed [#77][]
+* Renamed `requires` to `needs` to avoid C++20 keyword [#75][], [#82][]
+* MakeSingleHeader now works if outside of git [#78][]
+* Adding install support for CMake [#79][], improved support for `find_package` [#83][], [#84][]
+* Added support for Conan.io [#83][]
 
 [#70]: https://github.com/CLIUtils/CLI11/issues/70
 [#75]: https://github.com/CLIUtils/CLI11/issues/75
@@ -509,7 +557,7 @@ favorite CLI programs. Error messages and help messages are better and more flex
 * Single internal arg parse function [#56](https://github.com/CLIUtils/CLI11/pull/56)
 * Allow options to be disabled from INI file, rename `add_config` to `set_config` [#60](https://github.com/CLIUtils/CLI11/pull/60)
 
-> ### Converting from CLI11 1.2:
+> ### Converting from CLI11 1.2
 >
 > * `app.parse` no longer returns a vector. Instead, use `app.remaining(true)`.
 > * `"hidden"` is no longer a special group name, instead use `""`
diff --git a/packages/CLI11/CLI11.CPack.Description.txt b/packages/CLI11/CLI11.CPack.Description.txt
index 1fd074a4b..9a018919c 100644
--- a/packages/CLI11/CLI11.CPack.Description.txt
+++ b/packages/CLI11/CLI11.CPack.Description.txt
@@ -1,2 +1 @@
 CLI11 provides all the features you expect in a powerful command line parser, with a beautiful, minimal syntax and no dependencies beyond C++11. It is header only, and comes in a single file form for easy inclusion in projects. It is easy to use for small projects, but powerful enough for complex command line projects, and can be customized for frameworks.
-
diff --git a/packages/CLI11/CLI11.hpp.in b/packages/CLI11/CLI11.hpp.in
index 8de9c532e..9439a4300 100644
--- a/packages/CLI11/CLI11.hpp.in
+++ b/packages/CLI11/CLI11.hpp.in
@@ -5,7 +5,7 @@
 // This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts
 // from: {git}
 //
-// CLI11 {version} Copyright (c) 2017-2020 University of Cincinnati, developed by Henry
+// CLI11 {version} Copyright (c) 2017-2021 University of Cincinnati, developed by Henry
 // Schreiner under NSF AWARD 1414736. All rights reserved.
 //
 // Redistribution and use in source and binary forms of CLI11, with or without
@@ -31,6 +31,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#pragma once
+
 // Standard combined includes:
 {public_includes}
 
diff --git a/packages/CLI11/CMakeLists.txt b/packages/CLI11/CMakeLists.txt
index ee0228ee5..3227e409d 100644
--- a/packages/CLI11/CMakeLists.txt
+++ b/packages/CLI11/CMakeLists.txt
@@ -2,31 +2,34 @@ cmake_minimum_required(VERSION 3.4)
 # Note: this is a header only library. If you have an older CMake than 3.4,
 # just add the CLI11/include directory and that's all you need to do.
 
-# Make sure users don't get warnings on a tested (3.4 to 3.16) version
+# Make sure users don't get warnings on a tested (3.4 to 3.21) version
 # of CMake. For most of the policies, the new version is better (hence the change).
-# We don't use the 3.4...3.17 syntax because of a bug in an older MSVC's
+# We don't use the 3.4...3.21 syntax because of a bug in an older MSVC's
 # built-in and modified CMake 3.11
-if(${CMAKE_VERSION} VERSION_LESS 3.17)
-    cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
+if(${CMAKE_VERSION} VERSION_LESS 3.21)
+  cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
 else()
-    cmake_policy(VERSION 3.17)
+  cmake_policy(VERSION 3.21)
 endif()
 
 set(VERSION_REGEX "#define CLI11_VERSION[ \t]+\"(.+)\"")
 
 # Read in the line containing the version
-file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/Version.hpp"
-    VERSION_STRING REGEX ${VERSION_REGEX})
+file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/Version.hpp" VERSION_STRING
+     REGEX ${VERSION_REGEX})
 
 # Pick out just the version
 string(REGEX REPLACE ${VERSION_REGEX} "\\1" VERSION_STRING "${VERSION_STRING}")
 
 # Add the project
-project(CLI11 LANGUAGES CXX VERSION ${VERSION_STRING})
+project(
+  CLI11
+  LANGUAGES CXX
+  VERSION ${VERSION_STRING})
 
 # Print the version number of CMake if this is the main project
 if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
-    message(STATUS "CMake ${CMAKE_VERSION}")
+  message(STATUS "CMake ${CMAKE_VERSION}")
 endif()
 
 include(CMakeDependentOption)
@@ -34,7 +37,7 @@ include(GNUInstallDirs)
 include(CTest)
 
 if(NOT CMAKE_VERSION VERSION_LESS 3.11)
-    include(FetchContent)
+  include(FetchContent)
 endif()
 
 find_package(Doxygen)
@@ -49,83 +52,76 @@ list(APPEND build-docs "Doxygen_FOUND")
 
 # Necessary to support paths with spaces, see #457
 if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/docs")
-    set(docs_EXIST TRUE)
+  set(docs_EXIST TRUE)
 else()
-    set(docs_EXIST FALSE)
+  set(docs_EXIST FALSE)
 endif()
 list(APPEND build-docs "docs_EXIST")
 
 if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/examples")
-    set(examples_EXIST TRUE)
+  set(examples_EXIST TRUE)
 else()
-    set(examples_EXIST FALSE)
+  set(examples_EXIST FALSE)
 endif()
 
 option(CLI11_WARNINGS_AS_ERRORS "Turn all warnings into errors (for CI)")
 option(CLI11_SINGLE_FILE "Generate a single header file")
-cmake_dependent_option(CLI11_SANITIZERS
-    "Download the sanitizers CMake config" OFF
-    "NOT CMAKE_VERSION VERSION_LESS 3.11" OFF)
+cmake_dependent_option(CLI11_SANITIZERS "Download the sanitizers CMake config" OFF
+                       "NOT CMAKE_VERSION VERSION_LESS 3.11" OFF)
 
-cmake_dependent_option(CLI11_BUILD_DOCS
-    "Build CLI11 documentation" ON
-    "${build-docs}" OFF)
+cmake_dependent_option(CLI11_BUILD_DOCS "Build CLI11 documentation" ON "${build-docs}" OFF)
 
-cmake_dependent_option(CLI11_BUILD_TESTS
-    "Build CLI11 tests" ON
-    "BUILD_TESTING;CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME" OFF)
+cmake_dependent_option(CLI11_BUILD_TESTS "Build CLI11 tests" ON
+                       "BUILD_TESTING;CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME" OFF)
 
-cmake_dependent_option(CLI11_BUILD_EXAMPLES
-    "Build CLI11 examples" ON
-    "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME;${examples_EXIST}" OFF)
+cmake_dependent_option(CLI11_BUILD_EXAMPLES "Build CLI11 examples" ON
+                       "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME;${examples_EXIST}" OFF)
 
-cmake_dependent_option(CLI11_BUILD_EXAMPLES_JSON
-    "Build CLI11 json example" OFF
-    "CLI11_BUILD_EXAMPLES;NOT CMAKE_VERSION VERSION_LESS 3.11" OFF)
+cmake_dependent_option(CLI11_BUILD_EXAMPLES_JSON "Build CLI11 json example" OFF
+                       "CLI11_BUILD_EXAMPLES;NOT CMAKE_VERSION VERSION_LESS 3.11" OFF)
 
-cmake_dependent_option(CLI11_SINGLE_FILE_TESTS
-    "Duplicate all the tests for a single file build" OFF
-    "BUILD_TESTING;CLI11_SINGLE_FILE" OFF)
+cmake_dependent_option(CLI11_SINGLE_FILE_TESTS "Duplicate all the tests for a single file build"
+                       OFF "BUILD_TESTING;CLI11_SINGLE_FILE" OFF)
 
-cmake_dependent_option(CLI11_INSTALL
-    "Install the CLI11 folder to include during install process" ON
-    "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME" OFF)
+cmake_dependent_option(CLI11_INSTALL "Install the CLI11 folder to include during install process"
+                       ON "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME" OFF)
 
-cmake_dependent_option(CLI11_FORCE_LIBCXX
-    "Force clang to use libc++ instead of libstdc++ (Linux only)" OFF
-    "${force-libcxx}" OFF)
+cmake_dependent_option(
+  CLI11_FORCE_LIBCXX "Force clang to use libc++ instead of libstdc++ (Linux only)" OFF
+  "${force-libcxx}" OFF)
 
-cmake_dependent_option(CLI11_CUDA_TESTS
-    "Build the tests with NVCC to check for warnings there - requires CMake 3.9+" OFF
-    "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME" OFF)
+cmake_dependent_option(
+  CLI11_CUDA_TESTS "Build the tests with NVCC to check for warnings there - requires CMake 3.9+"
+  OFF "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME" OFF)
 
-cmake_dependent_option(CLI11_CLANG_TIDY
-    "Look for and use Clang-Tidy" OFF
-    "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME;NOT CMAKE_VERSION VERSION_LESS 3.6" OFF)
-set(CLI11_CLANG_TIDY_OPTIONS "" CACHE STRING "Clang tidy options, such as -fix, semicolon separated")
+cmake_dependent_option(
+  CLI11_CLANG_TIDY "Look for and use Clang-Tidy" OFF
+  "CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME;NOT CMAKE_VERSION VERSION_LESS 3.6" OFF)
+set(CLI11_CLANG_TIDY_OPTIONS
+    ""
+    CACHE STRING "Clang tidy options, such as -fix, semicolon separated")
 
 if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND NOT DEFINED CMAKE_CXX_STANDARD)
-    set(CMAKE_CXX_STANDARD 11)
+  set(CMAKE_CXX_STANDARD 11)
 endif()
 
 if(NOT DEFINED CMAKE_CXX_EXTENSIONS)
-    set(CMAKE_CXX_EXTENSIONS OFF)
+  set(CMAKE_CXX_EXTENSIONS OFF)
 endif()
 
 if(NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED)
-    set(CMAKE_CXX_STANDARD_REQUIRED ON)
+  set(CMAKE_CXX_STANDARD_REQUIRED ON)
 endif()
 
-
 # Allow IDE's to group targets into folders
 if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
-    set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+  set_property(GLOBAL PROPERTY USE_FOLDERS ON)
 endif()
 
 if(CMAKE_VERSION VERSION_LESS 3.10)
-    message(STATUS "CMake 3.10+ adds Doxygen support. Update CMake to build documentation")
+  message(STATUS "CMake 3.10+ adds Doxygen support. Update CMake to build documentation")
 elseif(NOT Doxygen_FOUND)
-    message(STATUS "Doxygen not found, building docs has been disabled")
+  message(STATUS "Doxygen not found, building docs has been disabled")
 endif()
 
 # Special target that adds warnings. Is not exported.
@@ -135,140 +131,128 @@ set(unix-warnings -Wall -Wextra -pedantic -Wshadow -Wsign-conversion -Wswitch-en
 
 # Buggy in GCC 4.8
 if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)
-    list(APPEND unix-warnings -Weffc++)
+  list(APPEND unix-warnings -Weffc++)
 endif()
 
-target_compile_options(CLI11_warnings
-   INTERFACE
-     $<$<BOOL:${CLI11_FORCE_LIBCXX}>:-stdlib=libc++>
-     $<$<CXX_COMPILER_ID:MSVC>:/W4 $<$<BOOL:${CLI11_WARNINGS_AS_ERRORS}>:/WX>>
-     $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:${unix-warnings} $<$<BOOL:${CLI11_WARNINGS_AS_ERRORS}>:-Werror>>)
-
-
- if(NOT CMAKE_VERSION VERSION_LESS 3.13)
-     target_link_options(CLI11_warnings
-         INTERFACE
-         $<$<BOOL:${CLI11_FORCE_LIBCXX}>:-stdlib=libc++>)
- endif()
+target_compile_options(
+  CLI11_warnings
+  INTERFACE $<$<BOOL:${CLI11_FORCE_LIBCXX}>:-stdlib=libc++>
+            $<$<CXX_COMPILER_ID:MSVC>:/W4
+            $<$<BOOL:${CLI11_WARNINGS_AS_ERRORS}>:/WX>>
+            $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:${unix-warnings}
+            $<$<BOOL:${CLI11_WARNINGS_AS_ERRORS}>:-Werror>>)
 
+if(NOT CMAKE_VERSION VERSION_LESS 3.13)
+  target_link_options(CLI11_warnings INTERFACE $<$<BOOL:${CLI11_FORCE_LIBCXX}>:-stdlib=libc++>)
+endif()
 
 # Allow IDE's to group targets into folders
 add_library(CLI11 INTERFACE)
 add_library(CLI11::CLI11 ALIAS CLI11) # for add_subdirectory calls
 
 # Duplicated because CMake adds the current source dir if you don't.
-target_include_directories(CLI11 INTERFACE
-     $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-     $<INSTALL_INTERFACE:include>)
-
+target_include_directories(CLI11 INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+                                           $<INSTALL_INTERFACE:include>)
 
 # To see in IDE, headers must be listed for target
 set(header-patterns "${PROJECT_SOURCE_DIR}/include/CLI/*")
-if(NOT CMAKE_VERSION VERSION_LESS 3.12)
+if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND NOT CMAKE_VERSION VERSION_LESS 3.12)
   list(INSERT header-patterns 0 CONFIGURE_DEPENDS)
 endif()
 
 file(GLOB CLI11_headers ${header-patterns})
 
 # Allow tests to be run on CUDA
- if(CLI11_CUDA_TESTS)
-     enable_language(CUDA)
-
-     # Print out warning and error numbers
-     set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --display_error_number")
- endif()
+if(CLI11_CUDA_TESTS)
+  enable_language(CUDA)
 
+  # Print out warning and error numbers
+  set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcudafe --display_error_number")
+endif()
 
 # Prepare Clang-Tidy
 if(CLI11_CLANG_TIDY)
-    find_program(
-        CLANG_TIDY_EXE
-        NAMES "clang-tidy"
-        DOC "Path to clang-tidy executable"
-        REQUIRED
-        )
-
-    set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" ${CLI11_CLANG_TIDY_OPTIONS})
-endif()
+  find_program(
+    CLANG_TIDY_EXE
+    NAMES "clang-tidy"
+    DOC "Path to clang-tidy executable" REQUIRED)
 
+  set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" ${CLI11_CLANG_TIDY_OPTIONS})
+endif()
 
 # This folder should be installed
 if(CLI11_INSTALL)
-    install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/"
-        DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
+  install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
 
-    # Make an export target
-    install(TARGETS CLI11 EXPORT CLI11Targets)
+  # Make an export target
+  install(TARGETS CLI11 EXPORT CLI11Targets)
 
-    # Use find_package on the installed package
-    # Since we have no custom code, we can directly write this
-    # to Config.cmake (otherwise we'd have a custom config and would
-    # import Targets.cmake
+  # Use find_package on the installed package
+  # Since we have no custom code, we can directly write this
+  # to Config.cmake (otherwise we'd have a custom config and would
+  # import Targets.cmake
 
-    # Add the version in a CMake readable way
-    configure_file("cmake/CLI11ConfigVersion.cmake.in"
-       "CLI11ConfigVersion.cmake" @ONLY)
+  # Add the version in a CMake readable way
+  configure_file("cmake/CLI11ConfigVersion.cmake.in" "CLI11ConfigVersion.cmake" @ONLY)
 
-    # Make version available in the install
-    install(FILES "${PROJECT_BINARY_DIR}/CLI11ConfigVersion.cmake"
-        DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CLI11")
+  # Make version available in the install
+  install(FILES "${PROJECT_BINARY_DIR}/CLI11ConfigVersion.cmake"
+          DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/CLI11")
 
-    # Install the export target as a file
-    install(EXPORT CLI11Targets
-        FILE CLI11Config.cmake
-        NAMESPACE CLI11::
-        DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CLI11")
+  # Install the export target as a file
+  install(
+    EXPORT CLI11Targets
+    FILE CLI11Config.cmake
+    NAMESPACE CLI11::
+    DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/CLI11")
 
-    # Use find_package on the installed package
-    export(TARGETS CLI11
-        NAMESPACE CLI11::
-        FILE CLI11Targets.cmake)
+  # Use find_package on the installed package
+  export(
+    TARGETS CLI11
+    NAMESPACE CLI11::
+    FILE CLI11Targets.cmake)
 
-    include(cmake/CLI11GeneratePkgConfig.cmake)
+  include(cmake/CLI11GeneratePkgConfig.cmake)
 
-    # Register in the user cmake package registry
-    export(PACKAGE CLI11)
+  # Register in the user cmake package registry
+  export(PACKAGE CLI11)
 endif()
 
 if(CLI11_SINGLE_FILE)
-    # Single file test
-    if(CMAKE_VERSION VERSION_LESS 3.12)
-        find_package(PythonInterp REQUIRED)
-        add_executable(Python::Interpreter IMPORTED)
-        set_target_properties(Python::Interpreter
-            PROPERTIES
-            IMPORTED_LOCATION "${PYTHON_EXECUTABLE}"
-            VERSION "${PYTHON_VERSION_STRING}")
-    else()
-        find_package(Python COMPONENTS Interpreter REQUIRED)
-    endif()
-
-    file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include")
-    add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp"
-        COMMAND Python::Interpreter
-        "${CMAKE_CURRENT_SOURCE_DIR}/scripts/MakeSingleHeader.py"
-        ${CLI11_headers}
-        --main "${CMAKE_CURRENT_SOURCE_DIR}/CLI11.hpp.in"
-        --output "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp"
-        --version "${CLI11_VERSION}"
-        DEPENDS
-        "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/CLI.hpp"
-        ${CLI11_headers})
-    add_custom_target(CLI11-generate-single-file ALL
-        DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp")
-    set_property(TARGET CLI11-generate-single-file PROPERTY FOLDER "Scripts")
-    install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp"
-        DESTINATION include)
-    add_library(CLI11_SINGLE INTERFACE)
-    target_link_libraries(CLI11_SINGLE INTERFACE CLI11)
-    add_dependencies(CLI11_SINGLE CLI11-generate-single-file)
-    target_compile_definitions(CLI11_SINGLE INTERFACE -DCLI11_SINGLE_FILE)
-    target_include_directories(CLI11_SINGLE INTERFACE
-        $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/>
-        $<INSTALL_INTERFACE:include>)
+  # Single file test
+  if(CMAKE_VERSION VERSION_LESS 3.12)
+    find_package(PythonInterp REQUIRED)
+    add_executable(Python::Interpreter IMPORTED)
+    set_target_properties(Python::Interpreter PROPERTIES IMPORTED_LOCATION "${PYTHON_EXECUTABLE}"
+                                                         VERSION "${PYTHON_VERSION_STRING}")
+  else()
+    find_package(
+      Python
+      COMPONENTS Interpreter
+      REQUIRED)
+  endif()
+
+  file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include")
+  add_custom_command(
+    OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp"
+    COMMAND
+      Python::Interpreter "${CMAKE_CURRENT_SOURCE_DIR}/scripts/MakeSingleHeader.py"
+      ${CLI11_headers} --main "${CMAKE_CURRENT_SOURCE_DIR}/CLI11.hpp.in" --output
+      "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp" --version "${CLI11_VERSION}"
+    DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/CLI.hpp" ${CLI11_headers})
+  add_custom_target(CLI11-generate-single-file ALL
+                    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp")
+  set_property(TARGET CLI11-generate-single-file PROPERTY FOLDER "Scripts")
+  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/CLI11.hpp" DESTINATION include)
+  add_library(CLI11_SINGLE INTERFACE)
+  target_link_libraries(CLI11_SINGLE INTERFACE CLI11)
+  add_dependencies(CLI11_SINGLE CLI11-generate-single-file)
+  target_compile_definitions(CLI11_SINGLE INTERFACE -DCLI11_SINGLE_FILE)
+  target_include_directories(
+    CLI11_SINGLE INTERFACE $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/>
+                           $<INSTALL_INTERFACE:include>)
 endif()
 
-
 if(CLI11_BUILD_TESTS)
   add_subdirectory(tests)
 endif()
@@ -283,7 +267,7 @@ endif()
 
 # From a build system, this might not be included.
 if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/book")
-    add_subdirectory(book)
+  add_subdirectory(book)
 endif()
 
 # Packaging support
@@ -316,12 +300,10 @@ set(CPACK_SOURCE_IGNORE_FILES
     .swp
     /.all-contributorsrc
     /.appveyor.yml
-    /.pre-commit.*yaml
-)
+    /.pre-commit.*yaml)
 
 set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "all")
 set(CPACK_DEBIAN_COMPRESSION_TYPE "xz")
 set(CPACK_DEBIAN_PACKAGE_NAME "libcli11-dev")
 
 include(CPack)
-
diff --git a/packages/CLI11/CPPLINT.cfg b/packages/CLI11/CPPLINT.cfg
index 0a1758da0..24dd86524 100644
--- a/packages/CLI11/CPPLINT.cfg
+++ b/packages/CLI11/CPPLINT.cfg
@@ -11,4 +11,3 @@ filter=-runtime/references  # Requires fundamental change of API, don't see need
 filter=-whitespace/blank_line  # Unnecessarily strict with blank lines that otherwise help with readability
 filter=-whitespace/indent  # Requires strange 3-space indent of private/protected/public markers
 filter=-whitespace/parens,-whitespace/braces  # Conflict with clang-format
-
diff --git a/packages/CLI11/README.md b/packages/CLI11/README.md
index 846d44ec7..229b65451 100644
--- a/packages/CLI11/README.md
+++ b/packages/CLI11/README.md
@@ -8,12 +8,13 @@
 [![Actions Status][actions-badge]][actions-link]
 [![Code Coverage][codecov-badge]][codecov]
 [![Codacy Badge][codacy-badge]][codacy-link]
-[![Join the chat at https://gitter.im/CLI11gitter/Lobby][gitter-badge]][gitter]
+[![Gitter chat][gitter-badge]][gitter]
 [![License: BSD][license-badge]](./LICENSE)
 [![Latest release][releases-badge]][github releases]
 [![DOI][doi-badge]][doi-link]
 [![Conan.io][conan-badge]][conan-link]
-[![Try CLI11 1.9 online][wandbox-badge]][wandbox-link]
+[![Conda Version][conda-badge]][conda-link]
+[![Try CLI11 2.0 online][wandbox-badge]][wandbox-link]
 
 [What's new](./CHANGELOG.md) •
 [Documentation][gitbook] •
@@ -23,38 +24,38 @@ CLI11 is a command line parser for C++11 and beyond that provides a rich feature
 
 ## Table of Contents
 
--   [Background](#background)
-    -   [Introduction](#introduction)
-    -   [Why write another CLI parser?](#why-write-another-cli-parser)
-    -   [Other parsers](#other-parsers)
-    -   [Features not supported by this library](#features-not-supported-by-this-library)
--   [Install](#install)
--   [Usage](#usage)
-    -   [Adding options](#adding-options)
-        -   [Option types](#option-types)
-        -   [Example](#example)
-        -   [Option options](#option-options)
-        -   [Validators](#validators)
-            -   [Transforming Validators](#transforming-validators)
-            -   [Validator operations](#validator-operations)
-            -   [Custom Validators](#custom-validators)
-            -   [Querying Validators](#querying-validators)
-        -   [Getting Results](#getting-results)
-    -   [Subcommands](#subcommands)
-        -   [Subcommand options](#subcommand-options)
-        -   [Option groups](#option-groups)
-        -   [Callbacks](#callbacks)
-    -   [Configuration file](#configuration-file)
-    -   [Inheriting defaults](#inheriting-defaults)
-    -   [Formatting](#formatting)
-    -   [Subclassing](#subclassing)
-    -   [How it works](#how-it-works)
-    -   [Utilities](#utilities)
-    -   [Other libraries](#other-libraries)
--   [API](#api)
--   [Examples](#Examples)
--   [Contribute](#contribute)
--   [License](#license)
+* [Background](#background)
+  * [Introduction](#introduction)
+  * [Why write another CLI parser?](#why-write-another-cli-parser)
+  * [Other parsers](#other-parsers)
+  * [Features not supported by this library](#features-not-supported-by-this-library)
+* [Install](#install)
+* [Usage](#usage)
+  * [Adding options](#adding-options)
+    * [Option types](#option-types)
+    * [Example](#example)
+    * [Option options](#option-options)
+    * [Validators](#validators)
+      * [Transforming Validators](#transforming-validators)
+      * [Validator operations](#validator-operations)
+      * [Custom Validators](#custom-validators)
+      * [Querying Validators](#querying-validators)
+      * [Getting Results](#getting-results)
+  * [Subcommands](#subcommands)
+    * [Subcommand options](#subcommand-options)
+    * [Option groups](#option-groups)
+    * [Callbacks](#callbacks)
+  * [Configuration file](#configuration-file)
+  * [Inheriting defaults](#inheriting-defaults)
+  * [Formatting](#formatting)
+  * [Subclassing](#subclassing)
+  * [How it works](#how-it-works)
+  * [Utilities](#utilities)
+  * [Other libraries](#other-libraries)
+* [API](#api)
+* [Examples](#Examples)
+* [Contribute](#contribute)
+* [License](#license)
 
 Features that were added in the last released major version are marked with "🆕". Features only available in master are marked with "🚧".
 
@@ -64,7 +65,7 @@ Features that were added in the last released major version are marked with "
 
 CLI11 provides all the features you expect in a powerful command line parser, with a beautiful, minimal syntax and no dependencies beyond C++11. It is header only, and comes in a single file form for easy inclusion in projects. It is easy to use for small projects, but powerful enough for complex command line projects, and can be customized for frameworks.
 It is tested on [Travis][], [AppVeyor][], [Azure][], and [GitHub Actions][actions-link], and is used by the [GooFit GPU fitting framework][goofit]. It was inspired by [`plumbum.cli`][plumbum] for Python. CLI11 has a user friendly introduction in this README, a more in-depth tutorial [GitBook][], as well as [API documentation][api-docs] generated by Travis.
-See the [changelog](./CHANGELOG.md) or [GitHub Releases][] for details for current and past releases. Also see the [Version 1.0 post][], [Version 1.3 post][], or [Version 1.6 post][] for more information.
+See the [changelog](./CHANGELOG.md) or [GitHub Releases][] for details for current and past releases. Also see the [Version 1.0 post][], [Version 1.3 post][], [Version 1.6 post][], or [Version 2.0 post][] for more information.
 
 You can be notified when new releases are made by subscribing to <https://github.com/CLIUtils/CLI11/releases.atom> on an RSS reader, like Feedly, or use the releases mode of the GitHub watching tool.
 
@@ -72,21 +73,21 @@ You can be notified when new releases are made by subscribing to <https://github
 
 An acceptable CLI parser library should be all of the following:
 
--   Easy to include (i.e., header only, one file if possible, **no external requirements**).
--   Short, simple syntax: This is one of the main reasons to use a CLI parser, it should make variables from the command line nearly as easy to define as any other variables. If most of your program is hidden in CLI parsing, this is a problem for readability.
--   C++11 or better: Should work with GCC 4.8+ (default on CentOS/RHEL 7), Clang 3.4+, AppleClang 7+, NVCC 7.0+, or MSVC 2015+.
--   Work on Linux, macOS, and Windows.
--   Well tested using [Travis][] (Linux) and [AppVeyor][] (Windows) or [Azure][] (all three). "Well" is defined as having good coverage measured by [CodeCov][].
--   Clear help printing.
--   Nice error messages.
--   Standard shell idioms supported naturally, like grouping flags, a positional separator, etc.
--   Easy to execute, with help, parse errors, etc. providing correct exit and details.
--   Easy to extend as part of a framework that provides "applications" to users.
--   Usable subcommand syntax, with support for multiple subcommands, nested subcommands, option groups, and optional fallthrough (explained later).
--   Ability to add a configuration file (`ini` or `TOML`🆕 format), and produce it as well.
--   Produce real values that can be used directly in code, not something you have pay compute time to look up, for HPC applications.
--   Work with standard types, simple custom types, and extensible to exotic types.
--   Permissively licensed.
+* Easy to include (i.e., header only, one file if possible, **no external requirements**).
+* Short, simple syntax: This is one of the main reasons to use a CLI parser, it should make variables from the command line nearly as easy to define as any other variables. If most of your program is hidden in CLI parsing, this is a problem for readability.
+* C++11 or better: Should work with GCC 4.8+ (default on CentOS/RHEL 7), Clang 3.4+, AppleClang 7+, NVCC 7.0+, or MSVC 2015+.
+* Work on Linux, macOS, and Windows.
+* Well tested using [Travis][] (Linux) and [AppVeyor][] (Windows) or [Azure][] (all three). "Well" is defined as having good coverage measured by [CodeCov][].
+* Clear help printing.
+* Nice error messages.
+* Standard shell idioms supported naturally, like grouping flags, a positional separator, etc.
+* Easy to execute, with help, parse errors, etc. providing correct exit and details.
+* Easy to extend as part of a framework that provides "applications" to users.
+* Usable subcommand syntax, with support for multiple subcommands, nested subcommands, option groups, and optional fallthrough (explained later).
+* Ability to add a configuration file (`TOML`, `INI`, or custom format), and produce it as well.
+* Produce real values that can be used directly in code, not something you have pay compute time to look up, for HPC applications.
+* Work with standard types, simple custom types, and extensible to exotic types.
+* Permissively licensed.
 
 ### Other parsers
 
@@ -126,32 +127,36 @@ So, this library was designed to provide a great syntax, good compiler compatibi
 
 There are some other possible "features" that are intentionally not supported by this library:
 
--   Non-standard variations on syntax, like `-long` options. This is non-standard and should be avoided, so that is enforced by this library.
--   Completion of partial options, such as Python's `argparse` supplies for incomplete arguments. It's better not to guess. Most third party command line parsers for python actually reimplement command line parsing rather than using argparse because of this perceived design flaw.
--   Autocomplete: This might eventually be added to both Plumbum and CLI11, but it is not supported yet.
--   Wide strings / unicode: Since this uses the standard library only, it might be hard to properly implement, but I would be open to suggestions in how to do this.
+* Non-standard variations on syntax, like `-long` options. This is non-standard and should be avoided, so that is enforced by this library.
+* Completion of partial options, such as Python's `argparse` supplies for incomplete arguments. It's better not to guess. Most third party command line parsers for python actually reimplement command line parsing rather than using argparse because of this perceived design flaw.
+* Autocomplete: This might eventually be added to both Plumbum and CLI11, but it is not supported yet.
+* Wide strings / unicode: Since this uses the standard library only, it might be hard to properly implement, but I would be open to suggestions in how to do this.
 
 ## Install
 
 To use, there are several methods:
 
-1.  All-in-one local header: Copy `CLI11.hpp` from the [most recent release][github releases] into your include directory, and you are set. This is combined from the source files  for every release. This includes the entire command parser library, but does not include separate utilities (like `Timer`, `AutoTimer`). The utilities are completely self contained and can be copied separately.
-2.  All-in-one global header: Like above, but copying the file to a shared folder location like `/opt/CLI11`. Then, the C++ include path has to be extended to point at this folder. With CMake, use `include_directories(/opt/CLI11)`
-3.  Local headers and target: Use `CLI/*.hpp` files. You could check out the repository as a git submodule, for example. With CMake, you can use `add_subdirectory` and the `CLI11::CLI11` interface target when linking. If not using a submodule, you must ensure that the copied files are located inside the same tree directory than your current project, to prevent an error with CMake and `add_subdirectory`.
-4.  Global headers: Use `CLI/*.hpp` files stored in a shared folder. You could check out the git repository in a system-wide folder, for example `/opt/`. With CMake, you could add to the include path via:
+* All-in-one local header: Copy `CLI11.hpp` from the [most recent release][github releases] into your include directory, and you are set. This is combined from the source files  for every release. This includes the entire command parser library, but does not include separate utilities (like `Timer`, `AutoTimer`). The utilities are completely self contained and can be copied separately.
+* All-in-one global header: Like above, but copying the file to a shared folder location like `/opt/CLI11`. Then, the C++ include path has to be extended to point at this folder. With CMake, use `include_directories(/opt/CLI11)`
+* Local headers and target: Use `CLI/*.hpp` files. You could check out the repository as a git submodule, for example. With CMake, you can use `add_subdirectory` and the `CLI11::CLI11` interface target when linking. If not using a submodule, you must ensure that the copied files are located inside the same tree directory than your current project, to prevent an error with CMake and `add_subdirectory`.
+* Global headers: Use `CLI/*.hpp` files stored in a shared folder. You could check out the git repository in a system-wide folder, for example `/opt/`. With CMake, you could add to the include path via:
+
 ```bash
 if(NOT DEFINED CLI11_DIR)
 set (CLI11_DIR "/opt/CLI11" CACHE STRING "CLI11 git repository")
 endif()
 include_directories(${CLI11_DIR}/include)
 ```
+
 And then in the source code (adding several headers might be needed to prevent linker errors):
+
 ```cpp
 #include "CLI/App.hpp"
 #include "CLI/Formatter.hpp"
 #include "CLI/Config.hpp"
 ```
-5.  Global headers and target: configuring and installing the project is required for linking CLI11 to your project in the same way as you would do with any other external library. With CMake, this step allows using `find_package(CLI11 CONFIG REQUIRED)` and then using the `CLI11::CLI11` target when linking. If `CMAKE_INSTALL_PREFIX` was changed during install to a specific folder like `/opt/CLI11`, then you have to pass `-DCLI11_DIR=/opt/CLI11` when building your current project. You can also use [Conan.io][conan-link] or [Hunter][].
+
+* Global headers and target: configuring and installing the project is required for linking CLI11 to your project in the same way as you would do with any other external library. With CMake, this step allows using `find_package(CLI11 CONFIG REQUIRED)` and then using the `CLI11::CLI11` target when linking. If `CMAKE_INSTALL_PREFIX` was changed during install to a specific folder like `/opt/CLI11`, then you have to pass `-DCLI11_DIR=/opt/CLI11` when building your current project. You can also use [Conan.io][conan-link] or [Hunter][].
     (These are just conveniences to allow you to use your favorite method of managing packages; it's just header only so including the correct path and
     using C++11 is all you really need.)
 
@@ -224,18 +229,16 @@ While all options internally are the same type, there are several ways to add an
 app.add_option(option_name, help_str="")
 
 app.add_option(option_name,
-               variable_to_bind_to, // bool, char(see note)🚧, int, float, vector, enum, std::atomic 🚧, or string-like, or anything with a defined conversion from a string or that takes an int 🆕, double 🆕, or string in a constructor. Also allowed are tuples 🆕, std::array 🆕 or std::pair 🆕. Also supported are complex numbers🚧, wrapper types🚧, and containers besides vector🚧 of any other supported type.
+               variable_to_bind_to, // bool, char(see note), int, float, vector, enum, std::atomic, or string-like, or anything with a defined conversion from a string or that takes an int, double, or string in a constructor. Also allowed are tuples, std::array or std::pair. Also supported are complex numbers, wrapper types, and containers besides vectorof any other supported type.
                help_string="")
 
 app.add_option_function<type>(option_name,
                function <void(const type &value)>, // type can be any type supported by add_option
                help_string="")
 
-app.add_complex(... // Special case: support for complex numbers ⚠️. Complex numbers are now fully supported in the add_option so this function is redundant.
-
 // char as an option type is supported before 2.0 but in 2.0 it defaulted to allowing single non numerical characters in addition to the numeric values.
 
-// 🆕 There is a template overload which takes two template parameters the first is the type of object to assign the value to, the second is the conversion type.  The conversion type should have a known way to convert from a string, such as any of the types that work in the non-template version.  If XC is a std::pair and T is some non pair type.  Then a two argument constructor for T is called to assign the value.  For tuples or other multi element types, XC must be a single type or a tuple like object of the same size as the assignment type
+// There is a template overload which takes two template parameters the first is the type of object to assign the value to, the second is the conversion type.  The conversion type should have a known way to convert from a string, such as any of the types that work in the non-template version.  If XC is a std::pair and T is some non pair type.  Then a two argument constructor for T is called to assign the value.  For tuples or other multi element types, XC must be a single type or a tuple like object of the same size as the assignment type
 app.add_option<typename T, typename XC>(option_name,
                T &output, // output must be assignable or constructible from a value of type XC
                help_string="")
@@ -245,7 +248,7 @@ app.add_flag(option_name,
              help_string="")
 
 app.add_flag(option_name,
-             variable_to_bind_to, // bool, int, float, complex, containers, enum, std::atomic 🚧, or string-like, or any singular object with a defined conversion from a string like add_option
+             variable_to_bind_to, // bool, int, float, complex, containers, enum, std::atomic, or string-like, or any singular object with a defined conversion from a string like add_option
              help_string="")
 
 app.add_flag_function(option_name,
@@ -260,32 +263,38 @@ App* subcom = app.add_subcommand(name, description);
 Option_group *app.add_option_group(name,description);
 ```
 
-An option name must start with a alphabetic character, underscore, a number, '?', or '@'. For long options, after the first character '.', and '-' are also valid characters. For the `add_flag*` functions '{' has special meaning. Names are given as a comma separated string, with the dash or dashes. An option or flag can have as many names as you want, and afterward, using `count`, you can use any of the names, with dashes as needed, to count the options. One of the names is allowed to be given without proceeding dash(es); if present the option is a positional option, and that name will be used on the help line for its positional form.
+An option name may start with any character except ('-', ' ', '\n', and '!') 🆕. For long options, after the first character all characters are allowed except ('=',':','{',' ', '\n')🆕. For the `add_flag*` functions '{' and '!' have special meaning which is why they are not allowed. Names are given as a comma separated string, with the dash or dashes. An option or flag can have as many names as you want, and afterward, using `count`, you can use any of the names, with dashes as needed, to count the options. One of the names is allowed to be given without proceeding dash(es); if present the option is a positional option, and that name will be used on the help line for its positional form.
 
 The `add_option_function<type>(...` function will typically require the template parameter be given unless a `std::function` object with an exact match is passed.  The type can be any type supported by the `add_option` function. The function should throw an error (`CLI::ConversionError` or `CLI::ValidationError` possibly) if the value is not valid.
 
-🆕 The two parameter template overload can be used in cases where you want to restrict the input such as
-```
+The two parameter template overload can be used in cases where you want to restrict the input such as
+
+```cpp
 double val
 app.add_option<double,unsigned int>("-v",val);
 ```
+
 which would first verify the input is convertible to an `unsigned int` before assigning it.  Or using some variant type
-```
+
+```cpp
 using vtype=std::variant<int, double, std::string>;
  vtype v1;
 app.add_option<vtype,std:string>("--vs",v1);
 app.add_option<vtype,int>("--vi",v1);
 app.add_option<vtype,double>("--vf",v1);
 ```
+
 otherwise the output would default to a string.  The `add_option` can be used with any integral or floating point types, enumerations, or strings.  Or any type that takes an int, double, or std\::string in an assignment operator or constructor.  If an object can take multiple varieties of those, std::string takes precedence, then double then int.    To better control which one is used or to use another type for the underlying conversions use the two parameter template to directly specify the conversion type.
 
 Types such as (std or boost) `optional<int>`, `optional<double>`, and `optional<string>` and any other wrapper types are supported directly. For purposes of CLI11 wrapper types are those which `value_type` definition.  See [CLI11 Advanced Topics/Custom Converters][] for information on how you can add your own converters for additional types.
 
 Vector types can also be used in the two parameter template overload
-```
+
+```cpp
 std::vector<double> v1;
 app.add_option<std::vector<double>,int>("--vs",v1);
 ```
+
 would load a vector of doubles but ensure all values can be represented as integers.
 
 Automatic direct capture of the default string is disabled when using the two parameter template.  Use `set_default_str(...)` or `->default_function(std::string())` to set the default string or capture function directly for these cases.
@@ -308,76 +317,79 @@ The default value can be any value. For example if you wished to define a numeri
 app.add_flag("-1{1},-2{2},-3{3}",result,"numerical flag")
 ```
 
-using any of those flags on the command line will result in the specified number in the output.  Similar things can be done for string values, and enumerations, as long as the default value can be converted to the given type.
-
+Using any of those flags on the command line will result in the specified number in the output.  Similar things can be done for string values, and enumerations, as long as the default value can be converted to the given type.
 
 On a `C++14` compiler, you can pass a callback function directly to `.add_flag`, while in C++11 mode you'll need to use `.add_flag_function` if you want a callback function. The function will be given the number of times the flag was passed. You can throw a relevant `CLI::ParseError` to signal a failure.
 
 #### Example
 
--   `"one,-o,--one"`: Valid as long as not a flag, would create an option that can be specified positionally, or with `-o` or `--one`
--   `"this"` Can only be passed positionally
--   `"-a,-b,-c"` No limit to the number of non-positional option names
+* `"one,-o,--one"`: Valid as long as not a flag, would create an option that can be specified positionally, or with `-o` or `--one`
+* `"this"` Can only be passed positionally
+* `"-a,-b,-c"` No limit to the number of non-positional option names
 
 The add commands return a pointer to an internally stored `Option`.
 This option can be used directly to check for the count (`->count()`) after parsing to avoid a string based lookup.
-⚠️  Deprecated: The `add_*` commands have a final argument than can be set to true, which causes the default value to be captured and printed on the command line with the help flag. Since CLI11 1.8, you can simply add `->capture_default_str()`.
 
 #### Option options
 
 Before parsing, you can set the following options:
 
--   `->required()`: The program will quit if this option is not present. This is `mandatory` in Plumbum, but required options seems to be a more standard term. For compatibility, `->mandatory()` also works.
--   `->expected(N)`: Take `N` values instead of as many as possible, only for vector args. If negative, require at least `-N`; end with `--` or another recognized option or subcommand.
--   `->type_name(typename)`: Set the name of an Option's type (`type_name_fn` allows a function instead)
--   `->type_size(N)`: Set the intrinsic size of an option. The parser will require multiples of this number if negative.
--   `->needs(opt)`: This option requires another option to also be present, opt is an `Option` pointer.
--   `->excludes(opt)`: This option cannot be given with `opt` present, opt is an `Option` pointer.
--   `->envname(name)`: Gets the value from the environment if present and not passed on the command line.
--   `->group(name)`: The help group to put the option in. No effect for positional options. Defaults to `"Options"`. `""` will not show up in the help print (hidden).
--   `->ignore_case()`: Ignore the case on the command line (also works on subcommands, does not affect arguments).
--   `->ignore_underscore()`: Ignore any underscores in the options names (also works on subcommands, does not affect arguments). For example "option_one" will match with "optionone".  This does not apply to short form options since they only have one character
--   `->disable_flag_override()`: From the command line long form flag options can be assigned a value on the command line using the `=` notation `--flag=value`. If this behavior is not desired, the `disable_flag_override()` disables it and will generate an exception if it is done on the command line.  The `=` does not work with short form flag options.
--   `->allow_extra_args(true/false)`: 🚧 If set to true the option will take an unlimited number of arguments like a vector, if false it will limit the number of arguments to the size of the type used in the option.  Default value depends on the nature of the type use, containers default to true, others default to false.
--   `->delimiter(char)`: Allows specification of a custom delimiter for separating single arguments into vector arguments, for example specifying `->delimiter(',')` on an option would result in `--opt=1,2,3` producing 3 elements of a vector and the equivalent of --opt 1 2 3 assuming opt is a vector value.
--   `->description(str)`: Set/change the description.
--   `->multi_option_policy(CLI::MultiOptionPolicy::Throw)`: Set the multi-option policy. Shortcuts available: `->take_last()`, `->take_first()`,`->take_all()`, and `->join()`. This will only affect options expecting 1 argument or bool flags (which do not inherit their default but always start with a specific policy).
--   `->check(std::string(const std::string &), validator_name="",validator_description="")`: Define a check function.  The function should return a non empty string with the error message if the check fails
--   `->check(Validator)`: Use a Validator object to do the check see [Validators](#validators) for a description of available Validators and how to create new ones.
--   `->transform(std::string(std::string &), validator_name="",validator_description=")`: Converts the input string into the output string, in-place in the parsed options.
--   `->transform(Validator)`: Uses a Validator object to do the transformation see [Validators](#validators) for a description of available Validators and how to create new ones.
--   `->each(void(const std::string &)>`: Run this function on each value received, as it is received. It should throw a `ValidationError` if an error is encountered.
--   `->configurable(false)`: Disable this option from being in a configuration file.
-    `->capture_default_str()`: Store the current value attached and display it in the help string.
--   `->default_function(std::string())`: Advanced: Change the function that `capture_default_str()` uses.
--   `->always_capture_default()`: Always run `capture_default_str()` when creating new options. Only useful on an App's `option_defaults`.
--   `default_str(string)`:  Set the default string directly.  This string will also be used as a default value if no arguments are passed and the value is requested.
--   `default_val(value)`: 🆕 Generate the default string from a value and validate that the value is also valid.  For options that assign directly to a value type the value in that type is also updated.  Value must be convertible to a string(one of known types or have a stream operator).
--   `->option_text(string)`: Sets the text between the option name and description.
-
+* `->required()`: The program will quit if this option is not present. This is `mandatory` in Plumbum, but required options seems to be a more standard term. For compatibility, `->mandatory()` also works.
+* `->expected(N)`: Take `N` values instead of as many as possible, only for vector args. If negative, require at least `-N`; end with `--` or another recognized option or subcommand.
+* `->expected(MIN,MAX)`: Set a range of expected values to accompany an option.  `expected(0,1)` is the equivalent of making a flag.
+* `->type_name(typename)`: Set the name of an Option's type (`type_name_fn` allows a function instead)
+* `->type_size(N)`: Set the intrinsic size of an option value. The parser will require multiples of this number if negative. Most of the time this is detected automatically though can be modified for specific use cases.
+* `->type_size(MIN,MAX)`: Set the intrinsic size of an option to a range.
+* `->needs(opt)`: This option requires another option to also be present, opt is an `Option` pointer. Options can be removed from the `needs` with `remove_needs(opt)`. The option can also be specified with a string containing the name of the option
+* `->excludes(opt)`: This option cannot be given with `opt` present, opt is an `Option` pointer.  Can also be given as a string containing the name of the option.  Options can be removed from the excludes list with `->remove_excludes(opt)`
+* `->envname(name)`: Gets the value from the environment if present and not passed on the command line.
+* `->group(name)`: The help group to put the option in. No effect for positional options. Defaults to `"Options"`. `""` will not show up in the help print (hidden).
+* `->ignore_case()`: Ignore the case on the command line (also works on subcommands, does not affect arguments).
+* `->ignore_underscore()`: Ignore any underscores in the options names (also works on subcommands, does not affect arguments). For example "option_one" will match with "optionone".  This does not apply to short form options since they only have one character
+* `->disable_flag_override()`: From the command line long form flag options can be assigned a value on the command line using the `=` notation `--flag=value`. If this behavior is not desired, the `disable_flag_override()` disables it and will generate an exception if it is done on the command line.  The `=` does not work with short form flag options.
+* `->allow_extra_args(true/false)`: If set to true the option will take an unlimited number of arguments like a vector, if false it will limit the number of arguments to the size of the type used in the option.  Default value depends on the nature of the type use, containers default to true, others default to false.
+* `->delimiter(char)`: Allows specification of a custom delimiter for separating single arguments into vector arguments, for example specifying `->delimiter(',')` on an option would result in `--opt=1,2,3` producing 3 elements of a vector and the equivalent of --opt 1 2 3 assuming opt is a vector value.
+* `->description(str)`: Set/change the description.
+* `->multi_option_policy(CLI::MultiOptionPolicy::Throw)`: Set the multi-option policy. Shortcuts available: `->take_last()`, `->take_first()`,`->take_all()`, and `->join()`. This will only affect options expecting 1 argument or bool flags (which do not inherit their default but always start with a specific policy). `->join(delim)` can also be used to join with a specific delimiter. This equivalent to calling `->delimiter(delim)` and `->join()`
+* `->check(std::string(const std::string &), validator_name="",validator_description="")`: Define a check function.  The function should return a non empty string with the error message if the check fails
+* `->check(Validator)`: Use a Validator object to do the check see [Validators](#validators) for a description of available Validators and how to create new ones.
+* `->transform(std::string(std::string &), validator_name="",validator_description=")`: Converts the input string into the output string, in-place in the parsed options.
+* `->transform(Validator)`: Uses a Validator object to do the transformation see [Validators](#validators) for a description of available Validators and how to create new ones.
+* `->each(void(const std::string &)>`: Run this function on each value received, as it is received. It should throw a `ValidationError` if an error is encountered.
+* `->configurable(false)`: Disable this option from being in a configuration file.
+* `->capture_default_str()`: Store the current value attached and display it in the help string.
+* `->default_function(std::string())`: Advanced: Change the function that `capture_default_str()` uses.
+* `->always_capture_default()`: Always run `capture_default_str()` when creating new options. Only useful on an App's `option_defaults`.
+* `->default_str(string)`:  Set the default string directly (NO VALIDATION OR CALLBACKS).  This string will also be used as a default value if no arguments are passed and the value is requested.
+* `->default_val(value)`: Generate the default string from a value and validate that the value is also valid.  For options that assign directly to a value type the value in that type is also updated.  Value must be convertible to a string(one of known types or have a stream operator). The callback may be triggered if the `run_callback_for_default` is set.
+* `->run_callback_for_default()`: This will force the option callback to be executed or the variable set when the `default_val` is set.
+* `->option_text(string)`: Sets the text between the option name and description.
+* `->force_callback()`: 🆕 Causes the option callback or value set to be triggered even if the option was not present in parsing.
+* `->trigger_on_parse()`: 🆕 If set, causes the callback and all associated validation checks for the option to be executed when the option value is parsed vs. at the end of all parsing. This could cause the callback to be executed multiple times.
 
 These options return the `Option` pointer, so you can chain them together, and even skip storing the pointer entirely. The `each` function takes any function that has the signature `void(const std::string&)`; it should throw a `ValidationError` when validation fails. The help message will have the name of the parent option prepended. Since `each`, `check` and `transform` use the same underlying mechanism, you can chain as many as you want, and they will be executed in order. Operations added through `transform` are executed first in reverse order of addition, and `check` and `each` are run following the transform functions in order of addition. If you just want to see the unconverted values, use `.results()` to get the `std::vector<std::string>` of results.
 
 On the command line, options can be given as:
 
--   `-a` (flag)
--   `-abc` (flags can be combined)
--   `-f filename` (option)
--   `-ffilename` (no space required)
--   `-abcf filename` (flags and option can be combined)
--   `--long` (long flag)
--   `--long_flag=true` (long flag with equals to override default value)
--   `--file filename` (space)
--   `--file=filename` (equals)
+* `-a` (flag)
+* `-abc` (flags can be combined)
+* `-f filename` (option)
+* `-ffilename` (no space required)
+* `-abcf filename` (flags and option can be combined)
+* `--long` (long flag)
+* `--long_flag=true` (long flag with equals to override default value)
+* `--file filename` (space)
+* `--file=filename` (equals)
 
 If `allow_windows_style_options()` is specified in the application or subcommand options can also be given as:
--   `/a` (flag)
--   `/f filename` (option)
--   `/long` (long flag)
--   `/file filename` (space)
--   `/file:filename` (colon)
--   `/long_flag:false` (long flag with : to override the default value)
-=  Windows style options do not allow combining short options or values not separated from the short option like with `-` options
+
+* `/a` (flag)
+* `/f filename` (option)
+* `/long` (long flag)
+* `/file filename` (space)
+* `/file:filename` (colon)
+* `/long_flag:false` (long flag with : to override the default value)
+  * Windows style options do not allow combining short options or values not separated from the short option like with `-` options
 
 Long flag options may be given with an `=<value>` to allow specifying a false value, or some other value to the flag. See [config files](#configuration-file) for details on the values supported.  NOTE: only the `=` or `:` for windows-style options may be used for this, using a space will result in the argument being interpreted as a positional argument.  This syntax can override the default values, and can be disabled by using `disable_flag_override()`.
 
@@ -394,22 +406,22 @@ Validators are structures to check or modify inputs, they can be used to verify
 
 CLI11 has several Validators built-in that perform some common checks
 
--   `CLI::IsMember(...)`: Require an option be a member of a given set. See [Transforming Validators](#transforming-validators) for more details.
--   `CLI::Transformer(...)`: Modify the input using a map. See [Transforming Validators](#transforming-validators) for more details.
--   `CLI::CheckedTransformer(...)`: Modify the input using a map, and require that the input is either in the set or already one of the outputs of the set. See [Transforming Validators](#transforming-validators) for more details.
--   `CLI::AsNumberWithUnit(...)`: Modify the `<NUMBER> <UNIT>` pair by matching the unit and multiplying the number by the corresponding factor. It can be used as a base for transformers, that accept things like size values (`1 KB`) or durations (`0.33 ms`).
--   `CLI::AsSizeValue(...)`: Convert inputs like `100b`, `42 KB`, `101 Mb`, `11 Mib` to absolute values. `KB` can be configured to be interpreted as 10^3 or 2^10.
--   `CLI::ExistingFile`: Requires that the file exists if given.
--   `CLI::ExistingDirectory`: Requires that the directory exists.
--   `CLI::ExistingPath`: Requires that the path (file or directory) exists.
--   `CLI::NonexistentPath`: Requires that the path does not exist.
--   `CLI::Range(min,max)`: Requires that the option be between min and max (make sure to use floating point if needed). Min defaults to 0.
--   `CLI::Bounded(min,max)`: Modify the input such that it is always between min and max (make sure to use floating point if needed). Min defaults to 0.  Will produce an error if conversion is not possible.
--   `CLI::PositiveNumber`: Requires the number be greater than 0
--   `CLI::NonNegativeNumber`: Requires the number be greater or equal to 0
--   `CLI::Number`: Requires the input be a number.
--   `CLI::ValidIPV4`: Requires that the option be a valid IPv4 string e.g. `'255.255.255.255'`, `'10.1.1.7'`.
--   `CLI::TypeValidator<TYPE>`:🚧 Requires that the option be convertible to the specified type e.g.  `CLI::TypeValidator<unsigned int>()` would require that the input be convertible to an `unsigned int` regardless of the end conversion.
+* `CLI::IsMember(...)`: Require an option be a member of a given set. See [Transforming Validators](#transforming-validators) for more details.
+* `CLI::Transformer(...)`: Modify the input using a map. See [Transforming Validators](#transforming-validators) for more details.
+* `CLI::CheckedTransformer(...)`: Modify the input using a map, and require that the input is either in the set or already one of the outputs of the set. See [Transforming Validators](#transforming-validators) for more details.
+* `CLI::AsNumberWithUnit(...)`: Modify the `<NUMBER> <UNIT>` pair by matching the unit and multiplying the number by the corresponding factor. It can be used as a base for transformers, that accept things like size values (`1 KB`) or durations (`0.33 ms`).
+* `CLI::AsSizeValue(...)`: Convert inputs like `100b`, `42 KB`, `101 Mb`, `11 Mib` to absolute values. `KB` can be configured to be interpreted as 10^3 or 2^10.
+* `CLI::ExistingFile`: Requires that the file exists if given.
+* `CLI::ExistingDirectory`: Requires that the directory exists.
+* `CLI::ExistingPath`: Requires that the path (file or directory) exists.
+* `CLI::NonexistentPath`: Requires that the path does not exist.
+* `CLI::Range(min,max)`: Requires that the option be between min and max (make sure to use floating point if needed). Min defaults to 0.
+* `CLI::Bounded(min,max)`: Modify the input such that it is always between min and max (make sure to use floating point if needed). Min defaults to 0.  Will produce an error if conversion is not possible.
+* `CLI::PositiveNumber`: Requires the number be greater than 0
+* `CLI::NonNegativeNumber`: Requires the number be greater or equal to 0
+* `CLI::Number`: Requires the input be a number.
+* `CLI::ValidIPV4`: Requires that the option be a valid IPv4 string e.g. `'255.255.255.255'`, `'10.1.1.7'`.
+* `CLI::TypeValidator<TYPE>`:Requires that the option be convertible to the specified type e.g.  `CLI::TypeValidator<unsigned int>()` would require that the input be convertible to an `unsigned int` regardless of the end conversion.
 
 These Validators can be used by simply passing the name into the `check` or `transform` methods on an option
 
@@ -433,36 +445,39 @@ will produce a check to ensure a value is between 0 and 10 or 20 and 30.
 will produce a check for a number less than or equal to 0.
 
 ##### Transforming Validators
+
 There are a few built in Validators that let you transform values if used with the `transform` function.  If they also do some checks then they can be used `check` but some may do nothing in that case.
--   `CLI::Bounded(min,max)` will bound values between min and max and values outside of that range are limited to min or max,  it will fail if the value cannot be converted and produce a `ValidationError`
--   The `IsMember` Validator lets you specify a set of predefined options. You can pass any container or copyable pointer (including `std::shared_ptr`) to a container to this Validator; the container just needs to be iterable and have a `::value_type`. The key type should be convertible from a string,  You can use an initializer list directly if you like. If you need to modify the set later, the pointer form lets you do that; the type message and check will correctly refer to the current version of the set.  The container passed in can be a set, vector, or a map like structure. If used in the `transform` method the output value will be the matching key as it could be modified by filters.
-After specifying a set of options, you can also specify "filter" functions of the form `T(T)`, where `T` is the type of the values. The most common choices probably will be `CLI::ignore_case` an `CLI::ignore_underscore`, and `CLI::ignore_space`.  These all work on strings but it is possible to define functions that work on other types.
-Here are some examples
-of `IsMember`:
-
--   `CLI::IsMember({"choice1", "choice2"})`: Select from exact match to choices.
--   `CLI::IsMember({"choice1", "choice2"}, CLI::ignore_case, CLI::ignore_underscore)`: Match things like `Choice_1`, too.
--   `CLI::IsMember(std::set<int>({2,3,4}))`: Most containers and types work; you just need `std::begin`, `std::end`, and `::value_type`.
--   `CLI::IsMember(std::map<std::string, TYPE>({{"one", 1}, {"two", 2}}))`: You can use maps; in `->transform()` these replace the matched value with the matched key.  The value member of the map is not used in `IsMember`, so it can be any type.
--   `auto p = std::make_shared<std::vector<std::string>>(std::initializer_list<std::string>("one", "two")); CLI::IsMember(p)`: You can modify `p` later.
--   The `Transformer` and `CheckedTransformer` Validators transform one value into another. Any container or copyable pointer (including `std::shared_ptr`) to a container that generates pairs of values can be passed to these `Validator's`; the container just needs to be iterable and have a `::value_type` that consists of pairs. The key type should be convertible from a string, and the value type should be convertible to a string  You can use an initializer list directly if you like. If you need to modify the map later, the pointer form lets you do that; the description message will correctly refer to the current version of the map.  `Transformer` does not do any checking so values not in the map are ignored.  `CheckedTransformer` takes an extra step of verifying that the value is either one of the map key values, in which case it is transformed, or one of the expected output values, and if not will generate a `ValidationError`.  A Transformer placed using `check` will not do anything.
+
+* `CLI::Bounded(min,max)` will bound values between min and max and values outside of that range are limited to min or max,  it will fail if the value cannot be converted and produce a `ValidationError`
+* The `IsMember` Validator lets you specify a set of predefined options. You can pass any container or copyable pointer (including `std::shared_ptr`) to a container to this Validator; the container just needs to be iterable and have a `::value_type`. The key type should be convertible from a string,  You can use an initializer list directly if you like. If you need to modify the set later, the pointer form lets you do that; the type message and check will correctly refer to the current version of the set.  The container passed in can be a set, vector, or a map like structure. If used in the `transform` method the output value will be the matching key as it could be modified by filters.
+
+After specifying a set of options, you can also specify "filter" functions of the form `T(T)`, where `T` is the type of the values. The most common choices probably will be `CLI::ignore_case` an `CLI::ignore_underscore`, and `CLI::ignore_space`.  These all work on strings but it is possible to define functions that work on other types. Here are some examples of `IsMember`:
+
+* `CLI::IsMember({"choice1", "choice2"})`: Select from exact match to choices.
+* `CLI::IsMember({"choice1", "choice2"}, CLI::ignore_case, CLI::ignore_underscore)`: Match things like `Choice_1`, too.
+* `CLI::IsMember(std::set<int>({2,3,4}))`: Most containers and types work; you just need `std::begin`, `std::end`, and `::value_type`.
+* `CLI::IsMember(std::map<std::string, TYPE>({{"one", 1}, {"two", 2}}))`: You can use maps; in `->transform()` these replace the matched value with the matched key.  The value member of the map is not used in `IsMember`, so it can be any type.
+* `auto p = std::make_shared<std::vector<std::string>>(std::initializer_list<std::string>("one", "two")); CLI::IsMember(p)`: You can modify `p` later.
+* The `Transformer` and `CheckedTransformer` Validators transform one value into another. Any container or copyable pointer (including `std::shared_ptr`) to a container that generates pairs of values can be passed to these `Validator's`; the container just needs to be iterable and have a `::value_type` that consists of pairs. The key type should be convertible from a string, and the value type should be convertible to a string  You can use an initializer list directly if you like. If you need to modify the map later, the pointer form lets you do that; the description message will correctly refer to the current version of the map.  `Transformer` does not do any checking so values not in the map are ignored.  `CheckedTransformer` takes an extra step of verifying that the value is either one of the map key values, in which case it is transformed, or one of the expected output values, and if not will generate a `ValidationError`.  A Transformer placed using `check` will not do anything.
+
 After specifying a map of options, you can also specify "filter" just like in `CLI::IsMember`.
 Here are some examples (`Transformer` and `CheckedTransformer` are interchangeable in the examples)
 of `Transformer`:
 
--   `CLI::Transformer({{"key1", "map1"},{"key2","map2"}})`: Select from key values and produce map values.
-
--   `CLI::Transformer(std::map<std::string,int>({"two",2},{"three",3},{"four",4}}))`: most maplike containers work,  the `::value_type` needs to produce a pair of some kind.
--   `CLI::CheckedTransformer(std::map<std::string, int>({{"one", 1}, {"two", 2}}))`: You can use maps; in `->transform()` these replace the matched key with the value.  `CheckedTransformer` also requires that the value either match one of the keys or match one of known outputs.
--   `auto p = std::make_shared<CLI::TransformPairs<std::string>>(std::initializer_list<std::pair<std::string,std::string>>({"key1", "map1"},{"key2","map2"})); CLI::Transformer(p)`: You can modify `p` later. `TransformPairs<T>` is an alias for `std::vector<std::pair<<std::string,T>>`
+* `CLI::Transformer({{"key1", "map1"},{"key2","map2"}})`: Select from key values and produce map values.
+* `CLI::Transformer(std::map<std::string,int>({"two",2},{"three",3},{"four",4}}))`: most maplike containers work,  the `::value_type` needs to produce a pair of some kind.
+* `CLI::CheckedTransformer(std::map<std::string, int>({{"one", 1}, {"two", 2}}))`: You can use maps; in `->transform()` these replace the matched key with the value.  `CheckedTransformer` also requires that the value either match one of the keys or match one of known outputs.
+* `auto p = std::make_shared<CLI::TransformPairs<std::string>>(std::initializer_list<std::pair<std::string,std::string>>({"key1", "map1"},{"key2","map2"})); CLI::Transformer(p)`: You can modify `p` later. `TransformPairs<T>` is an alias for `std::vector<std::pair<<std::string,T>>`
 
 NOTES:  If the container used in `IsMember`, `Transformer`, or `CheckedTransformer` has a `find` function like `std::unordered_map`  or `std::map` then that function is used to do the searching. If it does not have a `find` function a linear search is performed.  If there are filters present, the fast search is performed first, and if that fails a linear search with the filters on the key values is performed.
 
 ##### Validator operations
+
 Validators are copyable and have a few operations that can be performed on them to alter settings.  Most of the built in Validators have a default description that is displayed in the help.  This can be altered via `.description(validator_description)`.
 The name of a Validator, which is useful for later reference from the `get_validator(name)` method of an `Option` can be set via `.name(validator_name)`
 The operation function of a Validator can be set via
-`.operation(std::function<std::string(std::string &>)`.  The `.active()` function can activate or deactivate a Validator from the operation.  A validator can be set to apply only to a specific element of the output.  For example in a pair option `std::pair<int, std::string>` the first element may need to be a positive integer while the second may need to be a valid file.  The `.application_index(int)` 🆕 function can specify this.  It is zero based and negative indices apply to all values.
+`.operation(std::function<std::string(std::string &>)`.  The `.active()` function can activate or deactivate a Validator from the operation.  A validator can be set to apply only to a specific element of the output.  For example in a pair option `std::pair<int, std::string>` the first element may need to be a positive integer while the second may need to be a valid file.  The `.application_index(int)` function can specify this.  It is zero based and negative indices apply to all values.
+
 ```cpp
 opt->check(CLI::Validator(CLI::PositiveNumber).application_index(0));
 opt->check(CLI::Validator(CLI::ExistingFile).application_index(1));
@@ -507,27 +522,28 @@ opt->get_validator(name);
 
 This will retrieve a Validator with the given name or throw a `CLI::OptionNotFound` error.  If no name is given or name is empty the first unnamed Validator will be returned or the first Validator if there is only one.
 
-or 🆕
+or
 
 ```cpp
 opt->get_validator(index);
 ```
 
 Which will return a validator in the index it is applied which isn't necessarily the order in which was defined.  The pointer can be `nullptr` if an invalid index is given.
-Validators have a few functions to query the current values
--   `get_description()`: Will return a description string
--   `get_name()`: Will return the Validator name
--   `get_active()`: Will return the current active state, true if the Validator is active.
--   `get_application_index()`: 🆕 Will return the current application index.
--   `get_modifying()`: Will return true if the Validator is allowed to modify the input, this can be controlled via the `non_modifying()` method, though it is recommended to let `check` and `transform` option methods manipulate it if needed.
+Validators have a few functions to query the current values:
+
+* `get_description()`: Will return a description string
+* `get_name()`: Will return the Validator name
+* `get_active()`: Will return the current active state, true if the Validator is active.
+* `get_application_index()`: Will return the current application index.
+* `get_modifying()`: Will return true if the Validator is allowed to modify the input, this can be controlled via the `non_modifying()` method, though it is recommended to let `check` and `transform` option methods manipulate it if needed.
 
 #### Getting results
 
 In most cases, the fastest and easiest way is to return the results through a callback or variable specified in one of the `add_*` functions.  But there are situations where this is not possible or desired.  For these cases the results may be obtained through one of the following functions. Please note that these functions will do any type conversions and processing during the call so should not used in performance critical code:
 
--   `results()`: Retrieves a vector of strings with all the results in the order they were given.
--   `results(variable_to_bind_to)`: Gets the results according to the MultiOptionPolicy and converts them just like the `add_option_function` with a variable.
--   `Value=as<type>()`: Returns the result or default value directly as the specified type if possible, can be vector to return all results, and a non-vector to get the result according to the MultiOptionPolicy in place.
+* `->results()`: Retrieves a vector of strings with all the results in the order they were given.
+* `->results(variable_to_bind_to)`: Gets the results according to the MultiOptionPolicy and converts them just like the `add_option_function` with a variable.
+* `Value=opt->as<type>()`: Returns the result or default value directly as the specified type if possible, can be vector to return all results, and a non-vector to get the result according to the MultiOptionPolicy in place.
 
 ### Subcommands
 
@@ -546,72 +562,73 @@ even exit the program through the callback.
 Multiple subcommands are allowed, to allow [`Click`][click] like series of commands (order is preserved).  The same subcommand can be triggered multiple times but all positional arguments will take precedence over the second and future calls of the subcommand.  `->count()` on the subcommand will return the number of times the subcommand was called.  The subcommand callback will only be triggered once unless the `.immediate_callback()`  flag is set or the callback is specified through the `parse_complete_callback()` function. The `final_callback()` is triggered only once.  In which case the callback executes on completion of the subcommand arguments but after the arguments for that subcommand have been parsed, and can be triggered multiple times.
 
 Subcommands may also have an empty name either by calling `add_subcommand` with an empty string for the name or with no arguments.
-Nameless subcommands function a similarly to groups in the main `App`. See [Option groups](#option-groups) to see how this might work.  If an option is not defined in the main App, all nameless subcommands are checked as well.  This allows for the options to be defined in a composable group.  The `add_subcommand` function has an overload for adding a `shared_ptr<App>` so the subcommand(s) could be defined in different components and merged into a main `App`, or possibly multiple `Apps`.  Multiple nameless subcommands are allowed.  Callbacks for nameless subcommands are only triggered if any options from the subcommand were parsed.
+Nameless subcommands function a similarly to groups in the main `App`. See [Option groups](#option-groups) to see how this might work.  If an option is not defined in the main App, all nameless subcommands are checked as well.  This allows for the options to be defined in a composable group.  The `add_subcommand` function has an overload for adding a `shared_ptr<App>` so the subcommand(s) could be defined in different components and merged into a main `App`, or possibly multiple `Apps`.  Multiple nameless subcommands are allowed.  Callbacks for nameless subcommands are only triggered if any options from the subcommand were parsed. Subcommand names given through the `add_subcommand` method have the same restrictions as option names.
 
 #### Subcommand options
 
 There are several options that are supported on the main app and subcommands and option_groups. These are:
 
--   `.ignore_case()`: Ignore the case of this subcommand. Inherited by added subcommands, so is usually used on the main `App`.
--   `.ignore_underscore()`: Ignore any underscores in the subcommand name. Inherited by added subcommands, so is usually used on the main `App`.
--   `.allow_windows_style_options()`: Allow command line options to be parsed in the form of `/s /long /file:file_name.ext`  This option does not change how options are specified in the `add_option` calls or the ability to process options in the form of `-s --long --file=file_name.ext`.
--   `.fallthrough()`: Allow extra unmatched options and positionals to "fall through" and be matched on a parent option. Subcommands always are allowed to "fall through" as in they will first attempt to match on the current subcommand and if they fail will progressively check parents for matching subcommands.
--   `.configurable()`: 🆕 Allow the subcommand to be triggered from a configuration file. By default subcommand options in a configuration file do not trigger a subcommand but will just update default values.
--   `.disable()`: Specify that the subcommand is disabled, if given with a bool value it will enable or disable the subcommand or option group.
--   `.disabled_by_default()`: Specify that at the start of parsing the subcommand/option_group should be disabled. This is useful for allowing some Subcommands to trigger others.
--   `.enabled_by_default()`: Specify that at the start of each parse the subcommand/option_group should be enabled.  This is useful for allowing some Subcommands to disable others.
--   `.silent()`: 🚧 Specify that the subcommand is silent meaning that if used it won't show up in the subcommand list.  This allows the use of subcommands as modifiers
--   `.validate_positionals()`: Specify that positionals should pass validation before matching.  Validation is specified through `transform`, `check`, and `each` for an option.  If an argument fails validation it is not an error and matching proceeds to the next available positional or extra arguments.
--   `.excludes(option_or_subcommand)`: If given an option pointer or pointer to another subcommand, these subcommands cannot be given together.  In the case of options, if the option is passed the subcommand cannot be used and will generate an error.
--   `.needs(option_or_subcommand)`: 🆕 If given an option pointer or pointer to another subcommand, the subcommands will require the given option to have been given before this subcommand is validated which occurs prior to execution of any callback or after parsing is completed.
--   `.require_option()`: Require 1 or more options or option groups be used.
--   `.require_option(N)`: Require `N` options or option groups, if `N>0`, or up to `N` if `N<0`. `N=0` resets to the default to 0 or more.
--   `.require_option(min, max)`: Explicitly set min and max allowed options or option groups. Setting `max` to 0 implies unlimited options.
--   `.require_subcommand()`: Require 1 or more subcommands.
--   `.require_subcommand(N)`: Require `N` subcommands if `N>0`, or up to `N` if `N<0`. `N=0` resets to the default to 0 or more.
--   `.require_subcommand(min, max)`: Explicitly set min and max allowed subcommands. Setting `max` to 0 is unlimited.
--   `.add_subcommand(name="", description="")`: Add a subcommand, returns a pointer to the internally stored subcommand.
--   `.add_subcommand(shared_ptr<App>)`: Add a subcommand by shared_ptr, returns a pointer to the internally stored subcommand.
--   `.remove_subcommand(App)`: Remove a subcommand from the app or subcommand.
--   `.got_subcommand(App_or_name)`: Check to see if a subcommand was received on the command line.
--   `.get_subcommands(filter)`: The list of subcommands that match a particular filter function.
--   `.add_option_group(name="", description="")`: Add an [option group](#option-groups) to an App,  an option group is specialized subcommand intended for containing groups of options or other groups for controlling how options interact.
--   `.get_parent()`: Get the parent App or `nullptr` if called on master App.
--   `.get_option(name)`: Get an option pointer by option name will throw if the specified option is not available,  nameless subcommands are also searched
--   `.get_option_no_throw(name)`: Get an option pointer by option name. This function will return a `nullptr` instead of throwing if the option is not available.
--   `.get_options(filter)`: Get the list of all defined option pointers (useful for processing the app for custom output formats).
--   `.parse_order()`: Get the list of option pointers in the order they were parsed (including duplicates).
--   `.formatter(fmt)`: Set a formatter, with signature `std::string(const App*, std::string, AppFormatMode)`. See Formatting for more details.
--   `.description(str)`: Set/change the description.
--   `.get_description()`: Access the description.
--   `.alias(str)`: 🆕 set an alias for the subcommand, this allows subcommands to be called by more than one name.
--   `.parsed()`: True if this subcommand was given on the command line.
--   `.count()`: Returns the number of times the subcommand was called.
--   `.count(option_name)`: Returns the number of times a particular option was called.
--   `.count_all()`: Returns the total number of arguments a particular subcommand processed, on the master App it returns the total number of processed commands.
--   `.name(name)`: Add or change the name.
--   `.callback(void() function)`: Set the callback for an app. 🆕 either sets the pre_parse_callback or the final_callback depending on the value of `immediate_callback`. See [Subcommand callbacks](#callbacks) for some additional details.
--   `.parse_complete_callback(void() function)`: 🆕 Set the callback that runs at the completion of parsing. for subcommands this is executed at the completion of the single subcommand and can be executed multiple times. See [Subcommand callbacks](#callbacks) for some additional details.
--   `.final_callback(void() function)`: 🆕 Set the callback that runs at the end of all processing. This is the last thing that is executed before returning. See [Subcommand callbacks](#callbacks) for some additional details.
--   `.immediate_callback()`: Specifies whether the callback for a subcommand should be run as a `parse_complete_callback`(true) or `final_callback`(false). When used on the main app 🆕 it will execute the main app callback prior to the callbacks for a subcommand if they do not also have the `immediate_callback` flag set. 🆕 It is preferable to use the `parse_complete_callback` or `final_callback` directly instead of the `callback` and `immediate_callback` if one wishes to control the ordering and timing of callback.  Though `immediate_callback` can be used to swap them if that is needed.
--   `.pre_parse_callback(void(std::size_t) function)`: Set a callback that executes after the first argument of an application is processed.  See [Subcommand callbacks](#callbacks) for some additional details.
--   `.allow_extras()`: Do not throw an error if extra arguments are left over.
--   `.positionals_at_end()`: Specify that positional arguments occur as the last arguments and throw an error if an unexpected positional is encountered.
--   `.prefix_command()`: Like `allow_extras`, but stop immediately on the first unrecognized item. It is ideal for allowing your app or subcommand to be a "prefix" to calling another app.
--   `.footer(message)`: Set text to appear at the bottom of the help string.
--   `.footer(std::string())`: 🆕 Set a callback to generate a string that will appear at the end of the help string.
--   `.set_help_flag(name, message)`: Set the help flag name and message, returns a pointer to the created option.
--   `.set_help_all_flag(name, message)`: Set the help all flag name and message, returns a pointer to the created option. Expands subcommands.
--   `.failure_message(func)`: Set the failure message function. Two provided: `CLI::FailureMessage::help` and `CLI::FailureMessage::simple` (the default).
--   `.group(name)`: Set a group name, defaults to `"Subcommands"`. Setting `""` will be hide the subcommand.
--   `[option_name]`: retrieve a const pointer to an option given by `option_name` for Example `app["--flag1"]` will get a pointer to the option for the "--flag1" value,  `app["--flag1"]->as<bool>()` will get the results of the command line for a flag. The operation will throw an exception if the option name is not valid.
+* `.ignore_case()`: Ignore the case of this subcommand. Inherited by added subcommands, so is usually used on the main `App`.
+* `.ignore_underscore()`: Ignore any underscores in the subcommand name. Inherited by added subcommands, so is usually used on the main `App`.
+* `.allow_windows_style_options()`: Allow command line options to be parsed in the form of `/s /long /file:file_name.ext`  This option does not change how options are specified in the `add_option` calls or the ability to process options in the form of `-s --long --file=file_name.ext`.
+* `.fallthrough()`: Allow extra unmatched options and positionals to "fall through" and be matched on a parent option. Subcommands always are allowed to "fall through" as in they will first attempt to match on the current subcommand and if they fail will progressively check parents for matching subcommands.
+* `.configurable()`: Allow the subcommand to be triggered from a configuration file. By default subcommand options in a configuration file do not trigger a subcommand but will just update default values.
+* `.disable()`: Specify that the subcommand is disabled, if given with a bool value it will enable or disable the subcommand or option group.
+* `.disabled_by_default()`: Specify that at the start of parsing the subcommand/option_group should be disabled. This is useful for allowing some Subcommands to trigger others.
+* `.enabled_by_default()`: Specify that at the start of each parse the subcommand/option_group should be enabled.  This is useful for allowing some Subcommands to disable others.
+* `.silent()`: Specify that the subcommand is silent meaning that if used it won't show up in the subcommand list.  This allows the use of subcommands as modifiers
+* `.validate_positionals()`: Specify that positionals should pass validation before matching.  Validation is specified through `transform`, `check`, and `each` for an option.  If an argument fails validation it is not an error and matching proceeds to the next available positional or extra arguments.
+* `.excludes(option_or_subcommand)`: If given an option pointer or pointer to another subcommand, these subcommands cannot be given together.  In the case of options, if the option is passed the subcommand cannot be used and will generate an error.
+* `.needs(option_or_subcommand)`: If given an option pointer or pointer to another subcommand, the subcommands will require the given option to have been given before this subcommand is validated which occurs prior to execution of any callback or after parsing is completed.
+* `.require_option()`: Require 1 or more options or option groups be used.
+* `.require_option(N)`: Require `N` options or option groups, if `N>0`, or up to `N` if `N<0`. `N=0` resets to the default to 0 or more.
+* `.require_option(min, max)`: Explicitly set min and max allowed options or option groups. Setting `max` to 0 implies unlimited options.
+* `.require_subcommand()`: Require 1 or more subcommands.
+* `.require_subcommand(N)`: Require `N` subcommands if `N>0`, or up to `N` if `N<0`. `N=0` resets to the default to 0 or more.
+* `.require_subcommand(min, max)`: Explicitly set min and max allowed subcommands. Setting `max` to 0 is unlimited.
+* `.add_subcommand(name="", description="")`: Add a subcommand, returns a pointer to the internally stored subcommand.
+* `.add_subcommand(shared_ptr<App>)`: Add a subcommand by shared_ptr, returns a pointer to the internally stored subcommand.
+* `.remove_subcommand(App)`: Remove a subcommand from the app or subcommand.
+* `.got_subcommand(App_or_name)`: Check to see if a subcommand was received on the command line.
+* `.get_subcommands(filter)`: The list of subcommands that match a particular filter function.
+* `.add_option_group(name="", description="")`: Add an [option group](#option-groups) to an App,  an option group is specialized subcommand intended for containing groups of options or other groups for controlling how options interact.
+* `.get_parent()`: Get the parent App or `nullptr` if called on master App.
+* `.get_option(name)`: Get an option pointer by option name will throw if the specified option is not available,  nameless subcommands are also searched
+* `.get_option_no_throw(name)`: Get an option pointer by option name. This function will return a `nullptr` instead of throwing if the option is not available.
+* `.get_options(filter)`: Get the list of all defined option pointers (useful for processing the app for custom output formats).
+* `.parse_order()`: Get the list of option pointers in the order they were parsed (including duplicates).
+* `.formatter(fmt)`: Set a formatter, with signature `std::string(const App*, std::string, AppFormatMode)`. See Formatting for more details.
+* `.description(str)`: Set/change the description.
+* `.get_description()`: Access the description.
+* `.alias(str)`: set an alias for the subcommand, this allows subcommands to be called by more than one name.
+* `.parsed()`: True if this subcommand was given on the command line.
+* `.count()`: Returns the number of times the subcommand was called.
+* `.count(option_name)`: Returns the number of times a particular option was called.
+* `.count_all()`: Returns the total number of arguments a particular subcommand processed, on the master App it returns the total number of processed commands.
+* `.name(name)`: Add or change the name.
+* `.callback(void() function)`: Set the callback for an app. Either sets the `pre_parse_callback` or the `final_callback` depending on the value of `immediate_callback`. See [Subcommand callbacks](#callbacks) for some additional details.
+* `.parse_complete_callback(void() function)`: Set the callback that runs at the completion of parsing. For subcommands this is executed at the completion of the single subcommand and can be executed multiple times. See [Subcommand callbacks](#callbacks) for some additional details.
+* `.final_callback(void() function)`: Set the callback that runs at the end of all processing. This is the last thing that is executed before returning. See [Subcommand callbacks](#callbacks) for some additional details.
+* `.immediate_callback()`: Specifies whether the callback for a subcommand should be run as a `parse_complete_callback`(true) or `final_callback`(false). When used on the main app it will execute the main app callback prior to the callbacks for a subcommand if they do not also have the `immediate_callback` flag set. It is preferable to use the `parse_complete_callback` or `final_callback` directly instead of the `callback` and `immediate_callback` if one wishes to control the ordering and timing of callback.  Though `immediate_callback` can be used to swap them if that is needed.
+* `.pre_parse_callback(void(std::size_t) function)`: Set a callback that executes after the first argument of an application is processed.  See [Subcommand callbacks](#callbacks) for some additional details.
+* `.allow_extras()`: Do not throw an error if extra arguments are left over.
+* `.positionals_at_end()`: Specify that positional arguments occur as the last arguments and throw an error if an unexpected positional is encountered.
+* `.prefix_command()`: Like `allow_extras`, but stop immediately on the first unrecognized item. It is ideal for allowing your app or subcommand to be a "prefix" to calling another app.
+* `.footer(message)`: Set text to appear at the bottom of the help string.
+* `.footer(std::string())`: Set a callback to generate a string that will appear at the end of the help string.
+* `.set_help_flag(name, message)`: Set the help flag name and message, returns a pointer to the created option.
+* `.set_version_flag(name, versionString or callback, help_message)`: Set the version flag name and version string or callback and optional help message, returns a pointer to the created option.
+* `.set_help_all_flag(name, message)`: Set the help all flag name and message, returns a pointer to the created option. Expands subcommands.
+* `.failure_message(func)`: Set the failure message function. Two provided: `CLI::FailureMessage::help` and `CLI::FailureMessage::simple` (the default).
+* `.group(name)`: Set a group name, defaults to `"Subcommands"`. Setting `""` will be hide the subcommand.
+* `[option_name]`: retrieve a const pointer to an option given by `option_name` for Example `app["--flag1"]` will get a pointer to the option for the "--flag1" value,  `app["--flag1"]->as<bool>()` will get the results of the command line for a flag. The operation will throw an exception if the option name is not valid.
 
 > Note: if you have a fixed number of required positional options, that will match before subcommand names. `{}` is an empty filter function, and any positional argument will match before repeated subcommand names.
 
-
 #### Callbacks
+
 A subcommand has three optional callbacks that are executed at different stages of processing.  The `preparse_callback` is executed once after the first argument of a subcommand or application is processed and gives an argument for the number of remaining arguments to process.  For the main app the first argument is considered the program name,  for subcommands the first argument is the subcommand name.  For Option groups and nameless subcommands the first argument is after the first argument or subcommand is processed from that group.
-The second callback is executed after parsing.  This is known as the `parse_complete_callback`. For subcommands this is executed immediately after parsing and can be executed multiple times if a subcommand is called multiple times.    On the main app this callback is executed after all the `parse_complete_callback`s for the subcommands are executed but prior to any `final_callback` calls in the subcommand or option groups. If the main app or subcommand has a config file, no data from the config file will be reflected in `parse_complete_callback` on named subcommands 🆕.  For `option_group`s the `parse_complete_callback` is executed prior to the `parse_complete_callback` on the main app but after the `config_file` is loaded (if specified).  The 🆕 `final_callback` is executed after all processing is complete.  After the `parse_complete_callback` is executed on the main app, the used subcommand `final_callback` are executed followed by the "final callback" for option groups.  The last thing to execute is the `final_callback` for the `main_app`.
+The second callback is executed after parsing.  This is known as the `parse_complete_callback`. For subcommands this is executed immediately after parsing and can be executed multiple times if a subcommand is called multiple times.    On the main app this callback is executed after all the `parse_complete_callback`s for the subcommands are executed but prior to any `final_callback` calls in the subcommand or option groups. If the main app or subcommand has a config file, no data from the config file will be reflected in `parse_complete_callback` on named subcommands.  For `option_group`s the `parse_complete_callback` is executed prior to the `parse_complete_callback` on the main app but after the `config_file` is loaded (if specified).  The `final_callback` is executed after all processing is complete.  After the `parse_complete_callback` is executed on the main app, the used subcommand `final_callback` are executed followed by the "final callback" for option groups.  The last thing to execute is the `final_callback` for the `main_app`.
 For example say an application was set up like
 
 ```cpp
@@ -622,25 +639,25 @@ auto sub2=app.add_subcommand("sub2")->final_callback(c2)->preparse_callback(pc2)
 app.preparse_callback( pa);
 
 ... A bunch of other options
-
 ```
 
 Then the command line is given as
 
-```
+```bash
 program --opt1 opt1_val  sub1 --sub1opt --sub1optb val sub2 --sub2opt sub1 --sub1opt2 sub2 --sub2opt2 val
 ```
 
--   pa will be called prior to parsing any values with an argument of 13.
--   pc1 will be called immediately after processing the sub1 command with a value of 10.
--   c1 will be called when the `sub2` command is encountered.
--   pc2 will be called with value of 6 after the sub2 command is encountered.
--   c1 will be called again after the second sub2 command is encountered.
--   ac1 will be called after processing of all arguments
--   c2 will be called once after processing all arguments.
--   ac2 will be called last after completing  all lower level callbacks have been executed.
+* `pa` will be called prior to parsing any values with an argument of 13.
+* `pc1` will be called immediately after processing the `sub1` command with a value of 10.
+* `c1` will be called when the `sub2` command is encountered.
+* `pc2` will be called with value of 6 after the `sub2` command is encountered.
+* `c1` will be called again after the second `sub2` command is encountered.
+* `ac1` will be called after processing of all arguments
+* `c2` will be called once after processing all arguments.
+* `ac2` will be called last after completing  all lower level callbacks have been executed.
 
 A subcommand is considered terminated when one of the following conditions are met.
+
 1. There are no more arguments to process
 2. Another subcommand is encountered that would not fit in an optional slot of the subcommand
 3. The `positional_mark` (`--`) is encountered and there are no available positional slots in the subcommand.
@@ -648,8 +665,6 @@ A subcommand is considered terminated when one of the following conditions are m
 
 Prior to executed a `parse_complete_callback` all contained options are processed before the callback is triggered.  If a subcommand with a `parse_complete_callback` is called again, then the contained options are reset, and can be triggered again.
 
-
-
 #### Option groups
 
 The subcommand method
@@ -658,7 +673,7 @@ The subcommand method
 .add_option_group(name,description)
 ```
 
-Will create an option group, and return a pointer to it. The argument for `description` is optional and can be omitted.  An option group allows creation of a collection of options, similar to the groups function on options, but with additional controls and requirements.  They allow specific sets of options to be composed and controlled as a collective.  For an example see [range example](https://github.com/CLIUtils/CLI11/blob/master/examples/ranges.cpp).  Option groups are a specialization of an App so all [functions](#subcommand-options) that work with an App or subcommand also work on option groups.  Options can be created as part of an option group using the add functions just like a subcommand, or previously created options can be added through
+Will create an option group, and return a pointer to it. The argument for `description` is optional and can be omitted.  An option group allows creation of a collection of options, similar to the groups function on options, but with additional controls and requirements.  They allow specific sets of options to be composed and controlled as a collective.  For an example see [range example](https://github.com/CLIUtils/CLI11/blob/master/examples/ranges.cpp).  Option groups are a specialization of an App so all [functions](#subcommand-options) that work with an App or subcommand also work on option groups.  Options can be created as part of an option group using the add functions just like a subcommand, or previously created options can be added through.  The name given in an option group must not contain newlines or null characters.🆕
 
 ```cpp
 ogroup->add_option(option_pointer);
@@ -686,17 +701,20 @@ CLI::TriggerOff(group2_pointer, disabled_group);
 
 These functions make use of `preparse_callback`, `enabled_by_default()` and `disabled_by_default`.  The triggered group may be a vector of group pointers.  These methods should only be used once per group and will override any previous use of the underlying functions.  More complex arrangements can be accomplished using similar methodology with a custom `preparse_callback` function that does more.
 
-Additional helper functions `deprecate_option` 🆕 and `retire_option` 🆕 are available to deprecate or retire options
+Additional helper functions `deprecate_option` and `retire_option` are available to deprecate or retire options
+
 ```cpp
 CLI::deprecate_option(option *, replacement_name="");
 CLI::deprecate_option(App,option_name,replacement_name="");
 ```
+
 will specify that the option is deprecated which will display a message in the help and a warning on first usage.  Deprecated options function normally but will add a message in the help and display a warning on first use.
 
 ```cpp
 CLI::retire_option(App,option *);
 CLI::retire_option(App,option_name);
 ```
+
 will create an option that does nothing by default and will display a warning on first usage that the option is retired and has no effect.  If the option exists it is replaces with a dummy option that takes the same arguments.
 
 If an empty string is passed the option group name the entire group will be hidden in the help results.  For example.
@@ -704,6 +722,7 @@ If an empty string is passed the option group name the entire group will be hidd
 ```cpp
 auto hidden_group=app.add_option_group("");
 ```
+
 will create a group such that no options in that group are displayed in the help string.
 
 ### Configuration file
@@ -715,7 +734,7 @@ app.set_config(option_name="",
                required=false)
 ```
 
-If this is called with no arguments, it will remove the configuration file option (like `set_help_flag`). Setting a configuration option is special. If it is present, it will be read along with the normal command line arguments. The file will be read if it exists, and does not throw an error unless `required` is `true`. Configuration files are in [TOML] format by default 🚧, though the default reader can also accept files in INI format as well 🆕. It should be noted that CLI11 does not contain a full TOML parser but can read strings from most TOML file and run them through the CLI11 parser. Other formats can be added by an adept user, some variations are available through customization points in the default formatter. An example of a TOML file 🆕:
+If this is called with no arguments, it will remove the configuration file option (like `set_help_flag`). Setting a configuration option is special. If it is present, it will be read along with the normal command line arguments. The file will be read if it exists, and does not throw an error unless `required` is `true`. Configuration files are in [TOML][] format by default, though the default reader can also accept files in INI format as well. It should be noted that CLI11 does not contain a full TOML parser but can read strings from most TOML file and run them through the CLI11 parser. Other formats can be added by an adept user, some variations are available through customization points in the default formatter. An example of a TOML file:
 
 ```toml
 # Comments are supported, using a #
@@ -731,7 +750,9 @@ str_vector = ["one","two","and three"]
 in_subcommand = Wow
 sub.subcommand = true
 ```
+
 or equivalently in INI format
+
 ```ini
 ; Comments are supported, using a ;
 ; The default section is [default], case insensitive
@@ -747,10 +768,10 @@ in_subcommand = Wow
 sub.subcommand = true
 ```
 
-Spaces before and after the name and argument are ignored. Multiple arguments are separated by spaces. One set of quotes will be removed, preserving spaces (the same way the command line works). Boolean options can be `true`, `on`, `1`, `yes`, `enable`; or `false`, `off`, `0`, `no`, `disable` (case insensitive). Sections (and `.` separated names) are treated as subcommands (note: this does not necessarily mean that subcommand was passed, it just sets the "defaults"). You cannot set positional-only arguments.  🆕 Subcommands can be triggered from configuration files if the `configurable` flag was set on the subcommand.  Then the use of `[subcommand]` notation will trigger a subcommand and cause it to act as if it were on the command line.
+Spaces before and after the name and argument are ignored. Multiple arguments are separated by spaces. One set of quotes will be removed, preserving spaces (the same way the command line works). Boolean options can be `true`, `on`, `1`, `yes`, `enable`; or `false`, `off`, `0`, `no`, `disable` (case insensitive). Sections (and `.` separated names) are treated as subcommands (note: this does not necessarily mean that subcommand was passed, it just sets the "defaults"). You cannot set positional-only arguments.  Subcommands can be triggered from configuration files if the `configurable` flag was set on the subcommand.  Then the use of `[subcommand]` notation will trigger a subcommand and cause it to act as if it were on the command line.
 
 To print a configuration file from the passed
-arguments, use `.config_to_str(default_also=false, write_description=false)`, where `default_also` will also show any defaulted arguments, and `write_description` will include the app and option descriptions.  See [Config files](https://cliutils.github.io/CLI11/book/chapters/config.html) for some additional details.
+arguments, use `.config_to_str(default_also=false, write_description=false)`, where `default_also` will also show any defaulted arguments, and `write_description` will include the app and option descriptions.  See [Config files](https://cliutils.github.io/CLI11/book/chapters/config.html) for some additional details and customization points.
 
 If it is desired that multiple configuration be allowed.  Use
 
@@ -758,7 +779,7 @@ If it is desired that multiple configuration be allowed.  Use
 app.set_config("--config")->expected(1, X);
 ```
 
-Where X is some positive number and will allow up to `X` configuration files to be specified by separate `--config` arguments.
+Where X is some positive number and will allow up to `X` configuration files to be specified by separate `--config` arguments.  Value strings with quote characters in it will be printed with a single quote. All other arguments will use double quote.  Empty strings will use a double quoted argument. Numerical or boolean values are not quoted.
 
 ### Inheriting defaults
 
@@ -788,8 +809,8 @@ The App class was designed allow toolkits to subclass it, to provide preset defa
 but before run behavior, while
 still giving the user freedom to `callback` on the main app.
 
-The most important parse function is `parse(std::vector<std::string>)`, which takes a reversed list of arguments (so that `pop_back` processes the args in the correct order). `get_help_ptr` and `get_config_ptr` give you access to the help/config option pointers. The standard `parse` manually sets the name from the first argument, so it should not be in this vector. You can also use `parse(string, bool)` to split up and parse a string; the optional boolean should be set to true if you are
-including the program name in the string, and false otherwise.
+The most important parse function is `parse(std::vector<std::string>)`, which takes a reversed list of arguments (so that `pop_back` processes the args in the correct order). `get_help_ptr` and `get_config_ptr` give you access to the help/config option pointers. The standard `parse` manually sets the name from the first argument, so it should not be in this vector. You can also use `parse(string, bool)` to split up and parse a single string; the optional boolean should be set to true if you are
+including the program name in the string, and false otherwise.  The program name can contain spaces if it is an existing file,  otherwise can be enclosed in quotes(single quote, double quote or backtick).  Embedded quote characters can be escaped with `\`.
 
 Also, in a related note, the `App` you get a pointer to is stored in the parent `App` in a `shared_ptr`s (similar to `Option`s) and are deleted when the main `App` goes out of scope unless the object has another owner.
 
@@ -800,7 +821,7 @@ Every `add_` option you have seen so far depends on one method that takes a lamb
 
 Other values can be added as long as they support `operator>>` (and defaults can be printed if they support `operator<<`). To add a new type, for example, provide a custom `operator>>` with an `istream` (inside the CLI namespace is fine if you don't want to interfere with an existing `operator>>`).
 
-If you wanted to extend this to support a completely new type, use a lambda or add a specialization of the `lexical_cast` function template in the namespace `CLI::detail` with the type you need to convert to. Some examples of some new parsers for `complex<double>` that support all of the features of a standard `add_options` call are in [one of the tests](./tests/NewParseTest.cpp). A simpler example is shown below:
+If you wanted to extend this to support a completely new type, use a lambda or add a specialization of the `lexical_cast` function template in the namespace of the type you need to convert to. Some examples of some new parsers for `complex<double>` that support all of the features of a standard `add_options` call are in [one of the tests](./tests/NewParseTest.cpp). A simpler example is shown below:
 
 #### Example
 
@@ -871,28 +892,28 @@ The API is [documented here][api-docs]. Also see the [CLI11 tutorial GitBook][gi
 
 Several short examples of different features are included in the repository. A brief description of each is included here
 
- - [callback_passthrough](https://github.com/CLIUtils/CLI11/blob/master/examples/callback_passthrough.cpp): Example of directly passing remaining arguments through to a callback function which generates a CLI11 application based on existing arguments.
- - [digit_args](https://github.com/CLIUtils/CLI11/blob/master/examples/digit_args.cpp):  Based on [Issue #123](https://github.com/CLIUtils/CLI11/issues/123), uses digit flags to pass a value
- - [enum](https://github.com/CLIUtils/CLI11/blob/master/examples/enum.cpp):  Using enumerations in an option, and the use of [CheckedTransformer](#transforming-validators)
- - [enum_ostream](https://github.com/CLIUtils/CLI11/blob/master/examples/enum_ostream.cpp):  In addition to the contents of example enum.cpp, this example shows how a custom ostream operator overrides CLI11's enum streaming.
- - [formatter](https://github.com/CLIUtils/CLI11/blob/master/examples/formatter.cpp): Illustrating usage of a custom formatter
- - [groups](https://github.com/CLIUtils/CLI11/blob/master/examples/groups.cpp):  Example using groups of options for help grouping and a the timer helper class
- - [inter_argument_order](https://github.com/CLIUtils/CLI11/blob/master/examples/inter_argument_order.cpp): An app to practice mixing unlimited arguments, but still recover the original order.
- - [json](https://github.com/CLIUtils/CLI11/blob/master/examples/json.cpp):  Using JSON as a config file parser
- - [modhelp](https://github.com/CLIUtils/CLI11/blob/master/examples/modhelp.cpp):  How to modify the help flag to do something other than default
- - [nested](https://github.com/CLIUtils/CLI11/blob/master/examples/nested.cpp):  Nested subcommands
- - [option_groups](https://github.com/CLIUtils/CLI11/blob/master/examples/option_groups.cpp):  illustrating the use of option groups and a required number of options.
- based on [Issue #88](https://github.com/CLIUtils/CLI11/issues/88) to set interacting groups of options
- - [positional_arity](https://github.com/CLIUtils/CLI11/blob/master/examples/positional_arity.cpp): Illustrating use of `preparse_callback` to handle situations where the number of arguments can determine which should get parsed,  Based on [Issue #166](https://github.com/CLIUtils/CLI11/issues/166)
- - [positional_validation](https://github.com/CLIUtils/CLI11/blob/master/examples/positional_validation.cpp): Example of how positional arguments are validated using the `validate_positional` flag, also based on [Issue #166](https://github.com/CLIUtils/CLI11/issues/166)
- - [prefix_command](https://github.com/CLIUtils/CLI11/blob/master/examples/prefix_command.cpp): illustrating use of the `prefix_command` flag.
- - [ranges](https://github.com/CLIUtils/CLI11/blob/master/examples/ranges.cpp):  App to demonstrate exclusionary option groups based on [Issue #88](https://github.com/CLIUtils/CLI11/issues/88)
- - [shapes](https://github.com/CLIUtils/CLI11/blob/master/examples/shapes.cpp): illustrating how to set up repeated subcommands Based on [gitter discussion](https://gitter.im/CLI11gitter/Lobby?at=5c7af6b965ffa019ea788cd5)
- - [simple](https://github.com/CLIUtils/CLI11/blob/master/examples/simple.cpp): a simple example of how to set up a CLI11 Application with different flags and options
- - [subcom_help](https://github.com/CLIUtils/CLI11/blob/master/examples/subcom_help.cpp): configuring help for subcommands
- - [subcom_partitioned](https://github.com/CLIUtils/CLI11/blob/master/examples/subcom_partitioned.cpp): Example with a timer and subcommands generated separately and added to the main app later.
- - [subcommands](https://github.com/CLIUtils/CLI11/blob/master/examples/subcommands.cpp): Short example of subcommands
- - [validators](https://github.com/CLIUtils/CLI11/blob/master/examples/validators.cpp): Example illustrating use of validators
+* [callback_passthrough](https://github.com/CLIUtils/CLI11/blob/master/examples/callback_passthrough.cpp): Example of directly passing remaining arguments through to a callback function which generates a CLI11 application based on existing arguments.
+* [custom_parse](https://github.com/CLIUtils/CLI11/blob/master/examples/custom_parse.cpp): Based on [Issue #566](https://github.com/CLIUtils/CLI11/issues/566), example of custom parser
+* [digit_args](https://github.com/CLIUtils/CLI11/blob/master/examples/digit_args.cpp): Based on [Issue #123](https://github.com/CLIUtils/CLI11/issues/123), uses digit flags to pass a value
+* [enum](https://github.com/CLIUtils/CLI11/blob/master/examples/enum.cpp): Using enumerations in an option, and the use of [CheckedTransformer](#transforming-validators)
+* [enum_ostream](https://github.com/CLIUtils/CLI11/blob/master/examples/enum_ostream.cpp): In addition to the contents of example enum.cpp, this example shows how a custom ostream operator overrides CLI11's enum streaming.
+* [formatter](https://github.com/CLIUtils/CLI11/blob/master/examples/formatter.cpp): Illustrating usage of a custom formatter
+* [groups](https://github.com/CLIUtils/CLI11/blob/master/examples/groups.cpp): Example using groups of options for help grouping and a the timer helper class
+* [inter_argument_order](https://github.com/CLIUtils/CLI11/blob/master/examples/inter_argument_order.cpp): An app to practice mixing unlimited arguments, but still recover the original order.
+* [json](https://github.com/CLIUtils/CLI11/blob/master/examples/json.cpp): Using JSON as a config file parser
+* [modhelp](https://github.com/CLIUtils/CLI11/blob/master/examples/modhelp.cpp): How to modify the help flag to do something other than default
+* [nested](https://github.com/CLIUtils/CLI11/blob/master/examples/nested.cpp): Nested subcommands
+* [option_groups](https://github.com/CLIUtils/CLI11/blob/master/examples/option_groups.cpp): Illustrating the use of option groups and a required number of options. Based on [Issue #88](https://github.com/CLIUtils/CLI11/issues/88) to set interacting groups of options
+* [positional_arity](https://github.com/CLIUtils/CLI11/blob/master/examples/positional_arity.cpp): Illustrating use of `preparse_callback` to handle situations where the number of arguments can determine which should get parsed,  Based on [Issue #166](https://github.com/CLIUtils/CLI11/issues/166)
+* [positional_validation](https://github.com/CLIUtils/CLI11/blob/master/examples/positional_validation.cpp): Example of how positional arguments are validated using the `validate_positional` flag, also based on [Issue #166](https://github.com/CLIUtils/CLI11/issues/166)
+* [prefix_command](https://github.com/CLIUtils/CLI11/blob/master/examples/prefix_command.cpp): Illustrating use of the `prefix_command` flag.
+* [ranges](https://github.com/CLIUtils/CLI11/blob/master/examples/ranges.cpp): App to demonstrate exclusionary option groups based on [Issue #88](https://github.com/CLIUtils/CLI11/issues/88)
+* [shapes](https://github.com/CLIUtils/CLI11/blob/master/examples/shapes.cpp): Illustrating how to set up repeated subcommands Based on [gitter discussion](https://gitter.im/CLI11gitter/Lobby?at=5c7af6b965ffa019ea788cd5)
+* [simple](https://github.com/CLIUtils/CLI11/blob/master/examples/simple.cpp): A simple example of how to set up a CLI11 Application with different flags and options
+* [subcom_help](https://github.com/CLIUtils/CLI11/blob/master/examples/subcom_help.cpp): Configuring help for subcommands
+* [subcom_partitioned](https://github.com/CLIUtils/CLI11/blob/master/examples/subcom_partitioned.cpp): Example with a timer and subcommands generated separately and added to the main app later.
+* [subcommands](https://github.com/CLIUtils/CLI11/blob/master/examples/subcommands.cpp): Short example of subcommands
+* [validators](https://github.com/CLIUtils/CLI11/blob/master/examples/validators.cpp): Example illustrating use of validators
 
 ## Contribute
 
@@ -901,7 +922,6 @@ This readme roughly follows the [Standard Readme Style][] and includes a mention
 
 This project was created by [Henry Schreiner](https://github.com/henryiii) and major features were added by  [Philip Top](https://github.com/phlptp). Special thanks to all the contributors ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
 
-
 <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
 <!-- prettier-ignore-start -->
 <!-- markdownlint-disable -->
@@ -965,6 +985,12 @@ This project was created by [Henry Schreiner](https://github.com/henryiii) and m
     <td align="center"><a href="https://github.com/ZeeD26"><img src="https://avatars2.githubusercontent.com/u/2487468?v=4" width="100px;" alt=""/><br /><sub><b>Dominik Steinberger</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=ZeeD26" title="Code">💻</a></td>
     <td align="center"><a href="https://github.com/dfleury2"><img src="https://avatars1.githubusercontent.com/u/4805384?v=4" width="100px;" alt=""/><br /><sub><b>D. Fleury</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=dfleury2" title="Code">💻</a></td>
     <td align="center"><a href="https://github.com/dbarowy"><img src="https://avatars3.githubusercontent.com/u/573142?v=4" width="100px;" alt=""/><br /><sub><b>Dan Barowy</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=dbarowy" title="Documentation">📖</a></td>
+    <td align="center"><a href="https://github.com/paddy-hack"><img src="https://avatars.githubusercontent.com/u/6804372?v=4" width="100px;" alt=""/><br /><sub><b>Olaf Meeuwissen</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=paddy-hack" title="Code">💻</a></td>
+    <td align="center"><a href="https://github.com/dryleev"><img src="https://avatars.githubusercontent.com/u/83670813?v=4" width="100px;" alt=""/><br /><sub><b>dryleev</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=dryleev" title="Code">💻</a></td>
+    <td align="center"><a href="https://github.com/AnticliMaxtic"><img src="https://avatars.githubusercontent.com/u/43995389?v=4" width="100px;" alt=""/><br /><sub><b>Max</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=AnticliMaxtic" title="Code">💻</a></td>
+  </tr>
+  <tr>
+    <td align="center"><a href="https://profiles.sussex.ac.uk/p281168-alex-dewar/publications"><img src="https://avatars.githubusercontent.com/u/23149834?v=4" width="100px;" alt=""/><br /><sub><b>Alex Dewar</b></sub></a><br /><a href="https://github.com/CLIUtils/CLI11/commits?author=alexdewar" title="Code">💻</a></td>
   </tr>
 </table>
 
@@ -972,7 +998,6 @@ This project was created by [Henry Schreiner](https://github.com/henryiii) and m
 <!-- prettier-ignore-end -->
 <!-- ALL-CONTRIBUTORS-LIST:END -->
 
-
 This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
 
 ## License
@@ -996,8 +1021,10 @@ CLI11 was developed at the [University of Cincinnati][] to support of the [GooFi
 [gitter-badge]: https://badges.gitter.im/CLI11gitter/Lobby.svg
 [gitter]: https://gitter.im/CLI11gitter/Lobby
 [license-badge]: https://img.shields.io/badge/License-BSD-blue.svg
-[conan-badge]: https://api.bintray.com/packages/cliutils/CLI11/CLI11%3Acliutils/images/download.svg
-[conan-link]: https://bintray.com/cliutils/CLI11/CLI11%3Acliutils/_latestVersion
+[conan-badge]: https://img.shields.io/badge/conan-io-blue
+[conan-link]: https://conan.io/center/cli11
+[conda-badge]: https://img.shields.io/conda/vn/conda-forge/cli11.svg
+[conda-link]: https://github.com/conda-forge/cli11-feedstock
 [github releases]: https://github.com/CLIUtils/CLI11/releases
 [github issues]: https://github.com/CLIUtils/CLI11/issues
 [github pull requests]: https://github.com/CLIUtils/CLI11/pulls
@@ -1028,16 +1055,18 @@ CLI11 was developed at the [University of Cincinnati][] to support of the [GooFi
 [version 1.0 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-10/
 [version 1.3 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-13/
 [version 1.6 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-16/
-[wandbox-badge]: https://img.shields.io/badge/try_1.9-online-blue.svg
-[wandbox-link]: https://wandbox.org/permlink/8SirASwhbFQZyDTW
+[version 2.0 post]: https://iscinumpy.gitlab.io/post/announcing-cli11-20/
+[wandbox-badge]: https://img.shields.io/badge/try_2.0-online-blue.svg
+[wandbox-link]: https://wandbox.org/permlink/650go2SXpfdvQ7ex
 [releases-badge]: https://img.shields.io/github/release/CLIUtils/CLI11.svg
 [cli11-po-compare]: https://iscinumpy.gitlab.io/post/comparing-cli11-and-boostpo/
 [diana slides]: https://indico.cern.ch/event/619465/contributions/2507949/attachments/1448567/2232649/20170424-diana-2.pdf
 [awesome c++]: https://github.com/fffaraz/awesome-cpp/blob/master/README.md#cli
 [cli]: https://codesynthesis.com/projects/cli/
 [single file libs]: https://github.com/nothings/single_file_libs/blob/master/README.md
-[codacy-badge]: https://api.codacy.com/project/badge/Grade/ac0df3aead2a4421b02070c3f324a0b9
-[codacy-link]: https://www.codacy.com/app/henryiii/CLI11?utm_source=github.com&utm_medium=referral&utm_content=CLIUtils/CLI11&utm_campaign=Badge_Grade
+[codacy-badge]: https://app.codacy.com/project/badge/Grade/2796b969c1b54321a02ad08affec0800
+[codacy-link]: https://www.codacy.com/gh/CLIUtils/CLI11/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=CLIUtils/CLI11&amp;utm_campaign=Badge_Grade
 [hunter]: https://docs.hunter.sh/en/latest/packages/pkg/CLI11.html
 [standard readme style]: https://github.com/RichardLitt/standard-readme
 [argparse]: https://github.com/p-ranav/argparse
+[toml]: https://toml.io
diff --git a/packages/CLI11/book/CMakeLists.txt b/packages/CLI11/book/CMakeLists.txt
index e99bde606..8934873a2 100644
--- a/packages/CLI11/book/CMakeLists.txt
+++ b/packages/CLI11/book/CMakeLists.txt
@@ -1,10 +1,7 @@
+set(book_sources README.md SUMMARY.md)
 
-set(
-    book_sources
-    README.md
-    SUMMARY.md
-)
-
-file(GLOB book_chapters RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} chapters/*.md)
+file(
+  GLOB book_chapters
+  RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+  chapters/*.md)
 add_custom_target(cli_book SOURCES ${book_sources} ${book_chapters})
-
diff --git a/packages/CLI11/book/README.md b/packages/CLI11/book/README.md
index 79a061fb1..593adbc96 100644
--- a/packages/CLI11/book/README.md
+++ b/packages/CLI11/book/README.md
@@ -1,8 +1,8 @@
 # CLI11: An introduction
 
-This gitbook is designed to provide an introduction to using the CLI11 library to write your own command line programs. The library is designed to be clean, intuitive, but powerful. There are no requirements beyond C++11 support (and even `<regex>` support not required). It works on Mac, Linux, and Windows, and has 100% test coverage on all three systems. You can simply drop in a single header file (`CLI11.hpp` available in [releases]) to use CLI11 in your own application. Other ways to integrate it into a build system are listed in the [README].
+This gitbook is designed to provide an introduction to using the CLI11 library to write your own command line programs. The library is designed to be clean, intuitive, but powerful. There are no requirements beyond C++11 support (and even `<regex>` support not required). It works on Mac, Linux, and Windows, and has 100% test coverage on all three systems. You can simply drop in a single header file (`CLI11.hpp` available in [releases][]) to use CLI11 in your own application. Other ways to integrate it into a build system are listed in the [README][].
 
-The library was inspired the Python libraries [Plumbum] and [Click], and incorporates many of their user friendly features. The library is extensively documented, with a [friendly introduction][README], this tutorial book, and more technical [API docs].
+The library was inspired the Python libraries [Plumbum][] and [Click][], and incorporates many of their user friendly features. The library is extensively documented, with a [friendly introduction][README], this tutorial book, and more technical [API docs][].
 
 > Feel free to contribute to [this documentation here][CLI11Tutorial] if something can be improved!
 
@@ -49,21 +49,17 @@ You can use any valid type; the above example could have used a `boost::file_sys
 
 You can use subcommands, as well. Subcommands support callback lambda functions when parsed, or they can be checked later. You can infinitely nest subcommands, and each is a full `App` instance, supporting everything listed above.
 
-Reading/producing `.ini` files for configuration is also supported, as is using environment variables as input. The base `App` can be subclassed and customized for use in a toolkit (like [GooFit]). All the standard shell idioms, like `--`, work as well.
+Reading/producing `.ini` files for configuration is also supported, as is using environment variables as input. The base `App` can be subclassed and customized for use in a toolkit (like [GooFit][]). All the standard shell idioms, like `--`, work as well.
 
-CLI11 was developed at the [University of Cincinnati] in support of the [GooFit] library under [NSF Award 1414736][NSF 1414736]. It was featured in a [DIANA/HEP] meeting at CERN. Please give it a try! Feedback is always welcome.
+CLI11 was developed at the [University of Cincinnati][] in support of the [GooFit][] library under [NSF Award 1414736][NSF 1414736]. It was featured in a [DIANA/HEP][] meeting at CERN. Please give it a try! Feedback is always welcome.
 
-[GooFit]: https://github.com/GooFit/GooFit
-[DIANA/HEP]: http://diana-hep.org
-[CLI11]: https://github.com/CLIUtils/CLI11
-[CLI11Tutorial]: https://cliutils.github.io/CLI11/book
+[goofit]: https://github.com/GooFit/GooFit
+[diana/hep]: https://diana-hep.org
+[cli11tutorial]: https://cliutils.github.io/CLI11/book
 [releases]: https://github.com/CLIUtils/CLI11/releases
-[API docs]: https://cliutils.github.io/CLI11
-[README]: https://github.com/CLIUtils/CLI11/blob/master/README.md
-[NSF 1414736]: https://nsf.gov/awardsearch/showAward?AWD_ID=1414736
-[University of Cincinnati]: http://www.uc.edu
-[Plumbum]: http://plumbum.readthedocs.io/en/latest/
-[Click]: https://click.palletsprojects.com/
-
-
-
+[api docs]: https://cliutils.github.io/CLI11
+[readme]: https://github.com/CLIUtils/CLI11/blob/master/README.md
+[nsf 1414736]: https://nsf.gov/awardsearch/showAward?AWD_ID=1414736
+[university of cincinnati]: https://www.uc.edu
+[plumbum]: https://plumbum.readthedocs.io/en/latest/
+[click]: https://click.palletsprojects.com
diff --git a/packages/CLI11/book/SUMMARY.md b/packages/CLI11/book/SUMMARY.md
index cdbc049f4..38261d52e 100644
--- a/packages/CLI11/book/SUMMARY.md
+++ b/packages/CLI11/book/SUMMARY.md
@@ -13,4 +13,3 @@
 * [Toolkits](/chapters/toolkits.md)
 * [Advanced topics](/chapters/advanced-topics.md)
 * [Internals](/chapters/internals.md)
-
diff --git a/packages/CLI11/book/chapters/advanced-topics.md b/packages/CLI11/book/chapters/advanced-topics.md
index 1a7ef5379..fee282165 100644
--- a/packages/CLI11/book/chapters/advanced-topics.md
+++ b/packages/CLI11/book/chapters/advanced-topics.md
@@ -1,6 +1,5 @@
 # Advanced topics
 
-
 ## Environment variables
 
 Environment variables can be used to fill in the value of an option:
@@ -9,6 +8,7 @@ Environment variables can be used to fill in the value of an option:
 std::string opt;
 app.add_option("--my_option", opt)->envname("MY_OPTION");
 ```
+
 If not given on the command line, the environment variable will be checked and read from if it exists. All the standard tools, like default and required, work as expected.
 If passed on the command line, this will ignore the environment variable.
 
@@ -55,7 +55,7 @@ add_option(CLI::App &app, std::string name, cx &variable, std::string descriptio
 
 Then you could use it like this:
 
-```
+```cpp
 std::complex<double> comp{0, 0};
 add_option(app, "-c,--complex", comp);
 ```
@@ -89,7 +89,6 @@ template <typename T> std::istringstream &operator>>(std::istringstream &in, boo
 
 This is an example of how to use the system only; if you are just looking for a way to activate `boost::optional` support on older compilers, you should define `CLI11_BOOST_OPTIONAL` before including a CLI11 file, you'll get the `boost::optional` support.
 
-
 ## Custom converters and type names: std::chrono example
 
 An example of adding a custom converter and typename for `std::chrono` follows:
@@ -97,40 +96,40 @@ An example of adding a custom converter and typename for `std::chrono` follows:
 ```cpp
 namespace CLI
 {
-	template <typename T, typename R>
-	std::istringstream &operator>>(std::istringstream &in, std::chrono::duration<T,R> &val)
-	{
-		T v;
-		in >> v;
-		val = std::chrono::duration<T,R>(v);
-		return in;
-	}
-
-	template <typename T, typename R>
-	std::stringstream &operator<<(std::stringstream &in, std::chrono::duration<T,R> &val)
-	{
-		in << val.count();
-		return in;
-	}
+    template <typename T, typename R>
+    std::istringstream &operator>>(std::istringstream &in, std::chrono::duration<T,R> &val)
+    {
+        T v;
+        in >> v;
+        val = std::chrono::duration<T,R>(v);
+        return in;
+    }
+
+    template <typename T, typename R>
+    std::stringstream &operator<<(std::stringstream &in, std::chrono::duration<T,R> &val)
+    {
+        in << val.count();
+        return in;
+    }
  }
 
 #include <CLI/CLI.hpp>
 
 namespace CLI
 {
-	namespace detail
-	{
-		template <>
-		constexpr const char *type_name<std::chrono::hours>()
-		{
-			return "TIME [H]";
-		}
-
-		template <>
-		constexpr const char *type_name<std::chrono::minutes>()
-		{
-			return "TIME [MIN]";
-		}
+    namespace detail
+    {
+        template <>
+        constexpr const char *type_name<std::chrono::hours>()
+        {
+            return "TIME [H]";
+        }
+
+        template <>
+        constexpr const char *type_name<std::chrono::minutes>()
+        {
+            return "TIME [MIN]";
+        }
         }
 }
 ```
diff --git a/packages/CLI11/book/chapters/an-advanced-example.md b/packages/CLI11/book/chapters/an-advanced-example.md
index 2b20dde15..82fe7b71c 100644
--- a/packages/CLI11/book/chapters/an-advanced-example.md
+++ b/packages/CLI11/book/chapters/an-advanced-example.md
@@ -1,7 +1,5 @@
 # Making a git clone
 
-
-
 Let's try our hand at a little `git` clone, called `geet`. It will just print it's intent, rather than running actual code, since it's just a demonstration. Let's start by adding an app and requiring 1 subcommand to run:
 
 [include:"Intro"](../code/geet.cpp)
diff --git a/packages/CLI11/book/chapters/basics.md b/packages/CLI11/book/chapters/basics.md
index aa52cffb7..0c55ec4f4 100644
--- a/packages/CLI11/book/chapters/basics.md
+++ b/packages/CLI11/book/chapters/basics.md
@@ -24,4 +24,3 @@ Usage: ./a.out [OPTIONS]
 Options:
   -h,--help                   Print this help message and exit
 ```
-
diff --git a/packages/CLI11/book/chapters/config.md b/packages/CLI11/book/chapters/config.md
index 219c3d9dc..df004ce75 100644
--- a/packages/CLI11/book/chapters/config.md
+++ b/packages/CLI11/book/chapters/config.md
@@ -5,36 +5,48 @@
 You can tell your app to allow configure files with `set_config("--config")`. There are arguments: the first is the option name. If empty, it will clear the config flag. The second item is the default file name. If that is specified, the config will try to read that file. The third item is the help string, with a reasonable default, and the final argument is a boolean (default: false) that indicates that the configuration file is required and an error will be thrown if the file is not found and this is set to true.
 
 ### Extra fields
+
 Sometimes configuration files are used for multiple purposes so CLI11 allows options on how to deal with extra fields
 
 ```cpp
 app.allow_config_extras(true);
 ```
+
 will allow capture the extras in the extras field of the app. (NOTE:  This also sets the `allow_extras` in the app to true)
 
 ```cpp
 app.allow_config_extras(false);
 ```
+
 will generate an error if there are any extra fields
+for slightly finer control there is a scoped enumeration of the modes or
 
-for slightly finer control there is a scoped enumeration of the modes
-or
 ```cpp
 app.allow_config_extras(CLI::config_extras_mode::ignore);
 ```
+
 will completely ignore extra parameters in the config file.   This mode is the default.
 
 ```cpp
 app.allow_config_extras(CLI::config_extras_mode::capture);
 ```
+
 will store the unrecognized options in the app extras fields. This option is the closest equivalent to `app.allow_config_extras(true);` with the exception that it does not also set the `allow_extras` flag so using this option without also setting `allow_extras(true)` will generate an error which may or may not be the desired behavior.
 
 ```cpp
 app.allow_config_extras(CLI::config_extras_mode::error);
 ```
+
 is equivalent to `app.allow_config_extras(false);`
 
+```cpp
+app.allow_config_extras(CLI::config_extras_mode::ignore_all);
+```
+
+will completely ignore any mismatches, extras, or other issues with the config file
+
 ### Getting the used configuration file name
+
 If it is needed to get the configuration file name used this can be obtained via
 `app.get_config_ptr()->as<std::string>()`  or
 `app["--config"]->as<std::string>()` assuming `--config` was the configuration option name.
@@ -93,7 +105,6 @@ Where X is some positive integer and will allow up to `X` configuration files to
 To print a configuration file from the passed arguments, use `.config_to_str(default_also=false, write_description=false)`, where `default_also` will also show any defaulted arguments, and `write_description` will include option descriptions and the App description
 
 ```cpp
-
  CLI::App app;
  app.add_option(...);
     // several other options
@@ -105,7 +116,6 @@ To print a configuration file from the passed arguments, use `.config_to_str(def
 if a prefix is needed to print before the options, for example to print a config for just a subcommand, the config formatter can be obtained directly.
 
 ```cpp
-
   auto fmtr=app.get_config_formatter();
   //std::string to_config(const App *app, bool default_also, bool write_description, std::string prefix)
   fmtr->to_config(&app,true,true,"sub.");
@@ -113,7 +123,9 @@ if a prefix is needed to print before the options, for example to print a config
 ```
 
 ### Customization of configure file output
-The default config parser/generator has some customization points that allow variations on the TOML format.  The default formatter has a base configuration that matches the TOML format.  It defines 5 characters that define how different aspects of the configuration are handled
+
+The default config parser/generator has some customization points that allow variations on the TOML format.  The default formatter has a base configuration that matches the TOML format.  It defines 5 characters that define how different aspects of the configuration are handled.  You must use `get_config_formatter_base()` to have access to these fields
+
 ```cpp
 /// the character used for comments
 char commentChar = '#';
@@ -125,16 +137,33 @@ char arrayEnd = ']';
 char arraySeparator = ',';
 /// the character used separate the name from the value
 char valueDelimiter = '=';
+/// the character to use around strings
+char stringQuote = '"';
+/// the character to use around single characters
+char characterQuote = '\'';
+/// the maximum number of layers to allow
+uint8_t maximumLayers{255};
+/// the separator used to separator parent layers
+char parentSeparatorChar{'.'};
+/// Specify the configuration index to use for arrayed sections
+uint16_t configIndex{0};
+/// Specify the configuration section that should be used
+std::string configSection;
 ```
 
 These can be modified via setter functions
 
-- ` ConfigBase *comment(char cchar)` Specify the character to start a comment block
--  `ConfigBase *arrayBounds(char aStart, char aEnd)`  Specify the start and end characters for an array
--  `ConfigBase *arrayDelimiter(char aSep)` Specify the delimiter character for an array
--  `ConfigBase *valueSeparator(char vSep)` Specify the delimiter between a name and value
+* `ConfigBase *comment(char cchar)`: Specify the character to start a comment block
+* `ConfigBase *arrayBounds(char aStart, char aEnd)`: Specify the start and end characters for an array
+* `ConfigBase *arrayDelimiter(char aSep)`: Specify the delimiter character for an array
+* `ConfigBase *valueSeparator(char vSep)`: Specify the delimiter between a name and value
+* `ConfigBase *quoteCharacter(char qString, char qChar)` :specify the characters to use around strings and single characters
+* `ConfigBase *maxLayers(uint8_t layers)` : specify the maximum number of parent layers to process. This is useful to limit processing for larger config files
+* `ConfigBase *parentSeparator(char sep)` : specify the character to separate parent layers from options
+* `ConfigBase *section(const std::string &sectionName)` : specify the section name to use to get the option values, only this section will be processed
+* `ConfigBase *index(uint16_t sectionIndex)` : specify an index section to use for processing if multiple TOML sections of the same name are present `[[section]]`
 
-For example to specify reading a configure file that used `:` to separate name and values
+For example, to specify reading a configure file that used `:` to separate name and values:
 
 ```cpp
 auto config_base=app.get_config_formatter_base();
@@ -142,9 +171,11 @@ config_base->valueSeparator(':');
 ```
 
 The default configuration file will read INI files, but will write out files in the TOML format.  To specify outputting INI formatted files use
+
 ```cpp
 app.config_formatter(std::make_shared<CLI::ConfigINI>());
 ```
+
 which makes use of a predefined modification of the ConfigBase class which TOML also uses. If a custom formatter is used that is not inheriting from the from ConfigBase class `get_config_formatter_base() will return a nullptr if RTTI is on (usually the default), or garbage if RTTI is off, so some care must be exercised in its use with custom configurations.
 
 ## Custom formats
@@ -166,16 +197,39 @@ app.config_formatter(std::make_shared<NewConfig>());
 
 See [`examples/json.cpp`](https://github.com/CLIUtils/CLI11/blob/master/examples/json.cpp) for a complete JSON config example.
 
+### Trivial JSON configuration example
+
+```JSON
+{
+   "test": 56,
+   "testb": "test",
+   "flag": true
+}
+```
+
+The parser can handle these structures with only a minor tweak
+
+```cpp
+app.get_config_formatter_base()->valueSeparator(':');
+```
+
+The open and close brackets must be on a separate line and the comma gets interpreted as an array separator but since no values are after the comma they get ignored as well.  This will not support multiple layers or sections or any other moderately complex JSON, but can work if the input file is simple.
 
 ## Triggering Subcommands
-Configuration files can be used to trigger subcommands if a subcommand is set to configure.  By default configuration file just set the default values of a subcommand.  But if the `configure()` option is set on a subcommand then the if the subcommand is utilized via a `[subname]` block in the configuration file it will act as if it were called from the command line.  Subsubcommands can be triggered via [subname.subsubname].  Using the `[[subname]]` will be as if the subcommand were triggered multiple times from the command line.  This functionality can allow the configuration file to act as a scripting file.
+
+Configuration files can be used to trigger subcommands if a subcommand is set to configure.  By default configuration file just set the default values of a subcommand.  But if the `configure()` option is set on a subcommand then the if the subcommand is utilized via a `[subname]` block in the configuration file it will act as if it were called from the command line.  Subsubcommands can be triggered via `[subname.subsubname]`.  Using the `[[subname]]` will be as if the subcommand were triggered multiple times from the command line.  This functionality can allow the configuration file to act as a scripting file.
 
 For custom configuration files this behavior can be triggered by specifying the parent subcommands in the structure and `++` as the name to open a new subcommand scope and `--` to close it.  These names trigger the different callbacks of configurable subcommands.
 
+## Stream parsing
+
+In addition to the regular parse functions a `parse_from_stream(std::istream &input)` is available to directly parse a stream operator.  For example to process some arguments in an already open file stream.  The stream is fed directly in the config parser so bypasses the normal command line parsing.
+
 ## Implementation Notes
-The config file input works with any form of the option given:  Long, short, positional, or the environment variable name.  When generating a config file it will create a name in following priority.
 
-1.   First long name
-1.   Positional name
-1.   First short name
-1.   Environment name
+The config file input works with any form of the option given:  Long, short, positional, or the environment variable name.  When generating a config file it will create an option name in following priority.
+
+1. First long name
+2. Positional name
+3. First short name
+4. Environment name
diff --git a/packages/CLI11/book/chapters/flags.md b/packages/CLI11/book/chapters/flags.md
index d4f88fb68..aa920fe85 100644
--- a/packages/CLI11/book/chapters/flags.md
+++ b/packages/CLI11/book/chapters/flags.md
@@ -11,8 +11,7 @@ bool my_flag{false};
 app.add_flag("-f", my_flag, "Optional description");
 ```
 
-This will bind the flag `-f` to the boolean `my_flag`. After the parsing step, `my_flag` will be `false` if the flag was not found on the command line, or `true` if it was. By default, it will be allowed any number of times, but if you explicitly[^1] request `->take_last(false)`, it will only be allowed once; passing something like `./my_app -f -f` or `./my_app -ff` will throw a `ParseError` with a nice help description.
-
+This will bind the flag `-f` to the boolean `my_flag`. After the parsing step, `my_flag` will be `false` if the flag was not found on the command line, or `true` if it was. By default, it will be allowed any number of times, but if you explicitly\[^1\] request `->take_last(false)`, it will only be allowed once; passing something like `./my_app -f -f` or `./my_app -ff` will throw a `ParseError` with a nice help description. A flag name may start with any character except ('-', ' ', '\n', and '!'). For long flags, after the first character all characters are allowed except ('=',':','{',' ', '\n').  Names are given as a comma separated string, with the dash or dashes. An flag can have as many names as you want, and afterward, using `count`, you can use any of the names, with dashes as needed.
 
 ## Integer flags
 
@@ -65,12 +64,11 @@ After parsing, you can use `my_flag->count()` to count the number of times this
 
 If you want to define a callback that runs when you make a flag, you can use `add_flag_function` (C++11 or newer) or `add_flag` (C++14 or newer only) to add a callback function. The function should have the signature `void(std::size_t)`. This could be useful for a version printout, etc.
 
-```
+```cpp
 auto callback = [](int count){std::cout << "This was called " << count << " times";};
 app.add_flag_function("-c", callback, "Optional description");
 ```
 
-
 ## Aliases
 
 The name string, the first item of every `add_` method, can contain as many short and long names as you want, separated by commas. For example, `"-a,--alpha,-b,--beta"` would allow any of those to be recognized on the command line. If you use the same name twice, or if you use the same name in multiple flags, CLI11 will immediately throw a `CLI::ConstructionError` describing your problem (it will not wait until the parsing step).
@@ -122,5 +120,4 @@ Flag int: 3
 Flag plain: 1
 ```
 
-
-[^1] It will not inherit this from the parent defaults, since this is often useful even if you don't want all options to allow multiple passed options.
+\[^1\]: It will not inherit this from the parent defaults, since this is often useful even if you don't want all options to allow multiple passed options.
diff --git a/packages/CLI11/book/chapters/formatting.md b/packages/CLI11/book/chapters/formatting.md
index 66dd228da..f9cd36fa4 100644
--- a/packages/CLI11/book/chapters/formatting.md
+++ b/packages/CLI11/book/chapters/formatting.md
@@ -4,13 +4,12 @@
 New in CLI11 1.6
 {% endhint %}
 
-##  Customizing an existing formatter
+## Customizing an existing formatter
 
 In CLI11, you can control the output of the help printout in full or in part. The default formatter was written in such a way as to be customizable. You can use `app.get_formatter()` to get the current formatter. The formatter you set will be inherited by subcommands that are created after you set the formatter.
 
 There are several configuration options that you can set:
 
-
 | Set method | Description | Availability |
 |------------|-------------|--------------|
 | `column_width(width)` | The width of the columns | Both |
@@ -41,7 +40,7 @@ Look at the class definitions in `FormatterFwd.hpp` or the method definitions in
 
 This is a normal printout, with `<>` indicating the methods used to produce each line.
 
-```
+```text
 <make_description(app)>
 <make_usage(app)>
 <make_positionals(app)>
@@ -60,7 +59,7 @@ This is a normal printout, with `<>` indicating the methods used to produce each
 
 The `make_groups` print the group name then call `make_option(o)` on the options listed in that group. The normal printout for an option looks like this:
 
-```
+```text
         make_option_opts(o)
             ┌───┴────┐
  -n,--name  (REQUIRED)      This is a description
@@ -72,7 +71,3 @@ Notes:
 
 * `*1`: This signature depends on whether the call is from a positional or optional.
 * `o` is opt pointer, `p` is true if positional.
-
-
-
-
diff --git a/packages/CLI11/book/chapters/internals.md b/packages/CLI11/book/chapters/internals.md
index 17bc54aa3..1551c79c6 100644
--- a/packages/CLI11/book/chapters/internals.md
+++ b/packages/CLI11/book/chapters/internals.md
@@ -41,5 +41,3 @@ The `_process` procedure runs the following steps; each step is recursive and co
 ## Exceptions
 
 The library immediately returns a C++ exception when it detects a problem, such as an incorrect construction or a malformed command line.
-
-
diff --git a/packages/CLI11/book/chapters/options.md b/packages/CLI11/book/chapters/options.md
index 04bfd0bbd..8b1daa0ff 100644
--- a/packages/CLI11/book/chapters/options.md
+++ b/packages/CLI11/book/chapters/options.md
@@ -1,37 +1,37 @@
 # Options
 
 ## Simple options
-The most versatile addition to a command line program is a option. This is like a flag, but it takes an argument. CLI11 handles all the details for many types of options for you, based on their type. To add an option:
 
+The most versatile addition to a command line program is a option. This is like a flag, but it takes an argument. CLI11 handles all the details for many types of options for you, based on their type. To add an option:
 
 ```cpp
 int int_option{0};
 app.add_option("-i", int_option, "Optional description");
 ```
 
-This will bind the option `-i` to the integer `int_option`. On the command line, a single value that can be converted to an integer will be expected. Non-integer results will fail. If that option is not given, CLI11 will not touch the initial value. This allows you to set up defaults by simply setting your value beforehand. If you want CLI11 to display your default value, you can add the optional final argument `true` when you add the option.
+This will bind the option `-i` to the integer `int_option`. On the command line, a single value that can be converted to an integer will be expected. Non-integer results will fail. If that option is not given, CLI11 will not touch the initial value. This allows you to set up defaults by simply setting your value beforehand. If you want CLI11 to display your default value, you can add `->capture_default_str()` after the option.
 
 ```cpp
 int int_option{0};
-app.add_option("-i", int_option, "Optional description", true);
+app.add_option("-i", int_option, "Optional description")->capture_default_str();
 ```
 
 You can use any C++ int-like type, not just `int`. CLI11 understands the following categories of types:
 
 | Type        | CLI11 |
 |-------------|-------|
-| number like    | Integers, floats, bools, or any type that can be constructed from an integer or floating point number |
+| number like    | Integers, floats, bools, or any type that can be constructed from an integer or floating point number.  Accepts common numerical strings like `0xFF` as well as octal, and decimal |
 | string-like | std\::string, or anything that can be constructed from or assigned a std\::string |
 | char | For a single char, single string values are accepted, otherwise longer strings are treated as integral values and a conversion is attempted |
 | complex-number | std::complex or any type which has a real(), and imag() operations available, will allow 1 or 2 string definitions like "1+2j" or two arguments "1","2" |
 | enumeration | any enum or enum class type is supported through conversion from the underlying type(typically int, though it can be specified otherwise) |
 | container-like | a container(like vector) of any available types including other containers |
-| wrapper | any other object with a `value_type` static definition where the type specified by `value_type` is one of type in this list |
+| wrapper | any other object with a `value_type` static definition where the type specified by `value_type` is one of the type in this list, including `std::atomic<>` |
 | tuple | a tuple, pair, or array, or other type with a tuple size and tuple_type operations defined and the members being a type contained in this list |
 | function | A function that takes an array of strings and returns a string that describes the conversion failure or empty for success. May be the empty function. (`{}`) |
 | streamable | any other type with a `<<` operator will also work |
 
-By default, CLI11 will assume that an option is optional, and one value is expected if you do not use a vector. You can change this on a specific option using option modifiers.
+By default, CLI11 will assume that an option is optional, and one value is expected if you do not use a vector. You can change this on a specific option using option modifiers.  An option name may start with any character except ('-', ' ', '\n', and '!'). For long options, after the first character all characters are allowed except ('=',':','{',' ', '\n'). Names are given as a comma separated string, with the dash or dashes. An option can have as many names as you want, and afterward, using `count`, you can use any of the names, with dashes as needed, to count the options. One of the names is allowed to be given without proceeding dash(es); if present the option is a positional option, and that name will be used on the help line for its positional form.
 
 ## Positional options and aliases
 
@@ -72,29 +72,38 @@ Vectors will be replaced by the parsed content if the option is given on the com
 
 A definition of a container for purposes of CLI11 is a type with a `end()`, `insert(...)`, `clear()` and `value_type` definitions.  This includes `vector`, `set`, `deque`, `list`, `forward_iist`, `map`, `unordered_map` and a few others from the standard library, and many other containers from the boost library.
 
-### containers of containers
+### Containers of containers
+
 Containers of containers are also supported.
+
 ```cpp
 std::vector<std::vector<int>> int_vec;
 app.add_option("--vec", int_vec, "My vector of vectors option");
 ```
+
 CLI11 inserts a separator sequence at the start of each argument call to separate the vectors.  So unless the separators are injected as part of the command line each call of the option on the command line will result in a separate element of the outer vector.  This can be manually controlled via `inject_separator(true|false)` but in nearly all cases this should be left to the defaults.  To insert of a separator from the command line add a `%%` where the separation should occur.
-```
+
+```bash
 cmd --vec_of_vec 1 2 3 4 %% 1 2
 ```
+
 would then result in a container of size 2 with the first element containing 4 values and the second 2.
 
 This separator is also the only way to get values into something like
+
 ```cpp
 std::pair<std::vector<int>,std::vector<int>> two_vecs;
 app.add_option("--vec", two_vecs, "pair of vectors");
 ```
+
 without calling the argument twice.
 
 Further levels of nesting containers should compile but intermediate layers will only have a single element in the container, so is probably not that useful.
 
 ### Nested types
-Types can be nested For example
+
+Types can be nested. For example:
+
 ```cpp
 std::map<int, std::pair<int,std::string>> map;
 app.add_option("--dict", map, "map of pairs");
@@ -106,6 +115,7 @@ will require 3 arguments for each invocation, and multiple sets of 3 arguments c
 std::map<int, std::pair<int,std::vector<std::string>>> map;
 app.add_option("--dict", map, "map of pairs");
 ```
+
 will result in a requirement for 2 integers on each invocation and absorb an unlimited number of strings including 0.
 
 ## Option modifiers
@@ -119,8 +129,8 @@ When you call `add_option`, you get a pointer to the added option. You can use t
 | `->expected(Nmin,Nmax)` | Take between `Nmin` and `Nmax` values. |
 | `->type_size(N)` | specify that each block of values would consist of N elements |
 | `->type_size(Nmin,Nmax)` | specify that each block of values would consist of between Nmin and Nmax elements |
-| `->needs(opt)` | This option requires another option to also be present, opt is an `Option` pointer. |
-| `->excludes(opt)` | This option cannot be given with `opt` present, opt is an `Option` pointer. |
+| `->needs(opt)` | This option requires another option to also be present, opt is an `Option` pointer or a string with the name of the option.  Can be removed with `->remove_needs(opt)` |
+| `->excludes(opt)` | This option cannot be given with `opt` present, opt is an `Option` pointer or a string with the name of the option.  Can be removed with `->remove_excludes(opt)` |
 | `->envname(name)` | Gets the value from the environment if present and not passed on the command line. |
 | `->group(name)` | The help group to put the option in. No effect for positional options. Defaults to `"Options"`. `"Hidden"` will not show up in the help print. |
 | `->description(string)` | Set/change the description |
@@ -139,8 +149,14 @@ When you call `add_option`, you get a pointer to the added option. You can use t
 | `->transform(Validator)` | Run a transforming validator on each value passed. See [Validators](./validators.md) for more info |
 | `->each(void(std::string))` | Run a function on each parsed value, *in order*. |
 | `->default_str(string)` | set a default string for use in the help and as a default value if no arguments are passed and a value is requested |
-| `->default_function(string())` | Advanced: Change the function that `capture_default_str()` uses. |
+| `->default_function(std::string())` | Advanced: Change the function that `capture_default_str()` uses. |
 | `->default_val(value)` | Generate the default string from a value and validate that the value is also valid.  For options that assign directly to a value type the value in that type is also updated.  Value must be convertible to a string(one of known types or have a stream operator). |
+| `->capture_default_str()` | Store the current value attached and display it in the help string. |
+| `->always_capture_default()` | Always run `capture_default_str()` when creating new options. Only useful on an App's `option_defaults`. |
+| `->run_callback_for_default()` | Force the option callback to be executed or the variable set when the `default_val` is used.  |
+| `->force_callback()` | Force the option callback to be executed regardless of whether the option was used or not.  Will use the default_str if available, if no default is given the callback will be executed with an empty string as an argument, which will translate to a default initialized value, which can be compiler dependent |
+|`->trigger_on_parse()` | Have the option callback be triggered when the value is parsed vs. at the end of all parsing, the option callback can potentially be executed multiple times.  Generally only useful if you have a user defined callback or validation check. Or potentially if a vector input is given multiple times as it will clear the results when a repeat option is given via command line.  It will trigger the callbacks once per option call on the command line|
+| `->option_text(string)` | Sets the text between the option name and description. |
 
 The `->check(...)` and `->transform(...)` modifiers can also take a callback function of the form `bool function(std::string)` that runs on every value that the option receives, and returns a value that tells CLI11 whether the check passed or failed.
 
@@ -161,19 +177,19 @@ if(* opt)
 
 One of CLI11's systems to allow customizability without high levels of verbosity is the inheritance system. You can set default values on the parent `App`, and all options and subcommands created from it remember the default values at the point of creation. The default value for Options, specifically, are accessible through the `option_defaults()` method. There are a number of settings that can be set and inherited:
 
-*   `group`: The group name starts as "Options"
-*   `required`: If the option must be given. Defaults to `false`. Is ignored for flags.
-*   `multi_option_policy`: What to do if several copies of an option are passed and one value is expected. Defaults to `CLI::MultiOptionPolicy::Throw`. This is also used for bool flags, but they always are created with the value `CLI::MultiOptionPolicy::TakeLast` regardless of the default, so that multiple bool flags does not cause an error. But you can override that flag by flag.
-*   `ignore_case`: Allow any mixture of cases for the option or flag name
-*   `ignore_underscore`: Allow any number of underscores in the option or flag name
-*   `configurable`:  Specify whether an option can be configured through a config file
-*   `disable_flag_override`:  do not allow flag values to be overridden on the command line
-*   `always_capture_default`:  specify that the default values should be automatically captured.
-*   `delimiter`:  A delimiter to use for capturing multiple values in a single command line string (e.g. --flag="flag,-flag2,flag3")
+* `group`: The group name starts as "Options"
+* `required`: If the option must be given. Defaults to `false`. Is ignored for flags.
+* `multi_option_policy`: What to do if several copies of an option are passed and one value is expected. Defaults to `CLI::MultiOptionPolicy::Throw`. This is also used for bool flags, but they always are created with the value `CLI::MultiOptionPolicy::TakeLast` regardless of the default, so that multiple bool flags does not cause an error. But you can override that flag by flag.
+* `ignore_case`: Allow any mixture of cases for the option or flag name
+* `ignore_underscore`: Allow any number of underscores in the option or flag name
+* `configurable`:  Specify whether an option can be configured through a config file
+* `disable_flag_override`:  do not allow flag values to be overridden on the command line
+* `always_capture_default`:  specify that the default values should be automatically captured.
+* `delimiter`:  A delimiter to use for capturing multiple values in a single command line string (e.g. --flag="flag,-flag2,flag3")
 
 An example of usage:
 
-```
+```cpp
 app.option_defaults()->ignore_case()->group("Required");
 
 app.add_flag("--CaSeLeSs");
@@ -182,17 +198,16 @@ app.get_group() // is "Required"
 
 Groups are mostly for visual organization, but an empty string for a group name will hide the option.
 
-
 ### Windows style options
 
 You can also set the app setting `app->allow_windows_style_options()` to allow windows style options to also be recognized on the command line:
 
-*   `/a` (flag)
-*   `/f filename` (option)
-*   `/long` (long flag)
-*   `/file filename` (space)
-*   `/file:filename` (colon)
-*   `/long_flag:false` (long flag with : to override the default value)
+* `/a` (flag)
+* `/f filename` (option)
+* `/long` (long flag)
+* `/file filename` (space)
+* `/file:filename` (colon)
+* `/long_flag:false` (long flag with : to override the default value)
 
 Windows style options do not allow combining short options or values not separated from the short option like with `-` options. You still specify option names in the same manner as on Linux with single and double dashes when you use the `add_*` functions, and the Linux style on the command line will still work. If a long and a short option share the same name, the option will match on the first one defined.
 
@@ -200,15 +215,19 @@ Windows style options do not allow combining short options or values not separat
 
 How an option and its arguments are parsed depends on a set of controls that are part of the option structure.  In most circumstances these controls are set automatically based on the type or function used to create the option and the type the arguments are parsed into.  The variables define the size of the underlying type (essentially how many strings make up the type), the expected size (how many groups are expected) and a flag indicating if multiple groups are allowed with a single option.  And these interact with the `multi_option_policy` when it comes time to parse.
 
-### examples
-How options manage this is best illustrated through some examples
+### Examples
+
+How options manage this is best illustrated through some examples.
+
 ```cpp
 std::string val;
 app.add_option("--opt",val,"description");
 ```
+
 creates an option that assigns a value to a `std::string`  When this option is constructed it sets a type_size min and max of 1.  Meaning that the assignment uses a single string.  The Expected size is also set to 1 by default, and `allow_extra_args` is set to false. meaning that each time this option is called 1 argument is expected.  This would also be the case if val were a `double`, `int` or any other single argument types.
 
 now for example
+
 ```cpp
 std::pair<int, std::string> val;
 app.add_option("--opt",val,"description");
@@ -227,6 +246,7 @@ detects a type size of 1, since the underlying element type is a single string,
 std::vector<std::tuple<int, double, std::string>> val;
 app.add_option("--opt",val,"description");
 ```
+
 gets into the complicated cases where the type size is now 3.  and the expected max is set to a large number and `allow_extra_args` is set to true.  In this case at least 3 arguments are required to follow the option,  and subsequent groups must come in groups of three, otherwise an error will result.
 
 ```cpp
@@ -243,11 +263,11 @@ app.add_option("--opt",val,"description");
 
 triggers the complex number type which has a min of 1 and max of 2,  so 1 or 2 strings can be passed.  Complex number conversion supports arguments of the form "1+2j" or "1","2", or "1" "2i".  The imaginary number symbols `i` and `j` are interchangeable in this context.
 
-
 ```cpp
 std::vector<std::vector<int>> val;
 app.add_option("--opt",val,"description");
 ```
+
 has a type size of 1 to (1<<30).
 
 ### Customization
@@ -259,11 +279,13 @@ std::string val;
 auto opt=app.add_flag("--opt{vvv}",val,"description");
 opt->expected(0,1);
 ```
+
 will create a hybrid option, that can exist on its own in which case the value "vvv" is used or if a value is given that value will be used.
 
-There are some additional options that can be specified to modify an option for specific cases
--   `->run_callback_for_default()` will specify that the callback should be executed when a default_val is set. This is set automatically when appropriate though it can be turned on or off and any user specified callback for an option will be executed when the default value for an option is set.
+There are some additional options that can be specified to modify an option for specific cases:
+
+* `->run_callback_for_default()` will specify that the callback should be executed when a default_val is set. This is set automatically when appropriate though it can be turned on or off and any user specified callback for an option will be executed when the default value for an option is set.
 
 ## Unusual circumstances
-There are a few cases where some things break down in the type system managing options and definitions.  Using the `add_option` method defines a lambda function to extract a default value if required.  In most cases this either straightforward or a failure is detected automatically and handled.  But in a few cases a streaming template is available that several layers down may not actually be defined.  The conditions in CLI11 cannot detect this circumstance automatically and will result in compile error.  One specific known case is `boost::optional` if the boost optional_io header is included.  This header defines a template for all boost optional values even if they do no actually have a streaming operator.  For example `boost::optional<std::vector>` does not have a streaming operator but one is detected since it is part of a template.  For these cases a secondary method `app->add_option_no_stream(...)` is provided that bypasses this operation completely and should compile in these cases.
 
+There are a few cases where some things break down in the type system managing options and definitions.  Using the `add_option` method defines a lambda function to extract a default value if required.  In most cases this is either straightforward or a failure is detected automatically and handled.  But in a few cases a streaming template is available that several layers down may not actually be defined.  This results in CLI11 not being able to detect this circumstance automatically and will result in compile error.  One specific known case is `boost::optional` if the boost optional_io header is included.  This header defines a template for all boost optional values even if they do not actually have a streaming operator.  For example `boost::optional<std::vector>` does not have a streaming operator but one is detected since it is part of a template.  For these cases a secondary method `app->add_option_no_stream(...)` is provided that bypasses this operation completely and should compile in these cases.
diff --git a/packages/CLI11/book/chapters/subcommands.md b/packages/CLI11/book/chapters/subcommands.md
index 230cca880..585f91c72 100644
--- a/packages/CLI11/book/chapters/subcommands.md
+++ b/packages/CLI11/book/chapters/subcommands.md
@@ -7,7 +7,6 @@ C++ application, though the system git uses to extend the main command by callin
 in separate executables is supported too; that's called "Prefix commands" and is included at the
 end of this chapter.
 
-
 ## The parent App
 
 We'll start by discussing the parent `App`. You've already used it quite a bit, to create
@@ -18,7 +17,6 @@ You can replace the default help print when a `ParseError` is thrown with `app.s
 The default is `CLI:::FailureMessage::simple`, and you can easily define a new one. Just make a (lambda) function that takes an App pointer
 and a reference to an error code (even if you don't use them), and returns a string.
 
-
 ## Adding a subcommand
 
 Subcommands can be added just like an option:
@@ -55,6 +53,7 @@ Each App has controls to set the number of subcommands you expect. This is contr
 ```cpp
 app.require_subcommand(/* min */ 0, /* max */ 1);
 ```
+
 If you set the max to 0, CLI11 will allow an unlimited number of subcommands. After the (non-unlimited) maximum
 is reached, CLI11 will stop trying to match subcommands. So the if you pass "`one two`" to a command, and both `one`
 and `two` are subcommands, it will depend on the maximum number as to whether the "`two`" is a subcommand or an argument to the
diff --git a/packages/CLI11/book/chapters/toolkits.md b/packages/CLI11/book/chapters/toolkits.md
index 3b8e93a1f..4c276387a 100644
--- a/packages/CLI11/book/chapters/toolkits.md
+++ b/packages/CLI11/book/chapters/toolkits.md
@@ -2,7 +2,7 @@
 
 CLI11 was designed to be integrate into a toolkit, providing a native experience for users. This was used in GooFit to provide `GooFit::Application`, an class designed to make ROOT users feel at home.
 
-# Custom namespace
+## Custom namespace
 
 If you want to provide CLI11 in a custom namespace, you'll want to at least put `using CLI::App` in your namespace. You can also include Option, some errors, and validators. You can also put `using namespace CLI` inside your namespace to import everything.
 
@@ -17,14 +17,12 @@ You may also want to make your own copy of the `CLI11_PARSE` macro. Something li
      }
 ```
 
-
-# Subclassing App
+## Subclassing App
 
 If you subclass `App`, you'll just need to do a few things. You'll need a constructor; calling the base `App` constructor is a good idea, but not necessary (it just sets a description and adds a help flag.
 
 You can call anything you would like to configure in the constructor, like `option_defaults()->take_last()` or `fallthrough()`, and it will be set on all user instances. You can add flags and options, as well.
 
-
-# Virtual functions provided
+## Virtual functions provided
 
 You are given a few virtual functions that you can change (only on the main App). `pre_callback` runs right before the callbacks run, letting you print out custom messages at the top of your app.
diff --git a/packages/CLI11/book/chapters/validators.md b/packages/CLI11/book/chapters/validators.md
index 6266a9cae..06e42c80a 100644
--- a/packages/CLI11/book/chapters/validators.md
+++ b/packages/CLI11/book/chapters/validators.md
@@ -49,7 +49,6 @@ The built-in validators for CLI11 are:
 | `NonexistentPath`   | Check for an non-existing path |
 | `Range(min=0, max)` |  Produce a range (factory). Min and max are inclusive. |
 
-
 And, the protected members that you can set when you make your own are:
 
 | Type | Member | Description |
@@ -60,5 +59,3 @@ And, the protected members that you can set when you make your own are:
 | `int` (`-1`) | `application_index_` | The element this validator applies to (-1 for all) |
 | `bool` (`true`) | `active_` | This can be disabled |
 | `bool` (`false`) | `non_modifying_` | Specify that this is a Validator instead of a Transformer |
-
-
diff --git a/packages/CLI11/book/code/CMakeLists.txt b/packages/CLI11/book/code/CMakeLists.txt
index b91a9c7bb..987d53c49 100644
--- a/packages/CLI11/book/code/CMakeLists.txt
+++ b/packages/CLI11/book/code/CMakeLists.txt
@@ -12,27 +12,21 @@ enable_testing()
 
 # Quick function to add the base executable
 function(add_cli_exe NAME)
-    add_executable(${NAME} ${NAME}.cpp)
-    target_link_libraries(${NAME} CLI11::CLI11)
+  add_executable(${NAME} ${NAME}.cpp)
+  target_link_libraries(${NAME} CLI11::CLI11)
 endfunction()
 
-
 add_cli_exe(simplest)
 add_test(NAME simplest COMMAND simplest)
 
-
 add_cli_exe(intro)
 add_test(NAME intro COMMAND intro)
 add_test(NAME intro_p COMMAND intro -p 5)
 
-
 add_cli_exe(flags)
 add_test(NAME flags COMMAND flags)
 add_test(NAME flags_bip COMMAND flags -b -i -p)
 
-
 add_cli_exe(geet)
-add_test(NAME geet_add    COMMAND geet add)
+add_test(NAME geet_add COMMAND geet add)
 add_test(NAME geet_commit COMMAND geet commit -m "Test")
-
-
diff --git a/packages/CLI11/cmake/CLI11GeneratePkgConfig.cmake b/packages/CLI11/cmake/CLI11GeneratePkgConfig.cmake
index 667705d2a..5abb03d16 100644
--- a/packages/CLI11/cmake/CLI11GeneratePkgConfig.cmake
+++ b/packages/CLI11/cmake/CLI11GeneratePkgConfig.cmake
@@ -1,6 +1,3 @@
 configure_file("cmake/CLI11.pc.in" "CLI11.pc" @ONLY)
 
-install(FILES "${PROJECT_BINARY_DIR}/CLI11.pc"
-  DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
-
-
+install(FILES "${PROJECT_BINARY_DIR}/CLI11.pc" DESTINATION "${CMAKE_INSTALL_DATADIR}/pkgconfig")
diff --git a/packages/CLI11/cmake/CodeCoverage.cmake b/packages/CLI11/cmake/CodeCoverage.cmake
index 907cf72d0..e011ef134 100644
--- a/packages/CLI11/cmake/CodeCoverage.cmake
+++ b/packages/CLI11/cmake/CodeCoverage.cmake
@@ -69,57 +69,51 @@
 include(CMakeParseArguments)
 
 # Check prereqs
-find_program( GCOV_PATH gcov )
-find_program( LCOV_PATH  NAMES lcov lcov.bat lcov.exe lcov.perl)
-find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
-find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
-find_program( SIMPLE_PYTHON_EXECUTABLE python )
+find_program(GCOV_PATH gcov)
+find_program(LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
+find_program(GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat)
+find_program(GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
+find_program(SIMPLE_PYTHON_EXECUTABLE python)
 
 if(NOT GCOV_PATH)
-    message(FATAL_ERROR "gcov not found! Aborting...")
+  message(FATAL_ERROR "gcov not found! Aborting...")
 endif() # NOT GCOV_PATH
 
 if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
-    if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3)
-        message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
-    endif()
+  if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3)
+    message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
+  endif()
 elseif(NOT CMAKE_COMPILER_IS_GNUCXX)
-    message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
+  message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
 endif()
 
-set(COVERAGE_COMPILER_FLAGS "-g -O0 --coverage -fprofile-arcs -ftest-coverage -fno-inline -fno-inline-small-functions -fno-default-inline"
+set(COVERAGE_COMPILER_FLAGS
+    "-g -O0 --coverage -fprofile-arcs -ftest-coverage -fno-inline -fno-inline-small-functions -fno-default-inline"
     CACHE INTERNAL "")
 
 set(CMAKE_CXX_FLAGS_COVERAGE
     ${COVERAGE_COMPILER_FLAGS}
-    CACHE STRING "Flags used by the C++ compiler during coverage builds."
-    FORCE )
+    CACHE STRING "Flags used by the C++ compiler during coverage builds." FORCE)
 set(CMAKE_C_FLAGS_COVERAGE
     ${COVERAGE_COMPILER_FLAGS}
-    CACHE STRING "Flags used by the C compiler during coverage builds."
-    FORCE )
+    CACHE STRING "Flags used by the C compiler during coverage builds." FORCE)
 set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
     ""
-    CACHE STRING "Flags used for linking binaries during coverage builds."
-    FORCE )
+    CACHE STRING "Flags used for linking binaries during coverage builds." FORCE)
 set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
     ""
-    CACHE STRING "Flags used by the shared libraries linker during coverage builds."
-    FORCE )
-mark_as_advanced(
-    CMAKE_CXX_FLAGS_COVERAGE
-    CMAKE_C_FLAGS_COVERAGE
-    CMAKE_EXE_LINKER_FLAGS_COVERAGE
-    CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
+    CACHE STRING "Flags used by the shared libraries linker during coverage builds." FORCE)
+mark_as_advanced(CMAKE_CXX_FLAGS_COVERAGE CMAKE_C_FLAGS_COVERAGE CMAKE_EXE_LINKER_FLAGS_COVERAGE
+                 CMAKE_SHARED_LINKER_FLAGS_COVERAGE)
 
 if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
-    message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
+  message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
 endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
 
 if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
-    link_libraries(gcov)
+  link_libraries(gcov)
 else()
-    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
+  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
 endif()
 
 # Defines a target for running and collection code coverage information
@@ -134,54 +128,57 @@ endif()
 # )
 function(SETUP_TARGET_FOR_COVERAGE)
 
-    set(options NONE)
-    set(oneValueArgs NAME)
-    set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
-    cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
-
-    if(NOT LCOV_PATH)
-        message(FATAL_ERROR "lcov not found! Aborting...")
-    endif() # NOT LCOV_PATH
-
-    if(NOT GENHTML_PATH)
-        message(FATAL_ERROR "genhtml not found! Aborting...")
-    endif() # NOT GENHTML_PATH
-
-    # Setup target
-    add_custom_target(${Coverage_NAME}
-
-        # Cleanup lcov
-        COMMAND ${LCOV_PATH} --directory . --zerocounters
-        # Create baseline to make sure untouched files show up in the report
-        COMMAND ${LCOV_PATH} -c -i -d . -o ${Coverage_NAME}.base
-
-        # Run tests
-        COMMAND ${Coverage_EXECUTABLE}
-
-        # Capturing lcov counters and generating report
-        COMMAND ${LCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info
-        # add baseline counters
-        COMMAND ${LCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file ${Coverage_NAME}.total
-        COMMAND ${LCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_EXCLUDES} --output-file ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
-        COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
-        COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
-
-        WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
-        DEPENDS ${Coverage_DEPENDENCIES}
-        COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
-    )
-
-    # Show where to find the lcov info report
-    add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
-        COMMAND ;
-        COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info."
-    )
-
-    # Show info where to find the report
-    add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
-        COMMAND ;
-        COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
-    )
+  set(options NONE)
+  set(oneValueArgs NAME)
+  set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
+  cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  if(NOT LCOV_PATH)
+    message(FATAL_ERROR "lcov not found! Aborting...")
+  endif() # NOT LCOV_PATH
+
+  if(NOT GENHTML_PATH)
+    message(FATAL_ERROR "genhtml not found! Aborting...")
+  endif() # NOT GENHTML_PATH
+
+  # Setup target
+  add_custom_target(
+    ${Coverage_NAME}
+    # Cleanup lcov
+    COMMAND ${LCOV_PATH} --directory . --zerocounters
+    # Create baseline to make sure untouched files show up in the report
+    COMMAND ${LCOV_PATH} -c -i -d . -o ${Coverage_NAME}.base
+    # Run tests
+    COMMAND ${Coverage_EXECUTABLE}
+    # Capturing lcov counters and generating report
+    COMMAND ${LCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info
+    # add baseline counters
+    COMMAND ${LCOV_PATH} -a ${Coverage_NAME}.base -a ${Coverage_NAME}.info --output-file
+            ${Coverage_NAME}.total
+    COMMAND ${LCOV_PATH} --remove ${Coverage_NAME}.total ${COVERAGE_EXCLUDES} --output-file
+            ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
+    COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
+    COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.total
+            ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned
+    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
+    DEPENDS ${Coverage_DEPENDENCIES}
+    COMMENT
+      "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
+  )
+
+  # Show where to find the lcov info report
+  add_custom_command(
+    TARGET ${Coverage_NAME}
+    POST_BUILD
+    COMMAND ;
+    COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info.")
+
+  # Show info where to find the report
+  add_custom_command(
+    TARGET ${Coverage_NAME}
+    POST_BUILD
+    COMMAND ;
+    COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report.")
 
 endfunction() # SETUP_TARGET_FOR_COVERAGE
 
@@ -197,48 +194,50 @@ endfunction() # SETUP_TARGET_FOR_COVERAGE
 # )
 function(SETUP_TARGET_FOR_COVERAGE_COBERTURA)
 
-    set(options NONE)
-    set(oneValueArgs NAME)
-    set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
-    cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
-
-    if(NOT SIMPLE_PYTHON_EXECUTABLE)
-        message(FATAL_ERROR "python not found! Aborting...")
-    endif() # NOT SIMPLE_PYTHON_EXECUTABLE
-
-    if(NOT GCOVR_PATH)
-        message(FATAL_ERROR "gcovr not found! Aborting...")
-    endif() # NOT GCOVR_PATH
-
-    # Combine excludes to several -e arguments
-    set(COBERTURA_EXCLUDES "")
-    foreach(EXCLUDE ${COVERAGE_EXCLUDES})
-        set(COBERTURA_EXCLUDES "-e ${EXCLUDE} ${COBERTURA_EXCLUDES}")
-    endforeach()
-
-    add_custom_target(${Coverage_NAME}
-
-        # Run tests
-        ${Coverage_EXECUTABLE}
-
-        # Running gcovr
-        COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} ${COBERTURA_EXCLUDES}
-            -o ${Coverage_NAME}.xml
-        WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
-        DEPENDS ${Coverage_DEPENDENCIES}
-        COMMENT "Running gcovr to produce Cobertura code coverage report."
-    )
-
-    # Show info where to find the report
-    add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
-        COMMAND ;
-        COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
-    )
+  set(options NONE)
+  set(oneValueArgs NAME)
+  set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
+  cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  if(NOT SIMPLE_PYTHON_EXECUTABLE)
+    message(FATAL_ERROR "python not found! Aborting...")
+  endif() # NOT SIMPLE_PYTHON_EXECUTABLE
+
+  if(NOT GCOVR_PATH)
+    message(FATAL_ERROR "gcovr not found! Aborting...")
+  endif() # NOT GCOVR_PATH
+
+  # Combine excludes to several -e arguments
+  set(COBERTURA_EXCLUDES "")
+  foreach(EXCLUDE ${COVERAGE_EXCLUDES})
+    set(COBERTURA_EXCLUDES "-e ${EXCLUDE} ${COBERTURA_EXCLUDES}")
+  endforeach()
+
+  add_custom_target(
+    ${Coverage_NAME}
+    # Run tests
+    ${Coverage_EXECUTABLE}
+    # Running gcovr
+    COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} ${COBERTURA_EXCLUDES} -o ${Coverage_NAME}.xml
+    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
+    DEPENDS ${Coverage_DEPENDENCIES}
+    COMMENT "Running gcovr to produce Cobertura code coverage report.")
+
+  # Show info where to find the report
+  add_custom_command(
+    TARGET ${Coverage_NAME}
+    POST_BUILD
+    COMMAND ;
+    COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml.")
 
 endfunction() # SETUP_TARGET_FOR_COVERAGE_COBERTURA
 
 function(APPEND_COVERAGE_COMPILER_FLAGS)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
-    message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
+  set(CMAKE_C_FLAGS
+      "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
+      PARENT_SCOPE)
+  set(CMAKE_CXX_FLAGS
+      "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}"
+      PARENT_SCOPE)
+  message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
 endfunction() # APPEND_COVERAGE_COMPILER_FLAGS
diff --git a/packages/CLI11/docs/CMakeLists.txt b/packages/CLI11/docs/CMakeLists.txt
index f98ff35b6..e7ceb1d39 100644
--- a/packages/CLI11/docs/CMakeLists.txt
+++ b/packages/CLI11/docs/CMakeLists.txt
@@ -2,17 +2,10 @@ set(DOXYGEN_EXTRACT_ALL YES)
 set(DOXYGEN_BUILTIN_STL_SUPPORT YES)
 set(PROJECT_BRIEF "C++11 Command Line Interface Parser")
 
-file(GLOB DOC_LIST
-    RELATIVE "${PROJECT_SOURCE_DIR}/include"
-    "${PROJECT_SOURCE_DIR}/include/CLI/*.hpp"
-    )
-
-doxygen_add_docs(docs
-    ${DOC_LIST}
-    "${CMAKE_CURRENT_SOURCE_DIR}/mainpage.md"
-    WORKING_DIRECTORY
-    "${PROJECT_SOURCE_DIR}/include"
-)
-
-
+file(
+  GLOB DOC_LIST
+  RELATIVE "${PROJECT_SOURCE_DIR}/include"
+  "${PROJECT_SOURCE_DIR}/include/CLI/*.hpp")
 
+doxygen_add_docs(docs ${DOC_LIST} "${CMAKE_CURRENT_SOURCE_DIR}/mainpage.md"
+                 WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/include")
diff --git a/packages/CLI11/docs/mainpage.md b/packages/CLI11/docs/mainpage.md
index b9e2d33f8..b1f2b3967 100644
--- a/packages/CLI11/docs/mainpage.md
+++ b/packages/CLI11/docs/mainpage.md
@@ -1,6 +1,6 @@
 # Introduction {#mainpage}
 
-This is the Doxygen API documentation for CLI11 parser. There is a friendly introduction to CLI11 on the [Github page](https://github.com/CLIUtils/CLI11), and [a tutorial series](https://cliutils.github.io/CLI11/book/).
+This is the Doxygen API documentation for CLI11 parser. There is a friendly introduction to CLI11 on the [GitHub page](https://github.com/CLIUtils/CLI11), and [a tutorial series](https://cliutils.github.io/CLI11/book/).
 
 The main classes are:
 
@@ -14,13 +14,9 @@ The main classes are:
 |CLI::Timer     | A timer class, only in CLI/Timer.hpp (not in `CLI11.hpp`) |
 |CLI::AutoTimer | A timer that prints on deletion     |
 
-
 Groups of related topics:
 
 | Name                 | Description                                    |
 |----------------------|------------------------------------------------|
 | @ref error_group     | Errors that can be thrown                      |
 | @ref validator_group | Common validators used in CLI::Option::check() |
-
-
-
diff --git a/packages/CLI11/examples/CMakeLists.txt b/packages/CLI11/examples/CMakeLists.txt
index 8cea1581d..d0d45c628 100644
--- a/packages/CLI11/examples/CMakeLists.txt
+++ b/packages/CLI11/examples/CMakeLists.txt
@@ -1,186 +1,183 @@
-
 function(add_cli_exe T)
-    add_executable(${T} ${ARGN} ${CLI11_headers})
-    target_link_libraries(${T} PUBLIC CLI11)
-    set_property(TARGET ${T} PROPERTY FOLDER "Examples")
-    if(CLI11_FORCE_LIBCXX)
-        set_property(TARGET ${T} APPEND_STRING PROPERTY LINK_FLAGS -stdlib=libc++)
-    endif()
-    if(CLI11_CLANG_TIDY)
-        set_property(TARGET ${T} PROPERTY CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
-    endif()
+  add_executable(${T} ${ARGN} ${CLI11_headers})
+  target_link_libraries(${T} PUBLIC CLI11)
+  set_property(TARGET ${T} PROPERTY FOLDER "Examples")
+  if(CLI11_FORCE_LIBCXX)
+    set_property(
+      TARGET ${T}
+      APPEND_STRING
+      PROPERTY LINK_FLAGS -stdlib=libc++)
+  endif()
+  if(CLI11_CLANG_TIDY)
+    set_property(TARGET ${T} PROPERTY CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
+  endif()
 endfunction()
 
 if(CLI11_BUILD_EXAMPLES_JSON)
-    message(STATUS "Using nlohmann/json")
-    FetchContent_Declare(json
-        URL https://github.com/nlohmann/json/releases/download/v3.7.3/include.zip
-        URL_HASH "SHA256=87b5884741427220d3a33df1363ae0e8b898099fbc59f1c451113f6732891014"
-    )
-
-    FetchContent_GetProperties(json)
-    if (NOT json_POPULATED)
-        FetchContent_Populate(json)
-    endif()
-
-    add_cli_exe(json json.cpp)
-    target_include_directories(json PUBLIC SYSTEM "${json_SOURCE_DIR}/single_include")
-
-    add_test(NAME json_config_out COMMAND json --item 2)
-    set_property(TEST json_config_out PROPERTY PASS_REGULAR_EXPRESSION
-        [[{]]
-        [["item": "2"]]
-        [["simple": false]]
-        [[}]]
-        )
-
-    file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/input.json" [=[{"item":3,"simple":false}]=])
-    add_test(NAME json_config_in COMMAND json --config "${CMAKE_CURRENT_BINARY_DIR}/input.json")
-    set_property(TEST json_config_in PROPERTY PASS_REGULAR_EXPRESSION
-        [[{]]
-        [["item": "3"]]
-        [["simple": false]]
-        [[}]]
-)
+  message(STATUS "Using nlohmann/json")
+  FetchContent_Declare(
+    json
+    URL https://github.com/nlohmann/json/releases/download/v3.7.3/include.zip
+    URL_HASH "SHA256=87b5884741427220d3a33df1363ae0e8b898099fbc59f1c451113f6732891014")
+
+  FetchContent_GetProperties(json)
+  if(NOT json_POPULATED)
+    FetchContent_Populate(json)
+  endif()
+
+  add_cli_exe(json json.cpp)
+  target_include_directories(json PUBLIC SYSTEM "${json_SOURCE_DIR}/single_include")
+
+  add_test(NAME json_config_out COMMAND json --item 2)
+  set_property(TEST json_config_out PROPERTY PASS_REGULAR_EXPRESSION [[{]] [["item": "2"]]
+                                             [["simple": false]] [[}]])
+
+  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/input.json" [=[{"item":3,"simple":false}]=])
+  add_test(NAME json_config_in COMMAND json --config "${CMAKE_CURRENT_BINARY_DIR}/input.json")
+  set_property(TEST json_config_in PROPERTY PASS_REGULAR_EXPRESSION [[{]] [["item": "3"]]
+                                            [["simple": false]] [[}]])
 endif()
 
-
 add_cli_exe(simple simple.cpp)
 add_test(NAME simple_basic COMMAND simple)
 add_test(NAME simple_all COMMAND simple -f filename.txt -c 12 --flag --flag -d 1.2)
-set_property(TEST simple_all PROPERTY PASS_REGULAR_EXPRESSION
-    "Working on file: filename.txt, direct count: 1, opt count: 1"
-    "Working on count: 12, direct count: 1, opt count: 1"
-    "Received flag: 2 (2) times"
-    "Some value: 1.2")
+set_property(
+  TEST simple_all
+  PROPERTY PASS_REGULAR_EXPRESSION "Working on file: filename.txt, direct count: 1, opt count: 1"
+           "Working on count: 12, direct count: 1, opt count: 1" "Received flag: 2 (2) times"
+           "Some value: 1.2")
 
 add_test(NAME simple_version COMMAND simple --version)
-set_property(TEST simple_version PROPERTY PASS_REGULAR_EXPRESSION
-    "${CLI11_VERSION}")
+set_property(TEST simple_version PROPERTY PASS_REGULAR_EXPRESSION "${CLI11_VERSION}")
 
 add_cli_exe(subcommands subcommands.cpp)
 add_test(NAME subcommands_none COMMAND subcommands)
-set_property(TEST subcommands_none PROPERTY
-    PASS_REGULAR_EXPRESSION "A subcommand is required")
-add_test(NAME subcommands_all COMMAND subcommands --random start --file name stop --count)
-set_property(TEST subcommands_all PROPERTY PASS_REGULAR_EXPRESSION
-    "Working on --file from start: name"
-    "Working on --count from stop: 1, direct count: 1"
-    "Count of --random flag: 1"
-    "Subcommand: start"
-    "Subcommand: stop")
+set_property(TEST subcommands_none PROPERTY PASS_REGULAR_EXPRESSION "A subcommand is required")
+add_test(
+  NAME subcommands_all
+  COMMAND subcommands --random start --file
+  name stop --count)
+set_property(
+  TEST subcommands_all
+  PROPERTY PASS_REGULAR_EXPRESSION "Working on --file from start: name"
+           "Working on --count from stop: 1, direct count: 1" "Count of --random flag: 1"
+           "Subcommand: start" "Subcommand: stop")
 
 add_cli_exe(subcom_partitioned subcom_partitioned.cpp)
 add_test(NAME subcom_partitioned_none COMMAND subcom_partitioned)
-set_property(TEST subcom_partitioned_none PROPERTY PASS_REGULAR_EXPRESSION
-    "This is a timer:"
-    "--file is required"
-    "Run with --help for more information.")
+set_property(
+  TEST subcom_partitioned_none
+  PROPERTY PASS_REGULAR_EXPRESSION "This is a timer:" "--file is required"
+           "Run with --help for more information.")
 
 add_test(NAME subcom_partitioned_all COMMAND subcom_partitioned --file this --count --count -d 1.2)
-set_property(TEST subcom_partitioned_all PROPERTY PASS_REGULAR_EXPRESSION
-    "This is a timer:"
-    "Working on file: this, direct count: 1, opt count: 1"
-    "Working on count: 2, direct count: 2, opt count: 2"
-    "Some value: 1.2")
-    # test shows that the help prints out for unnamed subcommands
+set_property(
+  TEST subcom_partitioned_all
+  PROPERTY PASS_REGULAR_EXPRESSION "This is a timer:"
+           "Working on file: this, direct count: 1, opt count: 1"
+           "Working on count: 2, direct count: 2, opt count: 2" "Some value: 1.2")
+# test shows that the help prints out for unnamed subcommands
 add_test(NAME subcom_partitioned_help COMMAND subcom_partitioned --help)
 set_property(TEST subcom_partitioned_help PROPERTY PASS_REGULAR_EXPRESSION
-    "-f,--file TEXT REQUIRED"
-    "-d,--double FLOAT")
+                                                   "-f,--file TEXT REQUIRED" "-d,--double FLOAT")
+
+####################################################
+add_cli_exe(config_app config_app.cpp)
+add_test(NAME config_app1 COMMAND config_app -p)
+set_property(TEST config_app1 PROPERTY PASS_REGULAR_EXPRESSION "file=")
+
+add_test(NAME config_app2 COMMAND config_app -p -f /)
+set_property(TEST config_app2 PROPERTY PASS_REGULAR_EXPRESSION "file=\"/\"")
+
+add_test(NAME config_app3 COMMAND config_app -f "" -p)
+set_property(TEST config_app3 PROPERTY PASS_REGULAR_EXPRESSION "file=\"\"")
+
+add_test(NAME config_app4 COMMAND config_app -f "/" -p)
+set_property(TEST config_app4 PROPERTY PASS_REGULAR_EXPRESSION "file=\"/\"")
+
+####################################################
 
 add_cli_exe(option_groups option_groups.cpp)
-add_test(NAME option_groups_missing COMMAND option_groups )
-set_property(TEST option_groups_missing PROPERTY PASS_REGULAR_EXPRESSION
-    "Exactly 1 option from"
-    "is required")
+add_test(NAME option_groups_missing COMMAND option_groups)
+set_property(TEST option_groups_missing PROPERTY PASS_REGULAR_EXPRESSION "Exactly 1 option from"
+                                                 "is required")
 add_test(NAME option_groups_extra COMMAND option_groups --csv --binary)
-set_property(TEST option_groups_extra PROPERTY PASS_REGULAR_EXPRESSION
-    "and 2 were given")
-add_test(NAME option_groups_extra2 COMMAND option_groups --csv --address "192.168.1.1" -o "test.out")
-set_property(TEST option_groups_extra2 PROPERTY PASS_REGULAR_EXPRESSION
-    "at most 1")
+set_property(TEST option_groups_extra PROPERTY PASS_REGULAR_EXPRESSION "and 2 were given")
+add_test(NAME option_groups_extra2 COMMAND option_groups --csv --address "192.168.1.1" -o
+                                           "test.out")
+set_property(TEST option_groups_extra2 PROPERTY PASS_REGULAR_EXPRESSION "at most 1")
 
 add_cli_exe(positional_arity positional_arity.cpp)
-add_test(NAME positional_arity1 COMMAND positional_arity one )
-set_property(TEST positional_arity1 PROPERTY PASS_REGULAR_EXPRESSION
-    "File 1 = one")
-add_test(NAME positional_arity2 COMMAND positional_arity one two )
-set_property(TEST positional_arity2 PROPERTY PASS_REGULAR_EXPRESSION
-    "File 1 = one"
-    "File 2 = two")
+add_test(NAME positional_arity1 COMMAND positional_arity one)
+set_property(TEST positional_arity1 PROPERTY PASS_REGULAR_EXPRESSION "File 1 = one")
+add_test(NAME positional_arity2 COMMAND positional_arity one two)
+set_property(TEST positional_arity2 PROPERTY PASS_REGULAR_EXPRESSION "File 1 = one" "File 2 = two")
 add_test(NAME positional_arity3 COMMAND positional_arity 1 2 one)
-set_property(TEST positional_arity3 PROPERTY PASS_REGULAR_EXPRESSION
-    "File 1 = one")
+set_property(TEST positional_arity3 PROPERTY PASS_REGULAR_EXPRESSION "File 1 = one")
 add_test(NAME positional_arity_fail COMMAND positional_arity 1 one two)
-set_property(TEST positional_arity_fail PROPERTY PASS_REGULAR_EXPRESSION
-    "Could not convert")
-
-    add_cli_exe(positional_validation positional_validation.cpp)
-add_test(NAME positional_validation1 COMMAND positional_validation one )
-set_property(TEST positional_validation1 PROPERTY PASS_REGULAR_EXPRESSION
-    "File 1 = one")
-add_test(NAME positional_validation2 COMMAND positional_validation one 1 2 two )
-set_property(TEST positional_validation2 PROPERTY PASS_REGULAR_EXPRESSION
-    "File 1 = one"
-    "File 2 = two")
+set_property(TEST positional_arity_fail PROPERTY PASS_REGULAR_EXPRESSION "Could not convert")
+
+add_cli_exe(positional_validation positional_validation.cpp)
+add_test(NAME positional_validation1 COMMAND positional_validation one)
+set_property(TEST positional_validation1 PROPERTY PASS_REGULAR_EXPRESSION "File 1 = one")
+add_test(NAME positional_validation2 COMMAND positional_validation one 1 2 two)
+set_property(TEST positional_validation2 PROPERTY PASS_REGULAR_EXPRESSION "File 1 = one"
+                                                  "File 2 = two")
 add_test(NAME positional_validation3 COMMAND positional_validation 1 2 one)
-set_property(TEST positional_validation3 PROPERTY PASS_REGULAR_EXPRESSION
-    "File 1 = one")
+set_property(TEST positional_validation3 PROPERTY PASS_REGULAR_EXPRESSION "File 1 = one")
 add_test(NAME positional_validation4 COMMAND positional_validation 1 one two 2)
-set_property(TEST positional_validation4 PROPERTY PASS_REGULAR_EXPRESSION
-     "File 1 = one"
-    "File 2 = two")
+set_property(TEST positional_validation4 PROPERTY PASS_REGULAR_EXPRESSION "File 1 = one"
+                                                  "File 2 = two")
 
 add_cli_exe(shapes shapes.cpp)
-add_test(NAME shapes_all COMMAND shapes circle 4.4 circle 10.7 rectangle 4 4 circle 2.3 triangle 4.5 ++ rectangle 2.1 ++ circle 234.675)
-set_property(TEST shapes_all PROPERTY PASS_REGULAR_EXPRESSION
-    "circle2"
-    "circle4"
-    "rectangle2 with edges [2.1,2.1]"
-    "triangel1 with sides [4.5]")
+add_test(NAME shapes_all COMMAND shapes circle 4.4 circle 10.7 rectangle 4 4 circle 2.3 triangle
+                                 4.5 ++ rectangle 2.1 ++ circle 234.675)
+set_property(
+  TEST shapes_all PROPERTY PASS_REGULAR_EXPRESSION "circle2" "circle4"
+                           "rectangle2 with edges [2.1,2.1]" "triangel1 with sides [4.5]")
 
 add_cli_exe(ranges ranges.cpp)
 add_test(NAME ranges_range COMMAND ranges --range 1 2 3)
-set_property(TEST ranges_range PROPERTY PASS_REGULAR_EXPRESSION
-    "[2:1:3]")
+set_property(TEST ranges_range PROPERTY PASS_REGULAR_EXPRESSION "[2:1:3]")
 add_test(NAME ranges_minmax COMMAND ranges --min 2 --max 3)
-set_property(TEST ranges_minmax PROPERTY PASS_REGULAR_EXPRESSION
-    "[2:1:3]")
+set_property(TEST ranges_minmax PROPERTY PASS_REGULAR_EXPRESSION "[2:1:3]")
 add_test(NAME ranges_error COMMAND ranges --min 2 --max 3 --step 1 --range 1 2 3)
-set_property(TEST ranges_error PROPERTY PASS_REGULAR_EXPRESSION
-    "Exactly 1 option from")
+set_property(TEST ranges_error PROPERTY PASS_REGULAR_EXPRESSION "Exactly 1 option from")
 
 add_cli_exe(validators validators.cpp)
 add_test(NAME validators_help COMMAND validators --help)
-set_property(TEST validators_help PROPERTY PASS_REGULAR_EXPRESSION
-    "  -f,--file TEXT:FILE[\\r\\n\\t ]+File name"
-    "  -v,--value INT:INT in [3 - 6][\\r\\n\\t ]+Value in range")
+set_property(
+  TEST validators_help
+  PROPERTY PASS_REGULAR_EXPRESSION "  -f,--file TEXT:FILE[\\r\\n\\t ]+File name"
+           "  -v,--value INT:INT in [3 - 6][\\r\\n\\t ]+Value in range")
 add_test(NAME validators_file COMMAND validators --file nonex.xxx)
-set_property(TEST validators_file PROPERTY PASS_REGULAR_EXPRESSION
-    "--file: File does not exist: nonex.xxx"
-    "Run with --help for more information.")
+set_property(
+  TEST validators_file PROPERTY PASS_REGULAR_EXPRESSION "--file: File does not exist: nonex.xxx"
+                                "Run with --help for more information.")
 add_test(NAME validators_plain COMMAND validators --value 9)
-set_property(TEST validators_plain PROPERTY PASS_REGULAR_EXPRESSION
-    "--value: Value 9 not in range 3 to 6"
-    "Run with --help for more information.")
+set_property(
+  TEST validators_plain PROPERTY PASS_REGULAR_EXPRESSION "--value: Value 9 not in range 3 to 6"
+                                 "Run with --help for more information.")
 
 add_cli_exe(groups groups.cpp)
 add_test(NAME groups_none COMMAND groups)
-set_property(TEST groups_none PROPERTY PASS_REGULAR_EXPRESSION
-    "This is a timer:"
-    "--file is required"
-    "Run with --help for more information.")
+set_property(
+  TEST groups_none PROPERTY PASS_REGULAR_EXPRESSION "This is a timer:" "--file is required"
+                            "Run with --help for more information.")
 add_test(NAME groups_all COMMAND groups --file this --count --count -d 1.2)
-set_property(TEST groups_all PROPERTY PASS_REGULAR_EXPRESSION
-    "This is a timer:"
-    "Working on file: this, direct count: 1, opt count: 1"
-    "Working on count: 2, direct count: 2, opt count: 2"
-    "Some value: 1.2")
+set_property(
+  TEST groups_all
+  PROPERTY PASS_REGULAR_EXPRESSION "This is a timer:"
+           "Working on file: this, direct count: 1, opt count: 1"
+           "Working on count: 2, direct count: 2, opt count: 2" "Some value: 1.2")
 
 add_cli_exe(inter_argument_order inter_argument_order.cpp)
-add_test(NAME inter_argument_order COMMAND inter_argument_order --foo 1 2 3 --x --bar 4 5 6 --z --foo 7 8)
-set_property(TEST inter_argument_order PROPERTY PASS_REGULAR_EXPRESSION
+add_test(NAME inter_argument_order COMMAND inter_argument_order --foo 1 2 3 --x --bar 4 5 6 --z
+                                           --foo 7 8)
+set_property(
+  TEST inter_argument_order
+  PROPERTY
+    PASS_REGULAR_EXPRESSION
     [=[foo : 1
 foo : 2
 foo : 3
@@ -192,44 +189,37 @@ foo : 8]=])
 
 add_cli_exe(prefix_command prefix_command.cpp)
 add_test(NAME prefix_command COMMAND prefix_command -v 3 2 1 -- other one two 3)
-set_property(TEST prefix_command PROPERTY PASS_REGULAR_EXPRESSION
-    "Prefix: 3 : 2 : 1"
-    "Remaining commands: other one two 3")
+set_property(TEST prefix_command PROPERTY PASS_REGULAR_EXPRESSION "Prefix: 3 : 2 : 1"
+                                          "Remaining commands: other one two 3")
 
 add_cli_exe(callback_passthrough callback_passthrough.cpp)
 add_test(NAME callback_passthrough1 COMMAND callback_passthrough --argname t2 --t2 test)
-set_property(TEST callback_passthrough1 PROPERTY PASS_REGULAR_EXPRESSION
-    "the value is now test")
+set_property(TEST callback_passthrough1 PROPERTY PASS_REGULAR_EXPRESSION "the value is now test")
 add_test(NAME callback_passthrough2 COMMAND callback_passthrough --arg EEEK --argname arg)
-set_property(TEST callback_passthrough2 PROPERTY PASS_REGULAR_EXPRESSION
-    "the value is now EEEK")
+set_property(TEST callback_passthrough2 PROPERTY PASS_REGULAR_EXPRESSION "the value is now EEEK")
 
 add_cli_exe(enum enum.cpp)
 add_test(NAME enum_pass COMMAND enum -l 1)
 add_test(NAME enum_fail COMMAND enum -l 4)
-set_property(TEST enum_fail PROPERTY PASS_REGULAR_EXPRESSION
-    "--level: Check 4 value in {" "FAILED")
+set_property(TEST enum_fail PROPERTY PASS_REGULAR_EXPRESSION "--level: Check 4 value in {"
+                                     "FAILED")
 
 add_cli_exe(enum_ostream enum_ostream.cpp)
 add_test(NAME enum_ostream_pass COMMAND enum_ostream --level medium)
-set_property(TEST enum_ostream_pass PROPERTY PASS_REGULAR_EXPRESSION
-    "Enum received: Medium")
+set_property(TEST enum_ostream_pass PROPERTY PASS_REGULAR_EXPRESSION "Enum received: Medium")
 
 add_cli_exe(digit_args digit_args.cpp)
 add_test(NAME digit_args COMMAND digit_args -h)
-set_property(TEST digit_args PROPERTY PASS_REGULAR_EXPRESSION
-    "-3{3}")
+set_property(TEST digit_args PROPERTY PASS_REGULAR_EXPRESSION "-3{3}")
 
 add_cli_exe(modhelp modhelp.cpp)
 add_test(NAME modhelp COMMAND modhelp -a test -h)
-set_property(TEST modhelp PROPERTY PASS_REGULAR_EXPRESSION
-    "Option -a string in help: test")
+set_property(TEST modhelp PROPERTY PASS_REGULAR_EXPRESSION "Option -a string in help: test")
 
 add_subdirectory(subcom_in_files)
 add_test(NAME subcom_in_files COMMAND subcommand_main subcommand_a -f this.txt --with-foo)
-set_property(TEST subcom_in_files PROPERTY PASS_REGULAR_EXPRESSION
-    "Working on file: this\.txt"
-    "Using foo!")
+set_property(TEST subcom_in_files PROPERTY PASS_REGULAR_EXPRESSION "Working on file: this\.txt"
+                                           "Using foo!")
 
 add_cli_exe(formatter formatter.cpp)
 
@@ -245,14 +235,15 @@ add_test(NAME retired_retired_test2 COMMAND retired --retired_option 567)
 add_test(NAME retired_retired_test3 COMMAND retired --retired_option2 567 689 789)
 add_test(NAME retired_deprecated COMMAND retired --deprecate 19 20)
 
-set_property(TEST retired_retired_test PROPERTY PASS_REGULAR_EXPRESSION
-    "WARNING.*retired")
+set_property(TEST retired_retired_test PROPERTY PASS_REGULAR_EXPRESSION "WARNING.*retired")
+
+set_property(TEST retired_retired_test2 PROPERTY PASS_REGULAR_EXPRESSION "WARNING.*retired")
 
-set_property(TEST retired_retired_test2 PROPERTY PASS_REGULAR_EXPRESSION
-    "WARNING.*retired")
+set_property(TEST retired_retired_test3 PROPERTY PASS_REGULAR_EXPRESSION "WARNING.*retired")
 
-set_property(TEST retired_retired_test3 PROPERTY PASS_REGULAR_EXPRESSION
-    "WARNING.*retired")
+set_property(TEST retired_deprecated PROPERTY PASS_REGULAR_EXPRESSION "deprecated.*not_deprecated")
 
-set_property(TEST retired_deprecated PROPERTY PASS_REGULAR_EXPRESSION
-    "deprecated.*not_deprecated")
+#--------------------------------------------
+add_cli_exe(custom_parse custom_parse.cpp)
+add_test(NAME cp_test COMMAND custom_parse --dv 1.7)
+set_property(TEST cp_test PROPERTY PASS_REGULAR_EXPRESSION "called correct")
diff --git a/packages/CLI11/examples/callback_passthrough.cpp b/packages/CLI11/examples/callback_passthrough.cpp
index 16698aafb..48a248756 100644
--- a/packages/CLI11/examples/callback_passthrough.cpp
+++ b/packages/CLI11/examples/callback_passthrough.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/config_app.cpp b/packages/CLI11/examples/config_app.cpp
new file mode 100644
index 000000000..aec9fefdf
--- /dev/null
+++ b/packages/CLI11/examples/config_app.cpp
@@ -0,0 +1,50 @@
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
+// under NSF AWARD 1414736 and by the respective contributors.
+// All rights reserved.
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+#include <CLI/CLI.hpp>
+#include <iostream>
+#include <string>
+
+int main(int argc, char **argv) {
+
+    CLI::App app("configuration print example");
+
+    app.add_flag("-p,--print", "Print configuration and exit")->configurable(false);  // NEW: print flag
+
+    std::string file;
+    CLI::Option *opt = app.add_option("-f,--file,file", file, "File name")
+                           ->capture_default_str()
+                           ->run_callback_for_default();  // NEW: capture_default_str()
+
+    int count{0};
+    CLI::Option *copt =
+        app.add_option("-c,--count", count, "Counter")->capture_default_str();  // NEW: capture_default_str()
+
+    int v{0};
+    CLI::Option *flag = app.add_flag("--flag", v, "Some flag that can be passed multiple times")
+                            ->capture_default_str();  // NEW: capture_default_str()
+
+    double value{0.0};                                                          // = 3.14;
+    app.add_option("-d,--double", value, "Some Value")->capture_default_str();  // NEW: capture_default_str()
+
+    app.get_config_formatter_base()->quoteCharacter('"', '"');
+
+    CLI11_PARSE(app, argc, argv);
+
+    if(app.get_option("--print")->as<bool>()) {  // NEW: print configuration and exit
+        std::cout << app.config_to_str(true, false);
+        return 0;
+    }
+
+    std::cout << "Working on file: " << file << ", direct count: " << app.count("--file")
+              << ", opt count: " << opt->count() << std::endl;
+    std::cout << "Working on count: " << count << ", direct count: " << app.count("--count")
+              << ", opt count: " << copt->count() << std::endl;
+    std::cout << "Received flag: " << v << " (" << flag->count() << ") times\n";
+    std::cout << "Some value: " << value << std::endl;
+
+    return 0;
+}
diff --git a/packages/CLI11/examples/custom_parse.cpp b/packages/CLI11/examples/custom_parse.cpp
new file mode 100644
index 000000000..44fc77afd
--- /dev/null
+++ b/packages/CLI11/examples/custom_parse.cpp
@@ -0,0 +1,39 @@
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
+// under NSF AWARD 1414736 and by the respective contributors.
+// All rights reserved.
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+// from Issue #566 on github https://github.com/CLIUtils/CLI11/issues/566
+
+#include <CLI/CLI.hpp>
+#include <iostream>
+#include <sstream>
+
+// example file to demonstrate a custom lexical cast function
+
+template <class T = int> struct Values {
+    T a;
+    T b;
+    T c;
+};
+
+// in C++20 this is constructible from a double due to the new aggregate initialization in C++20.
+using DoubleValues = Values<double>;
+
+// the lexical cast operator should be in the same namespace as the type for ADL to work properly
+bool lexical_cast(const std::string &input, Values<double> &v) {
+    std::cout << "called correct lexical_cast function ! val: " << input << std::endl;
+    return true;
+}
+
+DoubleValues doubles;
+void argparse(CLI::Option_group *group) { group->add_option("--dv", doubles)->default_str("0"); }
+
+int main(int argc, char **argv) {
+    CLI::App app;
+
+    argparse(app.add_option_group("param"));
+    CLI11_PARSE(app, argc, argv);
+    return 0;
+}
diff --git a/packages/CLI11/examples/digit_args.cpp b/packages/CLI11/examples/digit_args.cpp
index cf8f7d331..af0891a4f 100644
--- a/packages/CLI11/examples/digit_args.cpp
+++ b/packages/CLI11/examples/digit_args.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/enum.cpp b/packages/CLI11/examples/enum.cpp
index a73e56b3f..09b7f043b 100644
--- a/packages/CLI11/examples/enum.cpp
+++ b/packages/CLI11/examples/enum.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/enum_ostream.cpp b/packages/CLI11/examples/enum_ostream.cpp
index 13d33502a..4e3e6b297 100644
--- a/packages/CLI11/examples/enum_ostream.cpp
+++ b/packages/CLI11/examples/enum_ostream.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/formatter.cpp b/packages/CLI11/examples/formatter.cpp
index 81d6209f4..3b2e3dce5 100644
--- a/packages/CLI11/examples/formatter.cpp
+++ b/packages/CLI11/examples/formatter.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/groups.cpp b/packages/CLI11/examples/groups.cpp
index 22d628948..c766d6b23 100644
--- a/packages/CLI11/examples/groups.cpp
+++ b/packages/CLI11/examples/groups.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/inter_argument_order.cpp b/packages/CLI11/examples/inter_argument_order.cpp
index deecd057e..ebee3977a 100644
--- a/packages/CLI11/examples/inter_argument_order.cpp
+++ b/packages/CLI11/examples/inter_argument_order.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/json.cpp b/packages/CLI11/examples/json.cpp
index d5fe35a70..ae2595c00 100644
--- a/packages/CLI11/examples/json.cpp
+++ b/packages/CLI11/examples/json.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/modhelp.cpp b/packages/CLI11/examples/modhelp.cpp
index 706abcae0..9c674300f 100644
--- a/packages/CLI11/examples/modhelp.cpp
+++ b/packages/CLI11/examples/modhelp.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/nested.cpp b/packages/CLI11/examples/nested.cpp
index 23f428514..dc8323fe0 100644
--- a/packages/CLI11/examples/nested.cpp
+++ b/packages/CLI11/examples/nested.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -18,7 +18,9 @@ int main(int argc, char **argv) {
 
     std::string mvcamera_config_file = "mvcamera_config.json";
     CLI::App *mvcameraApp = cameraApp->add_subcommand("mvcamera", "MatrixVision Camera Configuration");
-    mvcameraApp->add_option("-c,--config", mvcamera_config_file, "Config filename", true)->check(CLI::ExistingFile);
+    mvcameraApp->add_option("-c,--config", mvcamera_config_file, "Config filename")
+        ->capture_default_str()
+        ->check(CLI::ExistingFile);
 
     std::string mock_camera_path;
     CLI::App *mockcameraApp = cameraApp->add_subcommand("mock", "Mock Camera Configuration");
diff --git a/packages/CLI11/examples/option_groups.cpp b/packages/CLI11/examples/option_groups.cpp
index 679cb754b..acc65740d 100644
--- a/packages/CLI11/examples/option_groups.cpp
+++ b/packages/CLI11/examples/option_groups.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/positional_arity.cpp b/packages/CLI11/examples/positional_arity.cpp
index eb6639b04..e9238fc74 100644
--- a/packages/CLI11/examples/positional_arity.cpp
+++ b/packages/CLI11/examples/positional_arity.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/positional_validation.cpp b/packages/CLI11/examples/positional_validation.cpp
index 421de2509..afc03fa80 100644
--- a/packages/CLI11/examples/positional_validation.cpp
+++ b/packages/CLI11/examples/positional_validation.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/prefix_command.cpp b/packages/CLI11/examples/prefix_command.cpp
index 8977adcbd..2af1a87b3 100644
--- a/packages/CLI11/examples/prefix_command.cpp
+++ b/packages/CLI11/examples/prefix_command.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/ranges.cpp b/packages/CLI11/examples/ranges.cpp
index 085a7ad1b..6b4c1e3bc 100644
--- a/packages/CLI11/examples/ranges.cpp
+++ b/packages/CLI11/examples/ranges.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -19,7 +19,7 @@ int main(int argc, char **argv) {
     int min{0}, max{0}, step{1};
     ogroup->add_option("--min,-m", min, "The minimum")->required();
     ogroup->add_option("--max,-M", max, "The maximum")->required();
-    ogroup->add_option("--step,-s", step, "The step", true);
+    ogroup->add_option("--step,-s", step, "The step")->capture_default_str();
 
     app.require_option(1);
 
diff --git a/packages/CLI11/examples/retired.cpp b/packages/CLI11/examples/retired.cpp
index d658e754f..3a18db4ae 100644
--- a/packages/CLI11/examples/retired.cpp
+++ b/packages/CLI11/examples/retired.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/shapes.cpp b/packages/CLI11/examples/shapes.cpp
index 880441b85..b318df0e1 100644
--- a/packages/CLI11/examples/shapes.cpp
+++ b/packages/CLI11/examples/shapes.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/simple.cpp b/packages/CLI11/examples/simple.cpp
index c1354eaf3..0f904420f 100644
--- a/packages/CLI11/examples/simple.cpp
+++ b/packages/CLI11/examples/simple.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/subcom_help.cpp b/packages/CLI11/examples/subcom_help.cpp
index d41d4a59b..89af131da 100644
--- a/packages/CLI11/examples/subcom_help.cpp
+++ b/packages/CLI11/examples/subcom_help.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/subcom_in_files/subcommand_a.cpp b/packages/CLI11/examples/subcom_in_files/subcommand_a.cpp
index 63474fdc3..6b229839b 100644
--- a/packages/CLI11/examples/subcom_in_files/subcommand_a.cpp
+++ b/packages/CLI11/examples/subcom_in_files/subcommand_a.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/subcom_in_files/subcommand_a.hpp b/packages/CLI11/examples/subcom_in_files/subcommand_a.hpp
index 2993739ea..116160c53 100644
--- a/packages/CLI11/examples/subcom_in_files/subcommand_a.hpp
+++ b/packages/CLI11/examples/subcom_in_files/subcommand_a.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/subcom_in_files/subcommand_main.cpp b/packages/CLI11/examples/subcom_in_files/subcommand_main.cpp
index 76ebe7c01..62b63806e 100644
--- a/packages/CLI11/examples/subcom_in_files/subcommand_main.cpp
+++ b/packages/CLI11/examples/subcom_in_files/subcommand_main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/subcom_partitioned.cpp b/packages/CLI11/examples/subcom_partitioned.cpp
index 20dd36232..df48e2d79 100644
--- a/packages/CLI11/examples/subcom_partitioned.cpp
+++ b/packages/CLI11/examples/subcom_partitioned.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/subcommands.cpp b/packages/CLI11/examples/subcommands.cpp
index 937eaeaf4..68f163a75 100644
--- a/packages/CLI11/examples/subcommands.cpp
+++ b/packages/CLI11/examples/subcommands.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/examples/validators.cpp b/packages/CLI11/examples/validators.cpp
index 05ea045c0..6ca8d3896 100644
--- a/packages/CLI11/examples/validators.cpp
+++ b/packages/CLI11/examples/validators.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/App.hpp b/packages/CLI11/include/CLI/App.hpp
index edbe2b738..03b58d9fe 100644
--- a/packages/CLI11/include/CLI/App.hpp
+++ b/packages/CLI11/include/CLI/App.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -55,7 +55,7 @@ std::string help(const App *app, const Error &e);
 
 /// enumeration of modes of how to deal with extras in config files
 
-enum class config_extras_mode : char { error = 0, ignore, capture };
+enum class config_extras_mode : char { error = 0, ignore, ignore_all, capture };
 
 class App;
 
@@ -113,6 +113,7 @@ class App {
 
     /// This is a function that runs when parsing has finished.
     std::function<void()> parse_complete_callback_{};
+
     /// This is a function that runs when all processing has completed
     std::function<void()> final_callback_{};
 
@@ -367,10 +368,9 @@ class App {
 
     /// Set an alias for the app
     App *alias(std::string app_name) {
-        if(!detail::valid_name_string(app_name)) {
-            throw(IncorrectConstruction("alias is not a valid name string"));
+        if(app_name.empty() || !detail::valid_alias_name_string(app_name)) {
+            throw IncorrectConstruction("Aliases may not be empty or contain newlines or null characters");
         }
-
         if(parent_ != nullptr) {
             aliases_.push_back(app_name);
             auto &res = _compare_subcommand_names(*this, *_get_fallthrough_parent());
@@ -611,14 +611,13 @@ class App {
               enable_if_t<!std::is_const<ConvertTo>::value, detail::enabler> = detail::dummy>
     Option *add_option(std::string option_name,
                        AssignTo &variable,  ///< The variable to set
-                       std::string option_description = "",
-                       bool defaulted = false) {
+                       std::string option_description = "") {
 
         auto fun = [&variable](const CLI::results_t &res) {  // comment for spacing
             return detail::lexical_conversion<AssignTo, ConvertTo>(res, variable);
         };
 
-        Option *opt = add_option(option_name, fun, option_description, defaulted, [&variable]() {
+        Option *opt = add_option(option_name, fun, option_description, false, [&variable]() {
             return CLI::detail::checked_to_string<AssignTo, ConvertTo>(variable);
         });
         opt->type_name(detail::type_name<ConvertTo>());
@@ -720,7 +719,9 @@ class App {
     }
 
     /// Set a version flag and version display string, replace the existing one if present
-    Option *set_version_flag(std::string flag_name = "", const std::string &versionString = "") {
+    Option *set_version_flag(std::string flag_name = "",
+                             const std::string &versionString = "",
+                             const std::string &version_help = "Display program version information and exit") {
         // take flag_description by const reference otherwise add_flag tries to assign to version_description
         if(version_ptr_ != nullptr) {
             remove_option(version_ptr_);
@@ -730,17 +731,16 @@ class App {
         // Empty name will simply remove the version flag
         if(!flag_name.empty()) {
             version_ptr_ = add_flag_callback(
-                flag_name,
-                [versionString]() { throw(CLI::CallForVersion(versionString, 0)); },
-                "Display program version information and exit");
+                flag_name, [versionString]() { throw(CLI::CallForVersion(versionString, 0)); }, version_help);
             version_ptr_->configurable(false);
         }
 
         return version_ptr_;
     }
     /// Generate the version string through a callback function
-    Option *set_version_flag(std::string flag_name, std::function<std::string()> vfunc) {
-        // take flag_description by const reference otherwise add_flag tries to assign to version_description
+    Option *set_version_flag(std::string flag_name,
+                             std::function<std::string()> vfunc,
+                             const std::string &version_help = "Display program version information and exit") {
         if(version_ptr_ != nullptr) {
             remove_option(version_ptr_);
             version_ptr_ = nullptr;
@@ -749,9 +749,7 @@ class App {
         // Empty name will simply remove the version flag
         if(!flag_name.empty()) {
             version_ptr_ = add_flag_callback(
-                flag_name,
-                [vfunc]() { throw(CLI::CallForVersion(vfunc(), 0)); },
-                "Display program version information and exit");
+                flag_name, [vfunc]() { throw(CLI::CallForVersion(vfunc(), 0)); }, version_help);
             version_ptr_->configurable(false);
         }
 
@@ -897,56 +895,6 @@ class App {
     }
 #endif
 
-    /// Add a complex number DEPRECATED --use add_option instead
-    template <typename T, typename XC = double>
-    Option *add_complex(std::string option_name,
-                        T &variable,
-                        std::string option_description = "",
-                        bool defaulted = false,
-                        std::string label = "COMPLEX") {
-
-        CLI::callback_t fun = [&variable](const results_t &res) {
-            XC x, y;
-            bool worked;
-            if(res.size() >= 2 && !res[1].empty()) {
-                auto str1 = res[1];
-                if(str1.back() == 'i' || str1.back() == 'j')
-                    str1.pop_back();
-                worked = detail::lexical_cast(res[0], x) && detail::lexical_cast(str1, y);
-            } else {
-                auto str1 = res.front();
-                auto nloc = str1.find_last_of('-');
-                if(nloc != std::string::npos && nloc > 0) {
-                    worked = detail::lexical_cast(str1.substr(0, nloc), x);
-                    str1 = str1.substr(nloc);
-                    if(str1.back() == 'i' || str1.back() == 'j')
-                        str1.pop_back();
-                    worked = worked && detail::lexical_cast(str1, y);
-                } else {
-                    if(str1.back() == 'i' || str1.back() == 'j') {
-                        str1.pop_back();
-                        worked = detail::lexical_cast(str1, y);
-                        x = XC{0};
-                    } else {
-                        worked = detail::lexical_cast(str1, x);
-                        y = XC{0};
-                    }
-                }
-            }
-            if(worked)
-                variable = T{x, y};
-            return worked;
-        };
-
-        auto default_function = [&variable]() { return CLI::detail::checked_to_string<T, T>(variable); };
-
-        CLI::Option *opt =
-            add_option(option_name, std::move(fun), std::move(option_description), defaulted, default_function);
-
-        opt->type_name(label)->type_size(1, 2)->delimiter('+')->run_callback_for_default();
-        return opt;
-    }
-
     /// Set a configuration ini file option, or clear it if no name passed
     Option *set_config(std::string option_name = "",
                        std::string default_filename = "",
@@ -999,6 +947,9 @@ class App {
     /// creates an option group as part of the given app
     template <typename T = Option_group>
     T *add_option_group(std::string group_name, std::string group_description = "") {
+        if(!detail::valid_alias_name_string(group_name)) {
+            throw IncorrectConstruction("option group names may not contain newlines or null characters");
+        }
         auto option_group = std::make_shared<T>(std::move(group_description), group_name, this);
         auto ptr = option_group.get();
         // move to App_p for overload resolution on older gcc versions
@@ -1014,7 +965,17 @@ class App {
     /// Add a subcommand. Inherits INHERITABLE and OptionDefaults, and help flag
     App *add_subcommand(std::string subcommand_name = "", std::string subcommand_description = "") {
         if(!subcommand_name.empty() && !detail::valid_name_string(subcommand_name)) {
-            throw IncorrectConstruction("subcommand name is not valid");
+            if(!detail::valid_first_char(subcommand_name[0])) {
+                throw IncorrectConstruction(
+                    "Subcommand name starts with invalid character, '!' and '-' are not allowed");
+            }
+            for(auto c : subcommand_name) {
+                if(!detail::valid_later_char(c)) {
+                    throw IncorrectConstruction(std::string("Subcommand name contains invalid character ('") + c +
+                                                "'), all characters are allowed except"
+                                                "'=',':','{','}', and ' '");
+                }
+            }
         }
         CLI::App_p subcom = std::shared_ptr<App>(new App(std::move(subcommand_description), subcommand_name, this));
         return add_subcommand(std::move(subcom));
@@ -1329,6 +1290,16 @@ class App {
         run_callback();
     }
 
+    void parse_from_stream(std::istream &input) {
+        if(parsed_ == 0) {
+            _validate();
+            _configure();
+            // set the parent as nullptr as this object should be the top now
+        }
+
+        _parse_stream(input);
+        run_callback();
+    }
     /// Provide a function to print a help message. The function gets access to the App pointer and error.
     void failure_message(std::function<std::string(const App *, const Error &e)> function) {
         failure_message_ = function;
@@ -1791,7 +1762,7 @@ class App {
         if(name_.empty()) {
             return std::string("[Option Group: ") + get_group() + "]";
         }
-        if(aliases_.empty() || !with_aliases || aliases_.empty()) {
+        if(aliases_.empty() || !with_aliases) {
             return name_;
         }
         std::string dispname = name_;
@@ -1963,8 +1934,9 @@ class App {
             app->_configure();
         }
     }
+
     /// Internal function to run (App) callback, bottom up
-    void run_callback(bool final_mode = false) {
+    void run_callback(bool final_mode = false, bool suppress_final_callback = false) {
         pre_callback();
         // in the main app if immediate_callback_ is set it runs the main callback before the used subcommands
         if(!final_mode && parse_complete_callback_) {
@@ -1972,18 +1944,18 @@ class App {
         }
         // run the callbacks for the received subcommands
         for(App *subc : get_subcommands()) {
-            subc->run_callback(true);
+            subc->run_callback(true, suppress_final_callback);
         }
         // now run callbacks for option_groups
         for(auto &subc : subcommands_) {
             if(subc->name_.empty() && subc->count_all() > 0) {
-                subc->run_callback(true);
+                subc->run_callback(true, suppress_final_callback);
             }
         }
 
         // finally run the main callback
-        if(final_callback_ && (parsed_ > 0)) {
-            if(!name_.empty() || count_all() > 0) {
+        if(final_callback_ && (parsed_ > 0) && (!suppress_final_callback)) {
+            if(!name_.empty() || count_all() > 0 || parent_ == nullptr) {
                 final_callback_();
             }
         }
@@ -2110,7 +2082,7 @@ class App {
         }
 
         for(const Option_p &opt : options_) {
-            if(opt->count() > 0 && !opt->get_callback_run()) {
+            if((*opt) && !opt->get_callback_run()) {
                 opt->run_callback();
             }
         }
@@ -2277,10 +2249,27 @@ class App {
 
     /// Process callbacks and such.
     void _process() {
-        _process_config_file();
-        _process_env();
+        CLI::FileError fe("ne");
+        bool caught_error{false};
+        try {
+            // the config file might generate a FileError but that should not be processed until later in the process
+            // to allow for help, version and other errors to generate first.
+            _process_config_file();
+            // process env shouldn't throw but no reason to process it if config generated an error
+            _process_env();
+        } catch(const CLI::FileError &fe2) {
+            fe = fe2;
+            caught_error = true;
+        }
+        // callbacks and help_flags can generate exceptions which should take priority over the config file error if one
+        // exists
         _process_callbacks();
         _process_help_flags();
+
+        if(caught_error) {
+            throw CLI::FileError(std::move(fe));
+        }
+
         _process_requirements();
     }
 
@@ -2349,7 +2338,7 @@ class App {
             _process_callbacks();
             _process_help_flags();
             _process_requirements();
-            run_callback();
+            run_callback(false, true);
         }
     }
 
@@ -2370,6 +2359,18 @@ class App {
         _process_extras();
     }
 
+    /// Internal function to parse a stream
+    void _parse_stream(std::istream &input) {
+        auto values = config_formatter_->from_config(input);
+        _parse_config(values);
+        increment_parsed();
+        _trigger_pre_parse(values.size());
+        _process();
+
+        // Throw error if any items are left over (depending on settings)
+        _process_extras();
+    }
+
     /// Parse one config param, return false if not found in any subcommand, remove if it is
     ///
     /// If this has more than one dot.separated.name, go into the subcommand matching it
@@ -2430,8 +2431,12 @@ class App {
             return false;
         }
 
-        if(!op->get_configurable())
+        if(!op->get_configurable()) {
+            if(get_allow_config_extras() == config_extras_mode::ignore_all) {
+                return false;
+            }
             throw ConfigError::NotConfigurable(item.fullname());
+        }
 
         if(op->empty()) {
             // Flag parsing
@@ -2749,6 +2754,9 @@ class App {
                 op->add_result(std::string{});
             }
         }
+        if(op->get_trigger_on_parse() && op->current_option_state_ == Option::option_state::callback_run) {
+            op->clear();
+        }
         int min_num = (std::min)(op->get_type_size_min(), op->get_items_expected_min());
         int max_num = op->get_items_expected_max();
         // check container like options to limit the argument size to a single type if the allow_extra_flags argument is
@@ -2821,7 +2829,9 @@ class App {
         if(min_num > 0 && op->get_type_size_max() != min_num && (collected % op->get_type_size_max()) != 0) {
             op->add_result(std::string{});
         }
-
+        if(op->get_trigger_on_parse()) {
+            op->run_callback();
+        }
         if(!rest.empty()) {
             rest = "-" + rest;
             args.push_back(rest);
diff --git a/packages/CLI11/include/CLI/CLI.hpp b/packages/CLI11/include/CLI/CLI.hpp
index 98fca5488..990ba4078 100644
--- a/packages/CLI11/include/CLI/CLI.hpp
+++ b/packages/CLI11/include/CLI/CLI.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/Config.hpp b/packages/CLI11/include/CLI/Config.hpp
index 725872dca..57944ecae 100644
--- a/packages/CLI11/include/CLI/Config.hpp
+++ b/packages/CLI11/include/CLI/Config.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -23,9 +23,9 @@ namespace CLI {
 // [CLI11:config_hpp:verbatim]
 namespace detail {
 
-inline std::string convert_arg_for_ini(const std::string &arg) {
+inline std::string convert_arg_for_ini(const std::string &arg, char stringQuote = '"', char characterQuote = '\'') {
     if(arg.empty()) {
-        return std::string(2, '"');
+        return std::string(2, stringQuote);
     }
     // some specifically supported strings
     if(arg == "true" || arg == "false" || arg == "nan" || arg == "inf") {
@@ -40,7 +40,7 @@ inline std::string convert_arg_for_ini(const std::string &arg) {
     }
     // just quote a single non numeric character
     if(arg.size() == 1) {
-        return std::string("'") + arg + '\'';
+        return std::string(1, characterQuote) + arg + characterQuote;
     }
     // handle hex, binary or octal arguments
     if(arg.front() == '0') {
@@ -60,16 +60,20 @@ inline std::string convert_arg_for_ini(const std::string &arg) {
             }
         }
     }
-    if(arg.find_first_of('"') == std::string::npos) {
-        return std::string("\"") + arg + '"';
+    if(arg.find_first_of(stringQuote) == std::string::npos) {
+        return std::string(1, stringQuote) + arg + stringQuote;
     } else {
-        return std::string("'") + arg + '\'';
+        return characterQuote + arg + characterQuote;
     }
 }
 
 /// Comma separated join, adds quotes if needed
-inline std::string
-ini_join(const std::vector<std::string> &args, char sepChar = ',', char arrayStart = '[', char arrayEnd = ']') {
+inline std::string ini_join(const std::vector<std::string> &args,
+                            char sepChar = ',',
+                            char arrayStart = '[',
+                            char arrayEnd = ']',
+                            char stringQuote = '"',
+                            char characterQuote = '\'') {
     std::string joined;
     if(args.size() > 1 && arrayStart != '\0') {
         joined.push_back(arrayStart);
@@ -82,7 +86,7 @@ ini_join(const std::vector<std::string> &args, char sepChar = ',', char arraySta
                 joined.push_back(' ');
             }
         }
-        joined.append(convert_arg_for_ini(arg));
+        joined.append(convert_arg_for_ini(arg, stringQuote, characterQuote));
     }
     if(args.size() > 1 && arrayEnd != '\0') {
         joined.push_back(arrayEnd);
@@ -90,17 +94,17 @@ ini_join(const std::vector<std::string> &args, char sepChar = ',', char arraySta
     return joined;
 }
 
-inline std::vector<std::string> generate_parents(const std::string &section, std::string &name) {
+inline std::vector<std::string> generate_parents(const std::string &section, std::string &name, char parentSeparator) {
     std::vector<std::string> parents;
     if(detail::to_lower(section) != "default") {
-        if(section.find('.') != std::string::npos) {
-            parents = detail::split(section, '.');
+        if(section.find(parentSeparator) != std::string::npos) {
+            parents = detail::split(section, parentSeparator);
         } else {
             parents = {section};
         }
     }
-    if(name.find('.') != std::string::npos) {
-        std::vector<std::string> plist = detail::split(name, '.');
+    if(name.find(parentSeparator) != std::string::npos) {
+        std::vector<std::string> plist = detail::split(name, parentSeparator);
         name = plist.back();
         detail::remove_quotes(name);
         plist.pop_back();
@@ -115,10 +119,11 @@ inline std::vector<std::string> generate_parents(const std::string &section, std
 }
 
 /// assuming non default segments do a check on the close and open of the segments in a configItem structure
-inline void checkParentSegments(std::vector<ConfigItem> &output, const std::string &currentSection) {
+inline void
+checkParentSegments(std::vector<ConfigItem> &output, const std::string &currentSection, char parentSeparator) {
 
     std::string estring;
-    auto parents = detail::generate_parents(currentSection, estring);
+    auto parents = detail::generate_parents(currentSection, estring, parentSeparator);
     if(!output.empty() && output.back().name == "--") {
         std::size_t msize = (parents.size() > 1U) ? parents.size() : 2;
         while(output.back().parents.size() >= msize) {
@@ -166,43 +171,53 @@ inline void checkParentSegments(std::vector<ConfigItem> &output, const std::stri
 
 inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) const {
     std::string line;
-    std::string section = "default";
-
+    std::string currentSection = "default";
+    std::string previousSection = "default";
     std::vector<ConfigItem> output;
     bool isDefaultArray = (arrayStart == '[' && arrayEnd == ']' && arraySeparator == ',');
     bool isINIArray = (arrayStart == '\0' || arrayStart == ' ') && arrayStart == arrayEnd;
+    bool inSection{false};
     char aStart = (isINIArray) ? '[' : arrayStart;
     char aEnd = (isINIArray) ? ']' : arrayEnd;
     char aSep = (isINIArray && arraySeparator == ' ') ? ',' : arraySeparator;
-
+    int currentSectionIndex{0};
     while(getline(input, line)) {
         std::vector<std::string> items_buffer;
         std::string name;
 
         detail::trim(line);
         std::size_t len = line.length();
-        if(len > 1 && line.front() == '[' && line.back() == ']') {
-            if(section != "default") {
+        // lines have to be at least 3 characters to have any meaning to CLI just skip the rest
+        if(len < 3) {
+            continue;
+        }
+        if(line.front() == '[' && line.back() == ']') {
+            if(currentSection != "default") {
                 // insert a section end which is just an empty items_buffer
                 output.emplace_back();
-                output.back().parents = detail::generate_parents(section, name);
+                output.back().parents = detail::generate_parents(currentSection, name, parentSeparatorChar);
                 output.back().name = "--";
             }
-            section = line.substr(1, len - 2);
+            currentSection = line.substr(1, len - 2);
             // deal with double brackets for TOML
-            if(section.size() > 1 && section.front() == '[' && section.back() == ']') {
-                section = section.substr(1, section.size() - 2);
+            if(currentSection.size() > 1 && currentSection.front() == '[' && currentSection.back() == ']') {
+                currentSection = currentSection.substr(1, currentSection.size() - 2);
             }
-            if(detail::to_lower(section) == "default") {
-                section = "default";
+            if(detail::to_lower(currentSection) == "default") {
+                currentSection = "default";
             } else {
-                detail::checkParentSegments(output, section);
+                detail::checkParentSegments(output, currentSection, parentSeparatorChar);
+            }
+            inSection = false;
+            if(currentSection == previousSection) {
+                ++currentSectionIndex;
+            } else {
+                currentSectionIndex = 0;
+                previousSection = currentSection;
             }
             continue;
         }
-        if(len == 0) {
-            continue;
-        }
+
         // comment lines
         if(line.front() == ';' || line.front() == '#' || line.front() == commentChar) {
             continue;
@@ -213,6 +228,11 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons
         if(pos != std::string::npos) {
             name = detail::trim_copy(line.substr(0, pos));
             std::string item = detail::trim_copy(line.substr(pos + 1));
+            auto cloc = item.find(commentChar);
+            if(cloc != std::string::npos) {
+                item.erase(cloc, std::string::npos);
+                detail::trim(item);
+            }
             if(item.size() > 1 && item.front() == aStart) {
                 for(std::string multiline; item.back() != aEnd && std::getline(input, multiline);) {
                     detail::trim(multiline);
@@ -228,9 +248,15 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons
             }
         } else {
             name = detail::trim_copy(line);
+            auto cloc = name.find(commentChar);
+            if(cloc != std::string::npos) {
+                name.erase(cloc, std::string::npos);
+                detail::trim(name);
+            }
+
             items_buffer = {"true"};
         }
-        if(name.find('.') == std::string::npos) {
+        if(name.find(parentSeparatorChar) == std::string::npos) {
             detail::remove_quotes(name);
         }
         // clean up quotes on the items
@@ -238,8 +264,20 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons
             detail::remove_quotes(it);
         }
 
-        std::vector<std::string> parents = detail::generate_parents(section, name);
-
+        std::vector<std::string> parents = detail::generate_parents(currentSection, name, parentSeparatorChar);
+        if(parents.size() > maximumLayers) {
+            continue;
+        }
+        if(!configSection.empty() && !inSection) {
+            if(parents.empty() || parents.front() != configSection) {
+                continue;
+            }
+            if(configIndex >= 0 && currentSectionIndex != configIndex) {
+                continue;
+            }
+            parents.erase(parents.begin());
+            inSection = true;
+        }
         if(!output.empty() && name == output.back().name && parents == output.back().parents) {
             output.back().inputs.insert(output.back().inputs.end(), items_buffer.begin(), items_buffer.end());
         } else {
@@ -249,11 +287,11 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons
             output.back().inputs = std::move(items_buffer);
         }
     }
-    if(section != "default") {
+    if(currentSection != "default") {
         // insert a section end which is just an empty items_buffer
         std::string ename;
         output.emplace_back();
-        output.back().parents = detail::generate_parents(section, ename);
+        output.back().parents = detail::generate_parents(currentSection, ename, parentSeparatorChar);
         output.back().name = "--";
         while(output.back().parents.size() > 1) {
             output.push_back(output.back());
@@ -273,8 +311,8 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
     std::vector<std::string> groups = app->get_groups();
     bool defaultUsed = false;
     groups.insert(groups.begin(), std::string("Options"));
-    if(write_description) {
-        out << commentLead << app->get_description() << '\n';
+    if(write_description && (app->get_configurable() || app->get_parent() == nullptr || app->get_name().empty())) {
+        out << commentLead << detail::fix_newlines(commentLead, app->get_description()) << '\n';
     }
     for(auto &group : groups) {
         if(group == "Options" || group.empty()) {
@@ -296,13 +334,16 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
                     }
                 }
                 std::string name = prefix + opt->get_single_name();
-                std::string value = detail::ini_join(opt->reduced_results(), arraySeparator, arrayStart, arrayEnd);
+                std::string value = detail::ini_join(
+                    opt->reduced_results(), arraySeparator, arrayStart, arrayEnd, stringQuote, characterQuote);
 
                 if(value.empty() && default_also) {
                     if(!opt->get_default_str().empty()) {
-                        value = detail::convert_arg_for_ini(opt->get_default_str());
+                        value = detail::convert_arg_for_ini(opt->get_default_str(), stringQuote, characterQuote);
                     } else if(opt->get_expected_min() == 0) {
                         value = "false";
+                    } else if(opt->get_run_callback_for_default()) {
+                        value = "\"\"";  // empty string default value
                     }
                 }
 
@@ -332,17 +373,18 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
                 if(!prefix.empty() || app->get_parent() == nullptr) {
                     out << '[' << prefix << subcom->get_name() << "]\n";
                 } else {
-                    std::string subname = app->get_name() + "." + subcom->get_name();
+                    std::string subname = app->get_name() + parentSeparatorChar + subcom->get_name();
                     auto p = app->get_parent();
                     while(p->get_parent() != nullptr) {
-                        subname = p->get_name() + "." + subname;
+                        subname = p->get_name() + parentSeparatorChar + subname;
                         p = p->get_parent();
                     }
                     out << '[' << subname << "]\n";
                 }
                 out << to_config(subcom, default_also, write_description, "");
             } else {
-                out << to_config(subcom, default_also, write_description, prefix + subcom->get_name() + ".");
+                out << to_config(
+                    subcom, default_also, write_description, prefix + subcom->get_name() + parentSeparatorChar);
             }
         }
     }
diff --git a/packages/CLI11/include/CLI/ConfigFwd.hpp b/packages/CLI11/include/CLI/ConfigFwd.hpp
index 2d9f9a39c..ef2ac345f 100644
--- a/packages/CLI11/include/CLI/ConfigFwd.hpp
+++ b/packages/CLI11/include/CLI/ConfigFwd.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -87,6 +87,18 @@ class ConfigBase : public Config {
     char arraySeparator = ',';
     /// the character used separate the name from the value
     char valueDelimiter = '=';
+    /// the character to use around strings
+    char stringQuote = '"';
+    /// the character to use around single characters
+    char characterQuote = '\'';
+    /// the maximum number of layers to allow
+    uint8_t maximumLayers{255};
+    /// the separator used to separator parent layers
+    char parentSeparatorChar{'.'};
+    /// Specify the configuration index to use for arrayed sections
+    int16_t configIndex{-1};
+    /// Specify the configuration section that should be used
+    std::string configSection{};
 
   public:
     std::string
@@ -114,6 +126,41 @@ class ConfigBase : public Config {
         valueDelimiter = vSep;
         return this;
     }
+    /// Specify the quote characters used around strings and characters
+    ConfigBase *quoteCharacter(char qString, char qChar) {
+        stringQuote = qString;
+        characterQuote = qChar;
+        return this;
+    }
+    /// Specify the maximum number of parents
+    ConfigBase *maxLayers(uint8_t layers) {
+        maximumLayers = layers;
+        return this;
+    }
+    /// Specify the separator to use for parent layers
+    ConfigBase *parentSeparator(char sep) {
+        parentSeparatorChar = sep;
+        return this;
+    }
+    /// get a reference to the configuration section
+    std::string &sectionRef() { return configSection; }
+    /// get the section
+    const std::string &section() const { return configSection; }
+    /// specify a particular section of the configuration file to use
+    ConfigBase *section(const std::string &sectionName) {
+        configSection = sectionName;
+        return this;
+    }
+
+    /// get a reference to the configuration index
+    int16_t &indexRef() { return configIndex; }
+    /// get the section index
+    int16_t index() const { return configIndex; }
+    /// specify a particular index in the section to use (-1) for all sections to use
+    ConfigBase *index(int16_t sectionIndex) {
+        configIndex = sectionIndex;
+        return this;
+    }
 };
 
 /// the default Config is the TOML file format
diff --git a/packages/CLI11/include/CLI/Error.hpp b/packages/CLI11/include/CLI/Error.hpp
index e6a832573..de3122bb4 100644
--- a/packages/CLI11/include/CLI/Error.hpp
+++ b/packages/CLI11/include/CLI/Error.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/Formatter.hpp b/packages/CLI11/include/CLI/Formatter.hpp
index cb9e92a57..e45aa25d9 100644
--- a/packages/CLI11/include/CLI/Formatter.hpp
+++ b/packages/CLI11/include/CLI/Formatter.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/FormatterFwd.hpp b/packages/CLI11/include/CLI/FormatterFwd.hpp
index 6908d4644..728926c0f 100644
--- a/packages/CLI11/include/CLI/FormatterFwd.hpp
+++ b/packages/CLI11/include/CLI/FormatterFwd.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/Macros.hpp b/packages/CLI11/include/CLI/Macros.hpp
index 778fec7dc..f228c918c 100644
--- a/packages/CLI11/include/CLI/Macros.hpp
+++ b/packages/CLI11/include/CLI/Macros.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -8,7 +8,7 @@
 
 // [CLI11:macros_hpp:verbatim]
 
-// The following version macro is very similar to the one in PyBind11
+// The following version macro is very similar to the one in pybind11
 #if !(defined(_MSC_VER) && __cplusplus == 199711L) && !defined(__INTEL_COMPILER)
 #if __cplusplus >= 201402L
 #define CLI11_CPP14
diff --git a/packages/CLI11/include/CLI/Option.hpp b/packages/CLI11/include/CLI/Option.hpp
index f09f61f97..616cd120c 100644
--- a/packages/CLI11/include/CLI/Option.hpp
+++ b/packages/CLI11/include/CLI/Option.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -94,6 +94,9 @@ template <typename CRTP> class OptionBase {
 
     /// Changes the group membership
     CRTP *group(const std::string &name) {
+        if(!detail::valid_alias_name_string(name)) {
+            throw IncorrectConstruction("Group names may not contain newlines or null characters");
+        }
         group_ = name;
         return static_cast<CRTP *>(this);
     }
@@ -337,6 +340,10 @@ class Option : public OptionBase<Option> {
     bool run_callback_for_default_{false};
     /// flag indicating a separator needs to be injected after each argument call
     bool inject_separator_{false};
+    /// flag indicating that the option should trigger the validation and callback chain on each result when loaded
+    bool trigger_on_result_{false};
+    /// flag indicating that the option should force the callback regardless if any results present
+    bool force_callback_{false};
     ///@}
 
     /// Making an option by hand is not defined, it must be made by the App class
@@ -358,8 +365,8 @@ class Option : public OptionBase<Option> {
     /// True if the option was not passed
     bool empty() const { return results_.empty(); }
 
-    /// This class is true if option is passed.
-    explicit operator bool() const { return !empty(); }
+    /// This bool operator returns true if any arguments were passed or the option callback is forced
+    explicit operator bool() const { return !empty() || force_callback_; }
 
     /// Clear the parsed results (mostly for testing)
     void clear() {
@@ -420,6 +427,21 @@ class Option : public OptionBase<Option> {
     }
     /// Get the current value of allow extra args
     bool get_allow_extra_args() const { return allow_extra_args_; }
+    /// Set the value of trigger_on_parse which specifies that the option callback should be triggered on every parse
+    Option *trigger_on_parse(bool value = true) {
+        trigger_on_result_ = value;
+        return this;
+    }
+    /// The status of trigger on parse
+    bool get_trigger_on_parse() const { return trigger_on_result_; }
+
+    /// Set the value of force_callback
+    Option *force_callback(bool value = true) {
+        force_callback_ = value;
+        return this;
+    }
+    /// The status of force_callback
+    bool get_force_callback() const { return force_callback_; }
 
     /// Set the value of run_callback_for_default which controls whether the callback function should be called to set
     /// the default This is controlled automatically but could be manipulated by the user.
@@ -666,7 +688,7 @@ class Option : public OptionBase<Option> {
     /// The maximum number of arguments the option expects
     int get_type_size_max() const { return type_size_max_; }
 
-    /// The number of arguments the option expects
+    /// Return the inject_separator flag
     int get_inject_separator() const { return inject_separator_; }
 
     /// The environment variable associated to this value
@@ -818,7 +840,9 @@ class Option : public OptionBase<Option> {
 
     /// Process the callback
     void run_callback() {
-
+        if(force_callback_ && results_.empty()) {
+            add_result(default_str_);
+        }
         if(current_option_state_ == option_state::parsing) {
             _validate_results(results_);
             current_option_state_ = option_state::validated;
@@ -974,10 +998,10 @@ class Option : public OptionBase<Option> {
 
     /// Puts a result at the end
     Option *add_result(std::vector<std::string> s) {
+        current_option_state_ = option_state::parsing;
         for(auto &str : s) {
             _add_result(std::move(str), results_);
         }
-        current_option_state_ = option_state::parsing;
         return this;
     }
 
@@ -1136,7 +1160,8 @@ class Option : public OptionBase<Option> {
         results_.clear();
         try {
             add_result(val_str);
-            if(run_callback_for_default_) {
+            // if trigger_on_result_ is set the callback already ran
+            if(run_callback_for_default_ && !trigger_on_result_) {
                 run_callback();  // run callback sets the state we need to reset it again
                 current_option_state_ = option_state::parsing;
             } else {
diff --git a/packages/CLI11/include/CLI/Split.hpp b/packages/CLI11/include/CLI/Split.hpp
index 36c953de8..83ef572c1 100644
--- a/packages/CLI11/include/CLI/Split.hpp
+++ b/packages/CLI11/include/CLI/Split.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/StringTools.hpp b/packages/CLI11/include/CLI/StringTools.hpp
index 090445e5b..4718aedd9 100644
--- a/packages/CLI11/include/CLI/StringTools.hpp
+++ b/packages/CLI11/include/CLI/StringTools.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -157,6 +157,22 @@ inline std::string &remove_quotes(std::string &str) {
     return str;
 }
 
+/// Add a leader to the beginning of all new lines (nothing is added
+/// at the start of the first line). `"; "` would be for ini files
+///
+/// Can't use Regex, or this would be a subs.
+inline std::string fix_newlines(const std::string &leader, std::string input) {
+    std::string::size_type n = 0;
+    while(n != std::string::npos && n < input.size()) {
+        n = input.find('\n', n);
+        if(n != std::string::npos) {
+            input = input.substr(0, n + 1) + leader + input.substr(n + 1);
+            n += leader.size();
+        }
+    }
+    return input;
+}
+
 /// Make a copy of the string and then trim it, any filter string can be used (any char in string is filtered)
 inline std::string trim_copy(const std::string &str, const std::string &filter) {
     std::string s = str;
@@ -191,7 +207,7 @@ inline std::ostream &format_aliases(std::ostream &out, const std::vector<std::st
             } else {
                 front = false;
             }
-            out << alias;
+            out << detail::fix_newlines("              ", alias);
         }
         out << "\n";
     }
@@ -199,23 +215,35 @@ inline std::ostream &format_aliases(std::ostream &out, const std::vector<std::st
 }
 
 /// Verify the first character of an option
-template <typename T> bool valid_first_char(T c) {
-    return std::isalnum(c, std::locale()) || c == '_' || c == '?' || c == '@';
-}
+/// - is a trigger character, ! has special meaning and new lines would just be annoying to deal with
+template <typename T> bool valid_first_char(T c) { return ((c != '-') && (c != '!') && (c != ' ') && c != '\n'); }
 
 /// Verify following characters of an option
-template <typename T> bool valid_later_char(T c) { return valid_first_char(c) || c == '.' || c == '-'; }
+template <typename T> bool valid_later_char(T c) {
+    // = and : are value separators, { has special meaning for option defaults,
+    // and \n would just be annoying to deal with in many places allowing space here has too much potential for
+    // inadvertent entry errors and bugs
+    return ((c != '=') && (c != ':') && (c != '{') && (c != ' ') && c != '\n');
+}
 
-/// Verify an option name
+/// Verify an option/subcommand name
 inline bool valid_name_string(const std::string &str) {
-    if(str.empty() || !valid_first_char(str[0]))
+    if(str.empty() || !valid_first_char(str[0])) {
         return false;
-    for(auto c : str.substr(1))
-        if(!valid_later_char(c))
+    }
+    auto e = str.end();
+    for(auto c = str.begin() + 1; c != e; ++c)
+        if(!valid_later_char(*c))
             return false;
     return true;
 }
 
+/// Verify an app name
+inline bool valid_alias_name_string(const std::string &str) {
+    static const std::string badChars(std::string("\n") + '\0');
+    return (str.find_first_of(badChars) == std::string::npos);
+}
+
 /// check if a string is a container segment separator (empty or "%%")
 inline bool is_separator(const std::string &str) {
     static const std::string sep("%%");
@@ -260,7 +288,7 @@ inline bool has_default_flag_values(const std::string &flags) {
 }
 
 inline void remove_default_flag_values(std::string &flags) {
-    auto loc = flags.find_first_of('{');
+    auto loc = flags.find_first_of('{', 2);
     while(loc != std::string::npos) {
         auto finish = flags.find_first_of("},", loc + 1);
         if((finish != std::string::npos) && (flags[finish] == '}')) {
@@ -367,22 +395,6 @@ inline std::vector<std::string> split_up(std::string str, char delimiter = '\0')
     return output;
 }
 
-/// Add a leader to the beginning of all new lines (nothing is added
-/// at the start of the first line). `"; "` would be for ini files
-///
-/// Can't use Regex, or this would be a subs.
-inline std::string fix_newlines(const std::string &leader, std::string input) {
-    std::string::size_type n = 0;
-    while(n != std::string::npos && n < input.size()) {
-        n = input.find('\n', n);
-        if(n != std::string::npos) {
-            input = input.substr(0, n + 1) + leader + input.substr(n + 1);
-            n += leader.size();
-        }
-    }
-    return input;
-}
-
 /// This function detects an equal or colon followed by an escaped quote after an argument
 /// then modifies the string to replace the equality with a space.  This is needed
 /// to allow the split up function to work properly and is intended to be used with the find_and_modify function
diff --git a/packages/CLI11/include/CLI/Timer.hpp b/packages/CLI11/include/CLI/Timer.hpp
index 69728b7dc..429ca026c 100644
--- a/packages/CLI11/include/CLI/Timer.hpp
+++ b/packages/CLI11/include/CLI/Timer.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/include/CLI/TypeTools.hpp b/packages/CLI11/include/CLI/TypeTools.hpp
index be0e89ab6..2b87ec60a 100644
--- a/packages/CLI11/include/CLI/TypeTools.hpp
+++ b/packages/CLI11/include/CLI/TypeTools.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -1059,7 +1059,7 @@ bool lexical_cast(const std::string &input, T &output) {
     }
     // LCOV_EXCL_START
     // This version of cast is only used for odd cases in an older compilers the fail over
-    // from_stream is tested elsewhere an not relevent for coverage here
+    // from_stream is tested elsewhere an not relevant for coverage here
     return from_stream(input, output);
     // LCOV_EXCL_STOP
 }
diff --git a/packages/CLI11/include/CLI/Validators.hpp b/packages/CLI11/include/CLI/Validators.hpp
index 90b590f6b..3c8b2f420 100644
--- a/packages/CLI11/include/CLI/Validators.hpp
+++ b/packages/CLI11/include/CLI/Validators.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -467,35 +467,35 @@ class Range : public Validator {
     /// Note that the constructor is templated, but the struct is not, so C++17 is not
     /// needed to provide nice syntax for Range(a,b).
     template <typename T>
-    Range(T min, T max, const std::string &validator_name = std::string{}) : Validator(validator_name) {
+    Range(T min_val, T max_val, const std::string &validator_name = std::string{}) : Validator(validator_name) {
         if(validator_name.empty()) {
             std::stringstream out;
-            out << detail::type_name<T>() << " in [" << min << " - " << max << "]";
+            out << detail::type_name<T>() << " in [" << min_val << " - " << max_val << "]";
             description(out.str());
         }
 
-        func_ = [min, max](std::string &input) {
+        func_ = [min_val, max_val](std::string &input) {
             T val;
             bool converted = detail::lexical_cast(input, val);
-            if((!converted) || (val < min || val > max))
-                return std::string("Value ") + input + " not in range " + std::to_string(min) + " to " +
-                       std::to_string(max);
+            if((!converted) || (val < min_val || val > max_val))
+                return std::string("Value ") + input + " not in range " + std::to_string(min_val) + " to " +
+                       std::to_string(max_val);
 
-            return std::string();
+            return std::string{};
         };
     }
 
     /// Range of one value is 0 to value
     template <typename T>
-    explicit Range(T max, const std::string &validator_name = std::string{})
-        : Range(static_cast<T>(0), max, validator_name) {}
+    explicit Range(T max_val, const std::string &validator_name = std::string{})
+        : Range(static_cast<T>(0), max_val, validator_name) {}
 };
 
 /// Check for a non negative number
-const Range NonNegativeNumber(std::numeric_limits<double>::max(), "NONNEGATIVE");
+const Range NonNegativeNumber((std::numeric_limits<double>::max)(), "NONNEGATIVE");
 
 /// Check for a positive valued number (val>0.0), min() her is the smallest positive number
-const Range PositiveNumber(std::numeric_limits<double>::min(), std::numeric_limits<double>::max(), "POSITIVE");
+const Range PositiveNumber((std::numeric_limits<double>::min)(), (std::numeric_limits<double>::max)(), "POSITIVE");
 
 /// Produce a bounded range (factory). Min and max are inclusive.
 class Bound : public Validator {
@@ -504,28 +504,28 @@ class Bound : public Validator {
     ///
     /// Note that the constructor is templated, but the struct is not, so C++17 is not
     /// needed to provide nice syntax for Range(a,b).
-    template <typename T> Bound(T min, T max) {
+    template <typename T> Bound(T min_val, T max_val) {
         std::stringstream out;
-        out << detail::type_name<T>() << " bounded to [" << min << " - " << max << "]";
+        out << detail::type_name<T>() << " bounded to [" << min_val << " - " << max_val << "]";
         description(out.str());
 
-        func_ = [min, max](std::string &input) {
+        func_ = [min_val, max_val](std::string &input) {
             T val;
             bool converted = detail::lexical_cast(input, val);
             if(!converted) {
                 return std::string("Value ") + input + " could not be converted";
             }
-            if(val < min)
-                input = detail::to_string(min);
-            else if(val > max)
-                input = detail::to_string(max);
+            if(val < min_val)
+                input = detail::to_string(min_val);
+            else if(val > max_val)
+                input = detail::to_string(max_val);
 
             return std::string{};
         };
     }
 
     /// Range of one value is 0 to value
-    template <typename T> explicit Bound(T max) : Bound(static_cast<T>(0), max) {}
+    template <typename T> explicit Bound(T max_val) : Bound(static_cast<T>(0), max_val) {}
 };
 
 namespace detail {
@@ -1100,12 +1100,35 @@ inline std::pair<std::string, std::string> split_program_name(std::string comman
         if(esp == std::string::npos) {
             // if we have reached the end and haven't found a valid file just assume the first argument is the
             // program name
-            esp = commandline.find_first_of(' ', 1);
+            if(commandline[0] == '"' || commandline[0] == '\'' || commandline[0] == '`') {
+                bool embeddedQuote = false;
+                auto keyChar = commandline[0];
+                auto end = commandline.find_first_of(keyChar, 1);
+                while((end != std::string::npos) && (commandline[end - 1] == '\\')) {  // deal with escaped quotes
+                    end = commandline.find_first_of(keyChar, end + 1);
+                    embeddedQuote = true;
+                }
+                if(end != std::string::npos) {
+                    vals.first = commandline.substr(1, end - 1);
+                    esp = end + 1;
+                    if(embeddedQuote) {
+                        vals.first = find_and_replace(vals.first, std::string("\\") + keyChar, std::string(1, keyChar));
+                    }
+                } else {
+                    esp = commandline.find_first_of(' ', 1);
+                }
+            } else {
+                esp = commandline.find_first_of(' ', 1);
+            }
+
             break;
         }
     }
-    vals.first = commandline.substr(0, esp);
-    rtrim(vals.first);
+    if(vals.first.empty()) {
+        vals.first = commandline.substr(0, esp);
+        rtrim(vals.first);
+    }
+
     // strip the program name
     vals.second = (esp != std::string::npos) ? commandline.substr(esp + 1) : std::string{};
     ltrim(vals.second);
diff --git a/packages/CLI11/include/CLI/Version.hpp b/packages/CLI11/include/CLI/Version.hpp
index dde959890..c989ae86d 100644
--- a/packages/CLI11/include/CLI/Version.hpp
+++ b/packages/CLI11/include/CLI/Version.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -8,9 +8,9 @@
 
 // [CLI11:version_hpp:verbatim]
 
-#define CLI11_VERSION_MAJOR 1
-#define CLI11_VERSION_MINOR 9
+#define CLI11_VERSION_MAJOR 2
+#define CLI11_VERSION_MINOR 1
 #define CLI11_VERSION_PATCH 1
-#define CLI11_VERSION "1.9.1"
+#define CLI11_VERSION "2.1.1"
 
 // [CLI11:version_hpp:end]
diff --git a/packages/CLI11/scripts/MakeSingleHeader.py b/packages/CLI11/scripts/MakeSingleHeader.py
index 78714ffb5..42e0ee7a9 100755
--- a/packages/CLI11/scripts/MakeSingleHeader.py
+++ b/packages/CLI11/scripts/MakeSingleHeader.py
@@ -39,12 +39,20 @@ DIR = os.path.dirname(os.path.abspath(__file__))
 
 class HeaderGroups(dict):
     def __init__(self, tag):
+        """
+        A dictionary that also can read headers given a tag expression.
+
+        TODO: might have gone overboard on this one, could maybe be two functions.
+        """
         self.re_matcher = re.compile(
             tag_str.format(tag=tag), re.MULTILINE | re.DOTALL | re.VERBOSE
         )
         super(HeaderGroups, self).__init__()
 
     def read_header(self, filename):
+        """
+        Read a header file in and add items to the dict, based on the item's action.
+        """
         with open(filename) as f:
             inner = f.read()
 
@@ -67,12 +75,18 @@ class HeaderGroups(dict):
                 raise RuntimeError("Action not understood, must be verbatim or set")
 
     def post_process(self):
+        """
+        Turn sets into multiple line strings.
+        """
         for key in self:
             if isinstance(self[key], set):
                 self[key] = "\n".join(self[key])
 
 
-def MakeHeader(output, main_header, files, tag, namespace, macro=None, version=None):
+def make_header(output, main_header, files, tag, namespace, macro=None, version=None):
+    """
+    Makes a single header given a main header template and a list of files.
+    """
     groups = HeaderGroups(tag)
 
     # Set tag if possible to class variable
@@ -129,7 +143,7 @@ if __name__ == "__main__":
     parser.add_argument("--version", help="Include this version in the generated file")
     args = parser.parse_args()
 
-    MakeHeader(
+    make_header(
         args.output,
         args.main,
         args.files,
diff --git a/packages/CLI11/scripts/UpdateDownloadProj.py b/packages/CLI11/scripts/UpdateDownloadProj.py
deleted file mode 100755
index e20797f4f..000000000
--- a/packages/CLI11/scripts/UpdateDownloadProj.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import print_function, division
-
-from plumbum import local, cli, FG
-from plumbum.cmd import curl
-
-FILES = [
-    "https://raw.githubusercontent.com/Crascit/DownloadProject/master/DownloadProject.cmake",
-    "https://raw.githubusercontent.com/Crascit/DownloadProject/master/DownloadProject.CMakeLists.cmake.in",
-]
-
-DIR = local.path(__file__).dirname
-
-
-def download_file(path):
-    name = path.split("/")[-1]
-    (curl[path] > name) & FG
-
-
-class UpdateDownloadProj(cli.Application):
-    def main(self):
-        with local.cwd(DIR / "../cmake"):
-            for f in FILES:
-                download_file(f)
-
-
-if __name__ == "__main__":
-    UpdateDownloadProj()
diff --git a/packages/CLI11/scripts/mdlint_style.rb b/packages/CLI11/scripts/mdlint_style.rb
new file mode 100644
index 000000000..6fca85b1a
--- /dev/null
+++ b/packages/CLI11/scripts/mdlint_style.rb
@@ -0,0 +1,8 @@
+all
+
+exclude_rule 'MD013'  # Line length
+exclude_rule 'MD033'  # Inline HTML
+exclude_rule 'MD034'  # Bare URL (for now)
+
+rule 'MD026', punctuation: '.,;:!'  # Trailing punctuation in header (& in this case)
+rule 'MD029', style: :ordered
diff --git a/packages/CLI11/test_package/example.cpp b/packages/CLI11/test_package/example.cpp
index beb97fe7f..464cf7518 100644
--- a/packages/CLI11/test_package/example.cpp
+++ b/packages/CLI11/test_package/example.cpp
@@ -9,7 +9,7 @@ int main(int argc, char **argv) {
     CLI::App app("Some nice description");
 
     int x = 0;
-    app.add_option("-x", x, "an integer value", true /* show default */);
+    app.add_option("-x", x, "an integer value")->capture_default_str();
 
     bool flag;
     app.add_flag("-f,--flag", flag, "a flag option");
diff --git a/packages/CLI11/tests/AppTest.cpp b/packages/CLI11/tests/AppTest.cpp
index 6c3e71ced..d425b414c 100644
--- a/packages/CLI11/tests/AppTest.cpp
+++ b/packages/CLI11/tests/AppTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -127,6 +127,17 @@ TEST_CASE_METHOD(TApp, "DashedOptionsSingleString", "[app]") {
     CHECK(app.count("--that") == 2u);
 }
 
+TEST_CASE_METHOD(TApp, "StrangeFlagNames", "[app]") {
+    app.add_flag("-=");
+    app.add_flag("--t\tt");
+    app.add_flag("-{");
+    CHECK_THROWS_AS(app.add_flag("--t t"), CLI::ConstructionError);
+    args = {"-=", "--t\tt"};
+    run();
+    CHECK(app.count("-=") == 1u);
+    CHECK(app.count("--t\tt") == 1u);
+}
+
 TEST_CASE_METHOD(TApp, "RequireOptionsError", "[app]") {
     using Catch::Matchers::Contains;
 
@@ -582,6 +593,20 @@ TEST_CASE_METHOD(TApp, "SingleArgVector", "[app]") {
     CHECK("happy" == path);
 }
 
+TEST_CASE_METHOD(TApp, "StrangeOptionNames", "[app]") {
+    app.add_option("-:");
+    app.add_option("--t\tt");
+    app.add_option("--{}");
+    app.add_option("--:)");
+    CHECK_THROWS_AS(app.add_option("--t t"), CLI::ConstructionError);
+    args = {"-:)", "--{}", "5"};
+    run();
+    CHECK(app.count("-:") == 1u);
+    CHECK(app.count("--{}") == 1u);
+    CHECK(app["-:"]->as<char>() == ')');
+    CHECK(app["--{}"]->as<int>() == 5);
+}
+
 TEST_CASE_METHOD(TApp, "FlagLikeOption", "[app]") {
     bool val{false};
     auto opt = app.add_option("--flag", val)->type_size(0)->default_str("true");
@@ -809,7 +834,7 @@ TEST_CASE_METHOD(TApp, "TakeFirstOptMulti", "[app]") {
 
 TEST_CASE_METHOD(TApp, "ComplexOptMulti", "[app]") {
     std::complex<double> val;
-    app.add_complex("--long", val)->take_first()->allow_extra_args();
+    app.add_option("--long", val)->take_first()->allow_extra_args();
 
     args = {"--long", "1", "2", "3", "4"};
 
@@ -1933,7 +1958,6 @@ TEST_CASE_METHOD(TApp, "AllowExtrasArgModify", "[app]") {
     app.allow_extras();
     app.add_option("-f", v2);
     args = {"27", "-f", "45", "-x"};
-    auto cargs = args;
     app.parse(args);
     CHECK(std::vector<std::string>({"45", "-x"}) == args);
 
@@ -2219,7 +2243,7 @@ TEST_CASE_METHOD(TApp, "CustomUserSepParse3", "[app]") {
     CHECK(std::vector<int>({1, 2}) == vals);
     app.remove_option(opt);
 
-    app.add_option("--idx", vals, "", false)->delimiter(',');
+    app.add_option("--idx", vals)->delimiter(',');
     run();
     CHECK(std::vector<int>({1, 2}) == vals);
 }
@@ -2255,3 +2279,32 @@ TEST_CASE_METHOD(TApp, "CustomUserSepParse5", "[app]") {
     run();
     CHECK(std::vector<std::string>({"this", "is", "a", "test"}) == bar);
 }
+
+// #218
+TEST_CASE_METHOD(TApp, "logFormSingleDash", "[app]") {
+    bool verbose{false};
+    bool veryverbose{false};
+    bool veryveryverbose{false};
+    app.name("testargs");
+    app.allow_extras();
+    args = {"-v", "-vv", "-vvv"};
+    app.final_callback([&]() {
+        auto rem = app.remaining();
+        for(auto &arg : rem) {
+            if(arg == "-v") {
+                verbose = true;
+            }
+            if(arg == "-vv") {
+                veryverbose = true;
+            }
+            if(arg == "-vvv") {
+                veryveryverbose = true;
+            }
+        }
+    });
+    run();
+    CHECK(app.remaining().size() == 3U);
+    CHECK(verbose);
+    CHECK(veryverbose);
+    CHECK(veryveryverbose);
+}
diff --git a/packages/CLI11/tests/BoostOptionTypeTest.cpp b/packages/CLI11/tests/BoostOptionTypeTest.cpp
index 2110bcc65..7ed096cd1 100644
--- a/packages/CLI11/tests/BoostOptionTypeTest.cpp
+++ b/packages/CLI11/tests/BoostOptionTypeTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/CMakeLists.txt b/packages/CLI11/tests/CMakeLists.txt
index 4a86923f6..c322615f6 100644
--- a/packages/CLI11/tests/CMakeLists.txt
+++ b/packages/CLI11/tests/CMakeLists.txt
@@ -1,34 +1,35 @@
 list(APPEND CMAKE_MODULE_PATH "${CLI11_SOURCE_DIR}/cmake")
 
 if(CLI11_SANITIZERS)
-    message(STATUS "Using arsenm/sanitizers-cmake")
-    FetchContent_Declare(sanitizers
-        GIT_REPOSITORY https://github.com/arsenm/sanitizers-cmake.git
-        GIT_SHALLOW 1
-        GIT_TAG 99e159e)
+  message(STATUS "Using arsenm/sanitizers-cmake")
+  FetchContent_Declare(
+    sanitizers
+    GIT_REPOSITORY https://github.com/arsenm/sanitizers-cmake.git
+    GIT_SHALLOW 1
+    GIT_TAG 99e159e)
 
-    FetchContent_GetProperties(sanitizers)
+  FetchContent_GetProperties(sanitizers)
 
-    if (NOT sanitizers_POPULATED)
-        FetchContent_Populate(sanitizers)
-    endif()
+  if(NOT sanitizers_POPULATED)
+    FetchContent_Populate(sanitizers)
+  endif()
 
-    list(APPEND CMAKE_MODULE_PATH "${sanitizers_SOURCE_DIR}/cmake")
+  list(APPEND CMAKE_MODULE_PATH "${sanitizers_SOURCE_DIR}/cmake")
 
-    find_package(Sanitizers)
-    if(SANITIZE_ADDRESS)
-        message(STATUS "You might want to use \"${ASan_WRAPPER}\" to run your program")
-    endif()
+  find_package(Sanitizers)
+  if(SANITIZE_ADDRESS)
+    message(STATUS "You might want to use \"${ASan_WRAPPER}\" to run your program")
+  endif()
 else()
-    macro(add_sanitizers)
-    endmacro()
-endif()
+  macro(add_sanitizers)
 
+  endmacro()
+endif()
 
 # Add boost to test boost::optional (currently explicitly requested)"
 option(CLI11_BOOST "Turn on boost test (currently may fail with Boost 1.70)" OFF)
 if(CLI11_BOOST)
-    find_package(Boost 1.61 REQUIRED)
+  find_package(Boost 1.61 REQUIRED)
 endif()
 set(boost-optional-def $<$<BOOL:${Boost_FOUND}>:CLI11_BOOST_OPTIONAL>)
 
@@ -50,15 +51,14 @@ set(CLI11_TESTS
     StringParseTest
     ComplexTypeTest
     TrueFalseTest
-    OptionGroupTest
-    )
+    OptionGroupTest)
 
 if(WIN32)
-    list(APPEND CLI11_TESTS WindowsTest)
+  list(APPEND CLI11_TESTS WindowsTest)
 endif()
 
-if (Boost_FOUND)
-   list(APPEND CLI11_TESTS BoostOptionTypeTest)
+if(Boost_FOUND)
+  list(APPEND CLI11_TESTS BoostOptionTypeTest)
 endif()
 
 set(CLI11_MULTIONLY_TESTS TimerTest)
@@ -70,68 +70,64 @@ target_include_directories(catch_main PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
 # that would require changing the includes. FetchContent would be better, but
 # requires newer CMake.
 
-set(url https://github.com/philsquared/Catch/releases/download/v2.13.4/catch.hpp)
-file(DOWNLOAD ${url} "${CMAKE_CURRENT_BINARY_DIR}/catch.hpp" STATUS status EXPECTED_HASH SHA256=6e0fa3dd160891a01c1f3b34e8bcd6e0140abe08eca022e390027f27dec2050b)
+set(url https://github.com/philsquared/Catch/releases/download/v2.13.6/catch.hpp)
+file(
+  DOWNLOAD ${url} "${CMAKE_CURRENT_BINARY_DIR}/catch.hpp"
+  STATUS status
+  EXPECTED_HASH SHA256=681e7505a50887c9085539e5135794fc8f66d8e5de28eadf13a30978627b0f47)
 list(GET status 0 error)
 if(error)
-    message(FATAL_ERROR "Could not download ${url}")
+  message(FATAL_ERROR "Could not download ${url}")
 endif()
 target_include_directories(catch_main PUBLIC "${CMAKE_CURRENT_BINARY_DIR}")
 
 # Target must already exist
 macro(add_catch_test TESTNAME)
-    target_link_libraries(${TESTNAME} PUBLIC catch_main)
-
-    add_test(${TESTNAME} ${TESTNAME})
-    set_target_properties(${TESTNAME} PROPERTIES FOLDER "Tests")
-    if (CLI11_FORCE_LIBCXX)
-       set_property(TARGET ${T} APPEND_STRING
-         PROPERTY LINK_FLAGS -stdlib=libc++)
-     endif()
+  target_link_libraries(${TESTNAME} PUBLIC catch_main)
+
+  add_test(${TESTNAME} ${TESTNAME})
+  set_target_properties(${TESTNAME} PROPERTIES FOLDER "Tests")
+  if(CLI11_FORCE_LIBCXX)
+    set_property(
+      TARGET ${T}
+      APPEND_STRING
+      PROPERTY LINK_FLAGS -stdlib=libc++)
+  endif()
 endmacro()
 
 foreach(T IN LISTS CLI11_TESTS)
-    if(CLI11_CUDA_TESTS)
-        set_property(
-            SOURCE ${T}.cpp
-            PROPERTY LANGUAGE CUDA
-            )
-    endif()
-    add_executable(${T} ${T}.cpp ${CLI11_headers})
-    add_sanitizers(${T})
-    if(NOT CLI11_CUDA_TESTS)
-        target_link_libraries(${T} PRIVATE CLI11_warnings)
-    endif()
-    target_link_libraries(${T} PRIVATE CLI11)
-    add_catch_test(${T})
-
-    if(CLI11_SINGLE_FILE AND CLI11_SINGLE_FILE_TESTS)
-        add_executable(${T}_Single ${T}.cpp)
-        target_link_libraries(${T}_Single PRIVATE CLI11_SINGLE)
-        add_catch_test(${T}_Single)
-        set_property(TARGET ${T}_Single PROPERTY FOLDER "Tests Single File")
-    endif()
+  if(CLI11_CUDA_TESTS)
+    set_property(SOURCE ${T}.cpp PROPERTY LANGUAGE CUDA)
+  endif()
+  add_executable(${T} ${T}.cpp ${CLI11_headers})
+  add_sanitizers(${T})
+  if(NOT CLI11_CUDA_TESTS)
+    target_link_libraries(${T} PRIVATE CLI11_warnings)
+  endif()
+  target_link_libraries(${T} PRIVATE CLI11)
+  add_catch_test(${T})
+
+  if(CLI11_SINGLE_FILE AND CLI11_SINGLE_FILE_TESTS)
+    add_executable(${T}_Single ${T}.cpp)
+    target_link_libraries(${T}_Single PRIVATE CLI11_SINGLE)
+    add_catch_test(${T}_Single)
+    set_property(TARGET ${T}_Single PROPERTY FOLDER "Tests Single File")
+  endif()
 endforeach()
 
 foreach(T IN LISTS CLI11_MULTIONLY_TESTS)
-    add_executable(${T} ${T}.cpp ${CLI11_headers})
-    add_sanitizers(${T})
-    target_link_libraries(${T} PUBLIC CLI11)
-    add_catch_test(${T})
+  add_executable(${T} ${T}.cpp ${CLI11_headers})
+  add_sanitizers(${T})
+  target_link_libraries(${T} PUBLIC CLI11)
+  add_catch_test(${T})
 endforeach()
 
 # Add -Wno-deprecated-declarations to DeprecatedTest
-set(no-deprecated-declarations
-    $<$<CXX_COMPILER_ID:MSVC>:/wd4996>
-    $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-deprecated-declarations>
-    )
-target_compile_options(DeprecatedTest
-    PRIVATE
-    ${no-deprecated-declarations})
-if (TARGET DeprecatedTest_Single)
-    target_compile_options(DeprecatedTest_Single
-        PRIVATE
-        ${no-deprecated-declarations})
+set(no-deprecated-declarations $<$<CXX_COMPILER_ID:MSVC>:/wd4996>
+                               $<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wno-deprecated-declarations>)
+target_compile_options(DeprecatedTest PRIVATE ${no-deprecated-declarations})
+if(TARGET DeprecatedTest_Single)
+  target_compile_options(DeprecatedTest_Single PRIVATE ${no-deprecated-declarations})
 endif()
 
 # Link test (build error if inlines missing)
@@ -142,33 +138,38 @@ add_executable(link_test_2 link_test_2.cpp)
 target_link_libraries(link_test_2 PUBLIC CLI11 link_test_1)
 add_catch_test(link_test_2)
 if(CLI11_FORCE_LIBCXX)
-    set_property(TARGET link_test_1 APPEND_STRING
-        PROPERTY LINK_FLAGS -stdlib=libc++)
-    set_property(TARGET link_test_2 APPEND_STRING
-        PROPERTY LINK_FLAGS -stdlib=libc++)
+  set_property(
+    TARGET link_test_1
+    APPEND_STRING
+    PROPERTY LINK_FLAGS -stdlib=libc++)
+  set_property(
+    TARGET link_test_2
+    APPEND_STRING
+    PROPERTY LINK_FLAGS -stdlib=libc++)
 endif()
 
 # Add informational printout
 add_executable(informational informational.cpp)
 target_link_libraries(informational PUBLIC CLI11)
 if(CLI11_FORCE_LIBCXX)
-    set_property(TARGET informational APPEND_STRING
-        PROPERTY LINK_FLAGS -stdlib=libc++)
+  set_property(
+    TARGET informational
+    APPEND_STRING
+    PROPERTY LINK_FLAGS -stdlib=libc++)
 endif()
 
 # Force this to be in a standard location so CTest can find it
-set_target_properties(informational PROPERTIES
-    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
-    RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}"
-    RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}"
-    RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}"
-    RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_BINARY_DIR}"
-    )
+set_target_properties(
+  informational
+  PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+             RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}"
+             RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}"
+             RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${CMAKE_BINARY_DIR}"
+             RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${CMAKE_BINARY_DIR}")
 
 # Adding this printout to CTest
 file(WRITE "${PROJECT_BINARY_DIR}/CTestCustom.cmake"
-    "set(CTEST_CUSTOM_PRE_TEST \"${CMAKE_BINARY_DIR}/informational\")"
-)
+     "set(CTEST_CUSTOM_PRE_TEST \"${CMAKE_BINARY_DIR}/informational\")")
 
 target_compile_definitions(informational PRIVATE ${boost-optional-def})
 target_compile_definitions(OptionalTest PRIVATE ${boost-optional-def})
@@ -176,33 +177,33 @@ target_compile_definitions(OptionalTest PRIVATE ${boost-optional-def})
 message(STATUS "Boost libs=${Boost_INCLUDE_DIRS}")
 
 if(TARGET Boost::boost)
-    message(STATUS "including boost target")
-    target_link_libraries(informational PRIVATE Boost::boost)
-    target_link_libraries(OptionalTest PRIVATE Boost::boost)
-    target_link_libraries(BoostOptionTypeTest PRIVATE Boost::boost)
-    if(CLI11_SINGLE_FILE AND CLI11_SINGLE_FILE_TESTS)
-       target_link_libraries(OptionalTest_Single PRIVATE Boost::boost)
-       target_link_libraries(BoostOptionTypeTest_Single PRIVATE Boost::boost)
-    endif()
+  message(STATUS "including boost target")
+  target_link_libraries(informational PRIVATE Boost::boost)
+  target_link_libraries(OptionalTest PRIVATE Boost::boost)
+  target_link_libraries(BoostOptionTypeTest PRIVATE Boost::boost)
+  if(CLI11_SINGLE_FILE AND CLI11_SINGLE_FILE_TESTS)
+    target_link_libraries(OptionalTest_Single PRIVATE Boost::boost)
+    target_link_libraries(BoostOptionTypeTest_Single PRIVATE Boost::boost)
+  endif()
 elseif(BOOST_FOUND)
-message(STATUS "no boost target")
-    target_include_directories(informational PRIVATE ${Boost_INCLUDE_DIRS})
-    target_include_directories(OptionalTest PRIVATE ${Boost_INCLUDE_DIRS})
-    target_include_directories(BoostOptionTypeTest PRIVATE ${Boost_INCLUDE_DIRS})
-    if(CLI11_SINGLE_FILE AND CLI11_SINGLE_FILE_TESTS)
-        target_include_directories(OptionalTest_Single PRIVATE ${Boost_INCLUDE_DIRS})
-        target_include_directories(BoostOptionTypeTest_Single PRIVATE ${Boost_INCLUDE_DIRS})
-     endif()
+  message(STATUS "no boost target")
+  target_include_directories(informational PRIVATE ${Boost_INCLUDE_DIRS})
+  target_include_directories(OptionalTest PRIVATE ${Boost_INCLUDE_DIRS})
+  target_include_directories(BoostOptionTypeTest PRIVATE ${Boost_INCLUDE_DIRS})
+  if(CLI11_SINGLE_FILE AND CLI11_SINGLE_FILE_TESTS)
+    target_include_directories(OptionalTest_Single PRIVATE ${Boost_INCLUDE_DIRS})
+    target_include_directories(BoostOptionTypeTest_Single PRIVATE ${Boost_INCLUDE_DIRS})
+  endif()
 endif()
 
 if(CMAKE_BUILD_TYPE STREQUAL Coverage)
-    include(CodeCoverage)
-    setup_target_for_coverage(
-        NAME CLI11_coverage
-        EXECUTABLE ctest
-        DEPENDENCIES
-          ${CLI11_TESTS}
-          ${CLI11_MULTIONLY_TESTS}
-        )
+  include(CodeCoverage)
+  setup_target_for_coverage(
+    NAME
+    CLI11_coverage
+    EXECUTABLE
+    ctest
+    DEPENDENCIES
+    ${CLI11_TESTS}
+    ${CLI11_MULTIONLY_TESTS})
 endif()
-
diff --git a/packages/CLI11/tests/ComplexTypeTest.cpp b/packages/CLI11/tests/ComplexTypeTest.cpp
index b9a5d4e51..4806c544e 100644
--- a/packages/CLI11/tests/ComplexTypeTest.cpp
+++ b/packages/CLI11/tests/ComplexTypeTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/ConfigFileTest.cpp b/packages/CLI11/tests/ConfigFileTest.cpp
index 12fa88c10..61c066eed 100644
--- a/packages/CLI11/tests/ConfigFileTest.cpp
+++ b/packages/CLI11/tests/ConfigFileTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -535,6 +535,10 @@ TEST_CASE_METHOD(TApp, "IniRequiredNoDefault", "[config]") {
     int two{0};
     app.add_option("--two", two);
     REQUIRE_THROWS_AS(run(), CLI::FileError);
+    // test to make sure help still gets called correctly
+    // GitHub issue #533 https://github.com/CLIUtils/CLI11/issues/553
+    args = {"--help"};
+    REQUIRE_THROWS_AS(run(), CLI::CallForHelp);
 }
 
 TEST_CASE_METHOD(TApp, "IniNotRequiredNoDefault", "[config]") {
@@ -794,6 +798,114 @@ TEST_CASE_METHOD(TApp, "IniRequired", "[config]") {
     CHECK_THROWS_AS(run(), CLI::RequiredError);
 }
 
+TEST_CASE_METHOD(TApp, "IniInlineComment", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini, "", true);
+    app.config_formatter(std::make_shared<CLI::ConfigINI>());
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << std::endl;
+        out << "two=99 ; this is a two" << std::endl;
+        out << "three=3; this is a three" << std::endl;
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--one", one)->required();
+    app.add_option("--two", two)->required();
+    app.add_option("--three", three)->required();
+
+    args = {"--one=1"};
+
+    run();
+    CHECK(1 == one);
+    CHECK(99 == two);
+    CHECK(3 == three);
+
+    one = two = three = 0;
+    args = {"--one=1", "--two=2"};
+
+    CHECK_NOTHROW(run());
+    CHECK(1 == one);
+    CHECK(2 == two);
+    CHECK(3 == three);
+
+    args = {};
+
+    CHECK_THROWS_AS(run(), CLI::RequiredError);
+
+    args = {"--two=2"};
+
+    CHECK_THROWS_AS(run(), CLI::RequiredError);
+}
+
+TEST_CASE_METHOD(TApp, "TomlInlineComment", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini, "", true);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << std::endl;
+        out << "two=99 # this is a two" << std::endl;
+        out << "three=3# this is a three" << std::endl;
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--one", one)->required();
+    app.add_option("--two", two)->required();
+    app.add_option("--three", three)->required();
+
+    args = {"--one=1"};
+
+    run();
+    CHECK(1 == one);
+    CHECK(99 == two);
+    CHECK(3 == three);
+
+    one = two = three = 0;
+    args = {"--one=1", "--two=2"};
+
+    CHECK_NOTHROW(run());
+    CHECK(1 == one);
+    CHECK(2 == two);
+    CHECK(3 == three);
+
+    args = {};
+
+    CHECK_THROWS_AS(run(), CLI::RequiredError);
+
+    args = {"--two=2"};
+
+    CHECK_THROWS_AS(run(), CLI::RequiredError);
+}
+
+TEST_CASE_METHOD(TApp, "ConfigModifiers", "[config]") {
+
+    app.set_config("--config", "test.ini", "", true);
+
+    auto cfgptr = app.get_config_formatter_base();
+
+    cfgptr->section("test");
+    CHECK(cfgptr->section() == "test");
+
+    CHECK(cfgptr->sectionRef() == "test");
+    auto &sref = cfgptr->sectionRef();
+    sref = "this";
+    CHECK(cfgptr->section() == "this");
+
+    cfgptr->index(5);
+    CHECK(cfgptr->index() == 5);
+
+    CHECK(cfgptr->indexRef() == 5);
+    auto &iref = cfgptr->indexRef();
+    iref = 7;
+    CHECK(cfgptr->index() == 7);
+}
+
 TEST_CASE_METHOD(TApp, "IniVector", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
@@ -999,6 +1111,39 @@ TEST_CASE_METHOD(TApp, "IniLayered", "[config]") {
     CHECK(!*subcom);
 }
 
+TEST_CASE_METHOD(TApp, "IniLayeredStream", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << std::endl;
+        out << "val=1" << std::endl;
+        out << "[subcom]" << std::endl;
+        out << "val=2" << std::endl;
+        out << "subsubcom.val=3" << std::endl;
+    }
+
+    int one{0}, two{0}, three{0};
+    app.add_option("--val", one);
+    auto subcom = app.add_subcommand("subcom");
+    subcom->add_option("--val", two);
+    auto subsubcom = subcom->add_subcommand("subsubcom");
+    subsubcom->add_option("--val", three);
+
+    std::ifstream in{tmpini};
+    app.parse_from_stream(in);
+
+    CHECK(one == 1);
+    CHECK(two == 2);
+    CHECK(three == 3);
+
+    CHECK(0U == subcom->count());
+    CHECK(!*subcom);
+}
+
 TEST_CASE_METHOD(TApp, "IniLayeredDotSection", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
@@ -1030,6 +1175,45 @@ TEST_CASE_METHOD(TApp, "IniLayeredDotSection", "[config]") {
 
     CHECK(0U == subcom->count());
     CHECK(!*subcom);
+
+    three = 0;
+    // check maxlayers
+    app.get_config_formatter_base()->maxLayers(1);
+    run();
+    CHECK(three == 0);
+}
+
+TEST_CASE_METHOD(TApp, "IniLayeredCustomSectionSeparator", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << std::endl;
+        out << "val=1" << std::endl;
+        out << "[subcom]" << std::endl;
+        out << "val=2" << std::endl;
+        out << "[subcom|subsubcom]" << std::endl;
+        out << "val=3" << std::endl;
+    }
+    app.get_config_formatter_base()->parentSeparator('|');
+    int one{0}, two{0}, three{0};
+    app.add_option("--val", one);
+    auto subcom = app.add_subcommand("subcom");
+    subcom->add_option("--val", two);
+    auto subsubcom = subcom->add_subcommand("subsubcom");
+    subsubcom->add_option("--val", three);
+
+    run();
+
+    CHECK(one == 1);
+    CHECK(two == 2);
+    CHECK(three == 3);
+
+    CHECK(0U == subcom->count());
+    CHECK(!*subcom);
 }
 
 TEST_CASE_METHOD(TApp, "IniSubcommandConfigurable", "[config]") {
@@ -1107,6 +1291,130 @@ TEST_CASE_METHOD(TApp, "IniSubcommandConfigurablePreParse", "[config]") {
     CHECK(0U == subcom2->count());
 }
 
+TEST_CASE_METHOD(TApp, "IniSection", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+    app.get_config_formatter_base()->section("config");
+
+    {
+        std::ofstream out{tmpini};
+        out << "[config]" << std::endl;
+        out << "val=2" << std::endl;
+        out << "subsubcom.val=3" << std::endl;
+        out << "[default]" << std::endl;
+        out << "val=1" << std::endl;
+    }
+
+    int val{0};
+    app.add_option("--val", val);
+
+    run();
+
+    CHECK(2 == val);
+}
+
+TEST_CASE_METHOD(TApp, "IniSection2", "[config]") {
+
+    TempFile tmpini{"TestIniTmp.ini"};
+
+    app.set_config("--config", tmpini);
+    app.get_config_formatter_base()->section("config");
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << std::endl;
+        out << "val=1" << std::endl;
+        out << "[config]" << std::endl;
+        out << "val=2" << std::endl;
+        out << "subsubcom.val=3" << std::endl;
+    }
+
+    int val{0};
+    app.add_option("--val", val);
+
+    run();
+
+    CHECK(2 == val);
+}
+
+TEST_CASE_METHOD(TApp, "jsonLikeParsing", "[config]") {
+
+    TempFile tmpjson{"TestJsonTmp.json"};
+
+    app.set_config("--config", tmpjson);
+    app.get_config_formatter_base()->valueSeparator(':');
+
+    {
+        std::ofstream out{tmpjson};
+        out << "{" << std::endl;
+        out << "\"val\":1," << std::endl;
+        out << "\"val2\":\"test\"," << std::endl;
+        out << "\"flag\":true" << std::endl;
+        out << "}" << std::endl;
+    }
+
+    int val{0};
+    app.add_option("--val", val);
+    std::string val2{0};
+    app.add_option("--val2", val2);
+
+    bool flag{false};
+    app.add_flag("--flag", flag);
+
+    run();
+
+    CHECK(1 == val);
+    CHECK(val2 == "test");
+    CHECK(flag);
+}
+
+TEST_CASE_METHOD(TApp, "TomlSectionNumber", "[config]") {
+
+    TempFile tmpini{"TestTomlTmp.toml"};
+
+    app.set_config("--config", tmpini);
+    app.get_config_formatter_base()->section("config")->index(0);
+
+    {
+        std::ofstream out{tmpini};
+        out << "[default]" << std::endl;
+        out << "val=1" << std::endl;
+        out << "[[config]]" << std::endl;
+        out << "val=2" << std::endl;
+        out << "subsubcom.val=3" << std::endl;
+        out << "[[config]]" << std::endl;
+        out << "val=4" << std::endl;
+        out << "subsubcom.val=3" << std::endl;
+        out << "[[config]]" << std::endl;
+        out << "val=6" << std::endl;
+        out << "subsubcom.val=3" << std::endl;
+    }
+
+    int val{0};
+    app.add_option("--val", val);
+
+    run();
+
+    CHECK(2 == val);
+
+    auto &index = app.get_config_formatter_base()->indexRef();
+    index = 1;
+    run();
+
+    CHECK(4 == val);
+
+    index = -1;
+    run();
+    // Take the first section in this case
+    CHECK(2 == val);
+    index = 2;
+    run();
+
+    CHECK(6 == val);
+}
+
 TEST_CASE_METHOD(TApp, "IniSubcommandConfigurableParseComplete", "[config]") {
 
     TempFile tmpini{"TestIniTmp.ini"};
@@ -1685,7 +1993,7 @@ TEST_CASE_METHOD(TApp, "TomlOutputHiddenOptions", "[config]") {
     const std::string description2 = "Second description.";
     app.add_flag("--" + flag1, description1)->group("group1");
     app.add_flag("--" + flag2, description2)->group("group2");
-    app.add_option("--dval", val, "", true)->group("");
+    app.add_option("--dval", val)->capture_default_str()->group("");
 
     run();
 
@@ -1701,6 +2009,16 @@ TEST_CASE_METHOD(TApp, "TomlOutputHiddenOptions", "[config]") {
     CHECK(std::string::npos == loc);
 }
 
+TEST_CASE_METHOD(TApp, "TomlOutputAppMultiLineDescription", "[config]") {
+    app.description("Some short app description.\n"
+                    "That has multiple lines.");
+    run();
+
+    std::string str = app.config_to_str(true, true);
+    CHECK_THAT(str, Contains("# Some short app description.\n"));
+    CHECK_THAT(str, Contains("# That has multiple lines.\n"));
+}
+
 TEST_CASE_METHOD(TApp, "TomlOutputMultiLineDescription", "[config]") {
     std::string flag = "some_flag";
     const std::string description = "Some short description.\nThat has lines.";
@@ -1714,6 +2032,35 @@ TEST_CASE_METHOD(TApp, "TomlOutputMultiLineDescription", "[config]") {
     CHECK_THAT(str, Contains(flag + "=false\n"));
 }
 
+TEST_CASE_METHOD(TApp, "TomlOutputOptionGroupMultiLineDescription", "[config]") {
+    std::string flag = "flag";
+    const std::string description = "Short flag description.\n";
+    auto og = app.add_option_group("group");
+    og->description("Option group description.\n"
+                    "That has multiple lines.");
+    og->add_flag("--" + flag, description);
+    run();
+
+    std::string str = app.config_to_str(true, true);
+    CHECK_THAT(str, Contains("# Option group description.\n"));
+    CHECK_THAT(str, Contains("# That has multiple lines.\n"));
+}
+
+TEST_CASE_METHOD(TApp, "TomlOutputSubcommandMultiLineDescription", "[config]") {
+    std::string flag = "flag";
+    const std::string description = "Short flag description.\n";
+    auto subcom = app.add_subcommand("subcommand");
+    subcom->configurable();
+    subcom->description("Subcommand description.\n"
+                        "That has multiple lines.");
+    subcom->add_flag("--" + flag, description);
+    run();
+
+    std::string str = app.config_to_str(true, true);
+    CHECK_THAT(str, Contains("# Subcommand description.\n"));
+    CHECK_THAT(str, Contains("# That has multiple lines.\n"));
+}
+
 TEST_CASE_METHOD(TApp, "TomlOutputOptionGroup", "[config]") {
     std::string flag1 = "flagnr1";
     std::string flag2 = "flagnr2";
@@ -1723,7 +2070,7 @@ TEST_CASE_METHOD(TApp, "TomlOutputOptionGroup", "[config]") {
     app.add_flag("--" + flag1, description1)->group("group1");
     app.add_flag("--" + flag2, description2)->group("group2");
     auto og = app.add_option_group("group3", "g3 desc");
-    og->add_option("--dval", val, "", true)->group("");
+    og->add_option("--dval", val)->capture_default_str()->group("");
 
     run();
 
@@ -1809,7 +2156,7 @@ TEST_CASE_METHOD(TApp, "TomlOutputSet", "[config]") {
 TEST_CASE_METHOD(TApp, "TomlOutputDefault", "[config]") {
 
     int v{7};
-    app.add_option("--simple", v, "", true);
+    app.add_option("--simple", v)->capture_default_str();
 
     run();
 
@@ -1888,6 +2235,27 @@ TEST_CASE_METHOD(TApp, "TomlOutputSubsubcomConfigurable", "[config]") {
     CHECK(std::string::npos == str.find("sub2.newest=true"));
 }
 
+TEST_CASE_METHOD(TApp, "TomlOutputSubcomNonConfigurable", "[config]") {
+
+    app.add_flag("--simple");
+    auto subcom = app.add_subcommand("other", "other_descriptor")->configurable();
+    subcom->add_flag("--newer");
+
+    auto subcom2 = app.add_subcommand("sub2", "descriptor2");
+    subcom2->add_flag("--newest")->configurable(false);
+
+    args = {"--simple", "other", "--newer", "sub2", "--newest"};
+    run();
+
+    std::string str = app.config_to_str(true, true);
+    CHECK_THAT(str, Contains("other_descriptor"));
+    CHECK_THAT(str, Contains("simple=true"));
+    CHECK_THAT(str, Contains("[other]"));
+    CHECK_THAT(str, Contains("newer=true"));
+    CHECK_THAT(str, !Contains("newest"));
+    CHECK_THAT(str, !Contains("descriptor2"));
+}
+
 TEST_CASE_METHOD(TApp, "TomlOutputSubsubcomConfigurableDeep", "[config]") {
 
     app.add_flag("--simple");
@@ -1934,10 +2302,10 @@ TEST_CASE_METHOD(TApp, "TomlOutputQuoted", "[config]") {
 TEST_CASE_METHOD(TApp, "DefaultsTomlOutputQuoted", "[config]") {
 
     std::string val1{"I am a string"};
-    app.add_option("--val1", val1, "", true);
+    app.add_option("--val1", val1)->capture_default_str();
 
     std::string val2{R"(I am a "confusing" string)"};
-    app.add_option("--val2", val2, "", true);
+    app.add_option("--val2", val2)->capture_default_str();
 
     run();
 
@@ -2068,7 +2436,7 @@ TEST_CASE_METHOD(TApp, "IniOutputHiddenOptions", "[config]") {
     const std::string description2 = "Second description.";
     app.add_flag("--" + flag1, description1)->group("group1");
     app.add_flag("--" + flag2, description2)->group("group2");
-    app.add_option("--dval", val, "", true)->group("");
+    app.add_option("--dval", val)->capture_default_str()->group("");
     app.config_formatter(std::make_shared<CLI::ConfigINI>());
     run();
 
@@ -2084,6 +2452,17 @@ TEST_CASE_METHOD(TApp, "IniOutputHiddenOptions", "[config]") {
     CHECK(std::string::npos == loc);
 }
 
+TEST_CASE_METHOD(TApp, "IniOutputAppMultiLineDescription", "[config]") {
+    app.description("Some short app description.\n"
+                    "That has multiple lines.");
+    app.config_formatter(std::make_shared<CLI::ConfigINI>());
+    run();
+
+    std::string str = app.config_to_str(true, true);
+    CHECK_THAT(str, Contains("; Some short app description.\n"));
+    CHECK_THAT(str, Contains("; That has multiple lines.\n"));
+}
+
 TEST_CASE_METHOD(TApp, "IniOutputMultiLineDescription", "[config]") {
     std::string flag = "some_flag";
     const std::string description = "Some short description.\nThat has lines.";
@@ -2097,6 +2476,37 @@ TEST_CASE_METHOD(TApp, "IniOutputMultiLineDescription", "[config]") {
     CHECK_THAT(str, Contains(flag + "=false\n"));
 }
 
+TEST_CASE_METHOD(TApp, "IniOutputOptionGroupMultiLineDescription", "[config]") {
+    std::string flag = "flag";
+    const std::string description = "Short flag description.\n";
+    auto og = app.add_option_group("group");
+    og->description("Option group description.\n"
+                    "That has multiple lines.");
+    og->add_flag("--" + flag, description);
+    app.config_formatter(std::make_shared<CLI::ConfigINI>());
+    run();
+
+    std::string str = app.config_to_str(true, true);
+    CHECK_THAT(str, Contains("; Option group description.\n"));
+    CHECK_THAT(str, Contains("; That has multiple lines.\n"));
+}
+
+TEST_CASE_METHOD(TApp, "IniOutputSubcommandMultiLineDescription", "[config]") {
+    std::string flag = "flag";
+    const std::string description = "Short flag description.\n";
+    auto subcom = app.add_subcommand("subcommand");
+    subcom->configurable();
+    subcom->description("Subcommand description.\n"
+                        "That has multiple lines.");
+    subcom->add_flag("--" + flag, description);
+    app.config_formatter(std::make_shared<CLI::ConfigINI>());
+    run();
+
+    std::string str = app.config_to_str(true, true);
+    CHECK_THAT(str, Contains("; Subcommand description.\n"));
+    CHECK_THAT(str, Contains("; That has multiple lines.\n"));
+}
+
 TEST_CASE_METHOD(TApp, "IniOutputOptionGroup", "[config]") {
     std::string flag1 = "flagnr1";
     std::string flag2 = "flagnr2";
@@ -2106,7 +2516,7 @@ TEST_CASE_METHOD(TApp, "IniOutputOptionGroup", "[config]") {
     app.add_flag("--" + flag1, description1)->group("group1");
     app.add_flag("--" + flag2, description2)->group("group2");
     auto og = app.add_option_group("group3", "g3 desc");
-    og->add_option("--dval", val, "", true)->group("");
+    og->add_option("--dval", val)->capture_default_str()->group("");
     app.config_formatter(std::make_shared<CLI::ConfigINI>());
     run();
 
@@ -2177,7 +2587,7 @@ TEST_CASE_METHOD(TApp, "IniOutputSet", "[config]") {
 TEST_CASE_METHOD(TApp, "IniOutputDefault", "[config]") {
 
     int v{7};
-    app.add_option("--simple", v, "", true);
+    app.add_option("--simple", v)->capture_default_str();
     app.config_formatter(std::make_shared<CLI::ConfigINI>());
     run();
 
@@ -2202,6 +2612,21 @@ TEST_CASE_METHOD(TApp, "IniOutputSubcom", "[config]") {
     CHECK_THAT(str, Contains("other.newer=true"));
 }
 
+TEST_CASE_METHOD(TApp, "IniOutputSubcomCustomSep", "[config]") {
+
+    app.add_flag("--simple");
+    auto subcom = app.add_subcommand("other");
+    subcom->add_flag("--newer");
+    app.config_formatter(std::make_shared<CLI::ConfigINI>());
+    app.get_config_formatter_base()->parentSeparator(':');
+    args = {"--simple", "other", "--newer"};
+    run();
+
+    std::string str = app.config_to_str();
+    CHECK_THAT(str, Contains("simple=true"));
+    CHECK_THAT(str, Contains("other:newer=true"));
+}
+
 TEST_CASE_METHOD(TApp, "IniOutputSubcomConfigurable", "[config]") {
 
     app.add_flag("--simple");
@@ -2235,6 +2660,24 @@ TEST_CASE_METHOD(TApp, "IniOutputSubsubcom", "[config]") {
     CHECK_THAT(str, Contains("other.sub2.newest=true"));
 }
 
+TEST_CASE_METHOD(TApp, "IniOutputSubsubcomCustomSep", "[config]") {
+
+    app.add_flag("--simple");
+    auto subcom = app.add_subcommand("other");
+    subcom->add_flag("--newer");
+    auto subsubcom = subcom->add_subcommand("sub2");
+    subsubcom->add_flag("--newest");
+    app.config_formatter(std::make_shared<CLI::ConfigINI>());
+    app.get_config_formatter_base()->parentSeparator('|');
+    args = {"--simple", "other", "--newer", "sub2", "--newest"};
+    run();
+
+    std::string str = app.config_to_str();
+    CHECK_THAT(str, Contains("simple=true"));
+    CHECK_THAT(str, Contains("other|newer=true"));
+    CHECK_THAT(str, Contains("other|sub2|newest=true"));
+}
+
 TEST_CASE_METHOD(TApp, "IniOutputSubsubcomConfigurable", "[config]") {
 
     app.add_flag("--simple");
@@ -2302,10 +2745,10 @@ TEST_CASE_METHOD(TApp, "IniOutputQuoted", "[config]") {
 TEST_CASE_METHOD(TApp, "DefaultsIniOutputQuoted", "[config]") {
 
     std::string val1{"I am a string"};
-    app.add_option("--val1", val1, "", true);
+    app.add_option("--val1", val1)->capture_default_str();
 
     std::string val2{R"(I am a "confusing" string)"};
-    app.add_option("--val2", val2, "", true);
+    app.add_option("--val2", val2)->capture_default_str();
     app.config_formatter(std::make_shared<CLI::ConfigINI>());
     run();
 
diff --git a/packages/CLI11/tests/CreationTest.cpp b/packages/CLI11/tests/CreationTest.cpp
index 2a70f70d4..479005707 100644
--- a/packages/CLI11/tests/CreationTest.cpp
+++ b/packages/CLI11/tests/CreationTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -739,13 +739,13 @@ TEST_CASE_METHOD(TApp, "MakeUnstreamableOptions", "[creation]") {
     app.add_option("--value", value);
 
     // This used to fail to build, since it tries to stream from Unstreamable
-    app.add_option("--value2", value, "", false);
+    app.add_option("--value2", value);
 
     std::vector<Unstreamable> values;
     app.add_option("--values", values);
 
     // This used to fail to build, since it tries to stream from Unstreamable
-    app.add_option("--values2", values, "", false);
+    app.add_option("--values2", values);
 
     args = {"--value", "45"};
     run();
diff --git a/packages/CLI11/tests/DeprecatedTest.cpp b/packages/CLI11/tests/DeprecatedTest.cpp
index cf9987c6d..f763a89d4 100644
--- a/packages/CLI11/tests/DeprecatedTest.cpp
+++ b/packages/CLI11/tests/DeprecatedTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -12,214 +12,3 @@ TEST_CASE("Deprecated: Empty", "[deprecated]") {
     // No deprecated features at this time.
     CHECK(true);
 }
-
-// Classic sets
-
-TEST_CASE("THelp: Defaults", "[deprecated]") {
-    CLI::App app{"My prog"};
-
-    int one{1}, two{2};
-    app.add_option("--one", one, "Help for one", true);
-    app.add_option("--set", two, "Help for set", true)->check(CLI::IsMember({2, 3, 4}));
-
-    std::string help = app.help();
-
-    CHECK_THAT(help, Contains("--one"));
-    CHECK_THAT(help, Contains("--set"));
-    CHECK_THAT(help, Contains("1"));
-    CHECK_THAT(help, Contains("=2"));
-    CHECK_THAT(help, Contains("2,3,4"));
-}
-
-TEST_CASE("THelp: VectorOpts", "[deprecated]") {
-    CLI::App app{"My prog"};
-    std::vector<int> x = {1, 2};
-    app.add_option("-q,--quick", x, "", true);
-
-    std::string help = app.help();
-
-    CHECK_THAT(help, Contains("INT=[1,2] ..."));
-}
-
-TEST_CASE("THelp: SetLower", "[deprecated]") {
-    CLI::App app{"My prog"};
-
-    std::string def{"One"};
-    app.add_option("--set", def, "Help for set", true)->check(CLI::IsMember({"oNe", "twO", "THREE"}));
-
-    std::string help = app.help();
-
-    CHECK_THAT(help, Contains("--set"));
-    CHECK_THAT(help, Contains("=One"));
-    CHECK_THAT(help, Contains("oNe"));
-    CHECK_THAT(help, Contains("twO"));
-    CHECK_THAT(help, Contains("THREE"));
-}
-
-TEST_CASE("THelp: ChangingSetDefaulted", "[deprecated]") {
-    CLI::App app;
-
-    std::set<int> vals{1, 2, 3};
-    int val = 2;
-    app.add_option("--val", val, "", true)->check(CLI::IsMember(&vals));
-
-    std::string help = app.help();
-
-    CHECK_THAT(help, Contains("1"));
-    CHECK_THAT(help, !Contains("4"));
-
-    vals.insert(4);
-    vals.erase(1);
-
-    help = app.help();
-
-    CHECK_THAT(help, !Contains("1"));
-    CHECK_THAT(help, Contains("4"));
-}
-
-TEST_CASE("THelp: ChangingCaselessSetDefaulted", "[deprecated]") {
-    CLI::App app;
-
-    std::set<std::string> vals{"1", "2", "3"};
-    std::string val = "2";
-    app.add_option("--val", val, "", true)->check(CLI::IsMember(&vals, CLI::ignore_case));
-
-    std::string help = app.help();
-
-    CHECK_THAT(help, Contains("1"));
-    CHECK_THAT(help, !Contains("4"));
-
-    vals.insert("4");
-    vals.erase("1");
-
-    help = app.help();
-
-    CHECK_THAT(help, !Contains("1"));
-    CHECK_THAT(help, Contains("4"));
-}
-
-TEST_CASE_METHOD(TApp, "DefaultOpts", "[deprecated]") {
-
-    int i = 3;
-    std::string s = "HI";
-
-    app.add_option("-i,i", i, "", false);
-    app.add_option("-s,s", s, "", true);
-
-    args = {"-i2", "9"};
-
-    run();
-
-    CHECK(app.count("i") == 1u);
-    CHECK(app.count("-s") == 1u);
-    CHECK(i == 2);
-    CHECK(s == "9");
-}
-
-TEST_CASE_METHOD(TApp, "VectorDefaultedFixedString", "[deprecated]") {
-    std::vector<std::string> strvec{"one"};
-    std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};
-
-    CLI::Option *opt = app.add_option("-s,--string", strvec, "", true)->expected(3);
-    CHECK(opt->get_expected() == 3);
-
-    args = {"--string", "mystring", "mystring2", "mystring3"};
-    run();
-    CHECK(app.count("--string") == 3u);
-    CHECK(strvec == answer);
-}
-
-TEST_CASE_METHOD(TApp, "DefaultedResult", "[deprecated]") {
-    std::string sval = "NA";
-    int ival;
-    auto opts = app.add_option("--string", sval, "", true);
-    auto optv = app.add_option("--val", ival);
-    args = {};
-    run();
-    CHECK("NA" == sval);
-    std::string nString;
-    opts->results(nString);
-    CHECK("NA" == nString);
-    int newIval;
-    // CHECK_THROWS_AS (optv->results(newIval), CLI::ConversionError);
-    optv->default_str("442");
-    optv->results(newIval);
-    CHECK(442 == newIval);
-}
-
-TEST_CASE_METHOD(TApp, "OptionWithDefaults", "[deprecated]") {
-    int someint = 2;
-    app.add_option("-a", someint, "", true);
-
-    args = {"-a1", "-a2"};
-
-    CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
-}
-
-// #209
-TEST_CASE_METHOD(TApp, "CustomUserSepParse", "[deprecated]") {
-
-    std::vector<int> vals = {1, 2, 3};
-    args = {"--idx", "1,2,3"};
-    auto opt = app.add_option("--idx", vals)->delimiter(',');
-    run();
-    CHECK(std::vector<int>({1, 2, 3}) == vals);
-    std::vector<int> vals2;
-    // check that the results vector gets the results in the same way
-    opt->results(vals2);
-    CHECK(vals == vals2);
-
-    app.remove_option(opt);
-
-    app.add_option("--idx", vals, "", true)->delimiter(',');
-    run();
-    CHECK(std::vector<int>({1, 2, 3}) == vals);
-}
-
-// #209
-TEST_CASE_METHOD(TApp, "CustomUserSepParse2", "[deprecated]") {
-
-    std::vector<int> vals = {1, 2, 3};
-    args = {"--idx", "1,2,"};
-    auto opt = app.add_option("--idx", vals)->delimiter(',');
-    run();
-    CHECK(std::vector<int>({1, 2}) == vals);
-
-    app.remove_option(opt);
-
-    app.add_option("--idx", vals, "", true)->delimiter(',');
-    run();
-    CHECK(std::vector<int>({1, 2}) == vals);
-}
-//
-// #209
-TEST_CASE_METHOD(TApp, "CustomUserSepParse4", "[deprecated]") {
-
-    std::vector<int> vals;
-    args = {"--idx", "1,    2"};
-    auto opt = app.add_option("--idx", vals, "", true)->delimiter(',');
-    run();
-    CHECK(std::vector<int>({1, 2}) == vals);
-
-    app.remove_option(opt);
-
-    app.add_option("--idx", vals)->delimiter(',');
-    run();
-    CHECK(std::vector<int>({1, 2}) == vals);
-}
-
-// #218
-TEST_CASE_METHOD(TApp, "CustomUserSepParse5", "[deprecated]") {
-
-    std::vector<std::string> bar;
-    args = {"this", "is", "a", "test"};
-    auto opt = app.add_option("bar", bar, "bar");
-    run();
-    CHECK(std::vector<std::string>({"this", "is", "a", "test"}) == bar);
-
-    app.remove_option(opt);
-    args = {"this", "is", "a", "test"};
-    app.add_option("bar", bar, "bar", true);
-    run();
-    CHECK(std::vector<std::string>({"this", "is", "a", "test"}) == bar);
-}
diff --git a/packages/CLI11/tests/FormatterTest.cpp b/packages/CLI11/tests/FormatterTest.cpp
index 22da56f0e..1516945de 100644
--- a/packages/CLI11/tests/FormatterTest.cpp
+++ b/packages/CLI11/tests/FormatterTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/HelpTest.cpp b/packages/CLI11/tests/HelpTest.cpp
index 48089f6fc..cb8c81ab8 100644
--- a/packages/CLI11/tests/HelpTest.cpp
+++ b/packages/CLI11/tests/HelpTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -1155,6 +1155,7 @@ TEST_CASE("THelp: ChangingDefaults", "[help]") {
     std::vector<int> x = {1, 2};
     CLI::Option *opt = app.add_option("-q,--quick", x);
     x = {3, 4};
+    CHECK(x[0] == 3);
 
     opt->capture_default_str();
 
@@ -1162,6 +1163,7 @@ TEST_CASE("THelp: ChangingDefaults", "[help]") {
     std::string help = app.help();
 
     CHECK_THAT(help, Contains("INT=[3,4] ..."));
+    CHECK(x[0] == 5);
 }
 
 TEST_CASE("THelp: ChangingDefaultsWithAutoCapture", "[help]") {
@@ -1170,8 +1172,10 @@ TEST_CASE("THelp: ChangingDefaultsWithAutoCapture", "[help]") {
     app.option_defaults()->always_capture_default();
 
     std::vector<int> x = {1, 2};
+    CHECK(x[0] == 1);
     app.add_option("-q,--quick", x);
     x = {3, 4};
+    CHECK(x[0] == 3);
 
     std::string help = app.help();
 
@@ -1220,6 +1224,21 @@ TEST_CASE("TVersion: callback_flag", "[help]") {
     CHECK_THAT(vers, Contains("VERSION"));
 }
 
+TEST_CASE("TVersion: help", "[help]") {
+
+    CLI::App app;
+
+    app.set_version_flag("-v,--version", "version_string", "help_for_version");
+
+    auto hvers = app.help();
+    CHECK_THAT(hvers, Contains("help_for_version"));
+
+    app.set_version_flag(
+        "-v", []() { return std::string("VERSION2 " CLI11_VERSION); }, "help_for_version2");
+    hvers = app.help();
+    CHECK_THAT(hvers, Contains("help_for_version2"));
+}
+
 TEST_CASE("TVersion: parse_throw", "[help]") {
 
     CLI::App app;
diff --git a/packages/CLI11/tests/HelpersTest.cpp b/packages/CLI11/tests/HelpersTest.cpp
index 0c032fbce..7a497aa1c 100644
--- a/packages/CLI11/tests/HelpersTest.cpp
+++ b/packages/CLI11/tests/HelpersTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -155,13 +155,14 @@ TEST_CASE("String: InvalidName", "[helpers]") {
     CHECK(CLI::detail::valid_name_string("valid"));
     CHECK_FALSE(CLI::detail::valid_name_string("-invalid"));
     CHECK(CLI::detail::valid_name_string("va-li-d"));
-    CHECK_FALSE(CLI::detail::valid_name_string("vali&d"));
+    CHECK_FALSE(CLI::detail::valid_name_string("valid{}"));
     CHECK(CLI::detail::valid_name_string("_valid"));
-    CHECK_FALSE(CLI::detail::valid_name_string("/valid"));
+    CHECK(CLI::detail::valid_name_string("/valid"));
     CHECK(CLI::detail::valid_name_string("vali?d"));
     CHECK(CLI::detail::valid_name_string("@@@@"));
     CHECK(CLI::detail::valid_name_string("b@d2?"));
     CHECK(CLI::detail::valid_name_string("2vali?d"));
+    CHECK_FALSE(CLI::detail::valid_name_string("!valid"));
 }
 
 TEST_CASE("StringTools: Modify", "[helpers]") {
@@ -997,7 +998,12 @@ TEST_CASE("Types: TypeName", "[helpers]") {
     std::string umapName = CLI::detail::type_name<std::unordered_map<int, std::tuple<std::string, double>>>();
     CHECK(umapName == "[INT,[TEXT,FLOAT]]");
 
+    // On older compilers, this may show up as other/TEXT
     vclass = CLI::detail::classify_object<std::atomic<int>>::value;
+    CHECK((CLI::detail::object_category::wrapper_value == vclass || CLI::detail::object_category::other == vclass));
+
+    std::string atomic_name = CLI::detail::type_name<std::atomic<int>>();
+    CHECK((atomic_name == "INT" || atomic_name == "TEXT"));
 }
 
 TEST_CASE("Types: OverflowSmall", "[helpers]") {
@@ -1128,8 +1134,8 @@ TEST_CASE("Types: LexicalConversionDouble", "[helpers]") {
     CHECK((float)x == Approx((float)9.12));
 
     CLI::results_t bad_input = {"hello"};
-    res = CLI::detail::lexical_conversion<long double, double>(input, x);
-    CHECK(res);
+    res = CLI::detail::lexical_conversion<long double, double>(bad_input, x);
+    CHECK_FALSE(res);
 }
 
 TEST_CASE("Types: LexicalConversionDoubleTuple", "[helpers]") {
@@ -1140,8 +1146,8 @@ TEST_CASE("Types: LexicalConversionDoubleTuple", "[helpers]") {
     CHECK(std::get<0>(x) == Approx(9.12));
 
     CLI::results_t bad_input = {"hello"};
-    res = CLI::detail::lexical_conversion<decltype(x), decltype(x)>(input, x);
-    CHECK(res);
+    res = CLI::detail::lexical_conversion<decltype(x), decltype(x)>(bad_input, x);
+    CHECK_FALSE(res);
 }
 
 TEST_CASE("Types: LexicalConversionVectorDouble", "[helpers]") {
diff --git a/packages/CLI11/tests/NewParseTest.cpp b/packages/CLI11/tests/NewParseTest.cpp
index d9d9dbf91..30a0c9f41 100644
--- a/packages/CLI11/tests/NewParseTest.cpp
+++ b/packages/CLI11/tests/NewParseTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -13,49 +13,9 @@ using Catch::Matchers::Contains;
 
 using cx = std::complex<double>;
 
-TEST_CASE_METHOD(TApp, "Complex", "[newparse]") {
-    cx comp{1, 2};
-    app.add_complex("-c,--complex", comp, "", true);
-
-    args = {"-c", "4", "3"};
-
-    std::string help = app.help();
-    CHECK_THAT(help, Contains("1"));
-    CHECK_THAT(help, Contains("2"));
-    CHECK_THAT(help, Contains("COMPLEX"));
-
-    CHECK(comp.real() == Approx(1));
-    CHECK(comp.imag() == Approx(2));
-
-    run();
-
-    CHECK(comp.real() == Approx(4));
-    CHECK(comp.imag() == Approx(3));
-}
-
 TEST_CASE_METHOD(TApp, "ComplexOption", "[newparse]") {
     cx comp{1, 2};
-    app.add_option("-c,--complex", comp, "", true);
-
-    args = {"-c", "4", "3"};
-
-    std::string help = app.help();
-    CHECK_THAT(help, Contains("1"));
-    CHECK_THAT(help, Contains("2"));
-    CHECK_THAT(help, Contains("COMPLEX"));
-
-    CHECK(comp.real() == Approx(1));
-    CHECK(comp.imag() == Approx(2));
-
-    run();
-
-    CHECK(comp.real() == Approx(4));
-    CHECK(comp.imag() == Approx(3));
-}
-
-TEST_CASE_METHOD(TApp, "ComplexFloat", "[newparse]") {
-    std::complex<float> comp{1, 2};
-    app.add_complex<std::complex<float>, float>("-c,--complex", comp, "", true);
+    app.add_option("-c,--complex", comp)->capture_default_str();
 
     args = {"-c", "4", "3"};
 
@@ -75,7 +35,7 @@ TEST_CASE_METHOD(TApp, "ComplexFloat", "[newparse]") {
 
 TEST_CASE_METHOD(TApp, "ComplexFloatOption", "[newparse]") {
     std::complex<float> comp{1, 2};
-    app.add_option("-c,--complex", comp, "", true);
+    app.add_option("-c,--complex", comp)->capture_default_str();
 
     args = {"-c", "4", "3"};
 
@@ -93,41 +53,9 @@ TEST_CASE_METHOD(TApp, "ComplexFloatOption", "[newparse]") {
     CHECK(comp.imag() == Approx(3));
 }
 
-TEST_CASE_METHOD(TApp, "ComplexWithDelimiter", "[newparse]") {
-    cx comp{1, 2};
-    app.add_complex("-c,--complex", comp, "", true)->delimiter('+');
-
-    args = {"-c", "4+3i"};
-
-    std::string help = app.help();
-    CHECK_THAT(help, Contains("1"));
-    CHECK_THAT(help, Contains("2"));
-    CHECK_THAT(help, Contains("COMPLEX"));
-
-    CHECK(comp.real() == Approx(1));
-    CHECK(comp.imag() == Approx(2));
-
-    run();
-
-    CHECK(comp.real() == Approx(4));
-    CHECK(comp.imag() == Approx(3));
-
-    args = {"-c", "5+-3i"};
-    run();
-
-    CHECK(comp.real() == Approx(5));
-    CHECK(comp.imag() == Approx(-3));
-
-    args = {"-c", "6", "-4i"};
-    run();
-
-    CHECK(comp.real() == Approx(6));
-    CHECK(comp.imag() == Approx(-4));
-}
-
 TEST_CASE_METHOD(TApp, "ComplexWithDelimiterOption", "[newparse]") {
     cx comp{1, 2};
-    app.add_option("-c,--complex", comp, "", true)->delimiter('+');
+    app.add_option("-c,--complex", comp)->capture_default_str()->delimiter('+');
 
     args = {"-c", "4+3i"};
 
@@ -157,18 +85,6 @@ TEST_CASE_METHOD(TApp, "ComplexWithDelimiterOption", "[newparse]") {
     CHECK(comp.imag() == Approx(-4));
 }
 
-TEST_CASE_METHOD(TApp, "ComplexIgnoreI", "[newparse]") {
-    cx comp{1, 2};
-    app.add_complex("-c,--complex", comp);
-
-    args = {"-c", "4", "3i"};
-
-    run();
-
-    CHECK(comp.real() == Approx(4));
-    CHECK(comp.imag() == Approx(3));
-}
-
 TEST_CASE_METHOD(TApp, "ComplexIgnoreIOption", "[newparse]") {
     cx comp{1, 2};
     app.add_option("-c,--complex", comp);
@@ -181,40 +97,6 @@ TEST_CASE_METHOD(TApp, "ComplexIgnoreIOption", "[newparse]") {
     CHECK(comp.imag() == Approx(3));
 }
 
-TEST_CASE_METHOD(TApp, "ComplexSingleArg", "[newparse]") {
-    cx comp{1, 2};
-    app.add_complex("-c,--complex", comp);
-
-    args = {"-c", "4"};
-    run();
-    CHECK(comp.real() == Approx(4));
-    CHECK(comp.imag() == Approx(0));
-
-    args = {"-c", "4-2i"};
-    run();
-    CHECK(comp.real() == Approx(4));
-    CHECK(comp.imag() == Approx(-2));
-    args = {"-c", "4+2i"};
-    run();
-    CHECK(comp.real() == Approx(4));
-    CHECK(comp.imag() == Approx(2));
-
-    args = {"-c", "-4+2j"};
-    run();
-    CHECK(comp.real() == Approx(-4));
-    CHECK(comp.imag() == Approx(2));
-
-    args = {"-c", "-4.2-2j"};
-    run();
-    CHECK(comp.real() == Approx(-4.2));
-    CHECK(comp.imag() == Approx(-2));
-
-    args = {"-c", "-4.2-2.7i"};
-    run();
-    CHECK(comp.real() == Approx(-4.2));
-    CHECK(comp.imag() == Approx(-2.7));
-}
-
 TEST_CASE_METHOD(TApp, "ComplexSingleArgOption", "[newparse]") {
     cx comp{1, 2};
     app.add_option("-c,--complex", comp);
@@ -249,29 +131,6 @@ TEST_CASE_METHOD(TApp, "ComplexSingleArgOption", "[newparse]") {
     CHECK(comp.imag() == Approx(-2.7));
 }
 
-TEST_CASE_METHOD(TApp, "ComplexSingleImag", "[newparse]") {
-    cx comp{1, 2};
-    app.add_complex("-c,--complex", comp);
-
-    args = {"-c", "4j"};
-    run();
-    CHECK(comp.real() == Approx(0));
-    CHECK(comp.imag() == Approx(4));
-
-    args = {"-c", "-4j"};
-    run();
-    CHECK(comp.real() == Approx(0));
-    CHECK(comp.imag() == Approx(-4));
-    args = {"-c", "-4"};
-    run();
-    CHECK(comp.real() == Approx(-4));
-    CHECK(comp.imag() == Approx(0));
-    args = {"-c", "+4"};
-    run();
-    CHECK(comp.real() == Approx(4));
-    CHECK(comp.imag() == Approx(0));
-}
-
 TEST_CASE_METHOD(TApp, "ComplexSingleImagOption", "[newparse]") {
     cx comp{1, 2};
     app.add_option("-c,--complex", comp);
diff --git a/packages/CLI11/tests/OptionGroupTest.cpp b/packages/CLI11/tests/OptionGroupTest.cpp
index 175f31dc3..ac6684f49 100644
--- a/packages/CLI11/tests/OptionGroupTest.cpp
+++ b/packages/CLI11/tests/OptionGroupTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -23,6 +23,16 @@ TEST_CASE_METHOD(TApp, "BasicOptionGroup", "[optiongroup]") {
     CHECK(1u == app.count_all());
 }
 
+TEST_CASE_METHOD(TApp, "OptionGroupInvalidNames", "[optiongroup]") {
+    CHECK_THROWS_AS(app.add_option_group("clusters\ncluster2", "description"), CLI::IncorrectConstruction);
+
+    std::string groupName("group1");
+    groupName += '\0';
+    groupName.append("group2");
+
+    CHECK_THROWS_AS(app.add_option_group(groupName), CLI::IncorrectConstruction);
+}
+
 TEST_CASE_METHOD(TApp, "BasicOptionGroupExact", "[optiongroup]") {
     auto ogroup = app.add_option_group("clusters");
     int res{0};
@@ -593,7 +603,7 @@ TEST_CASE_METHOD(ManyGroups, "SameSubcommand", "[optiongroup]") {
     // so when the subcommands are disabled they can have the same name
     sub1->disabled(false);
     sub2->disabled(false);
-    // if they are reenabled they are not checked for overlap on enabling so they can have the same name
+    // if they are re-enabled they are not checked for overlap on enabling so they can have the same name
     args = {"sub1", "sub1", "sub1"};
 
     run();
diff --git a/packages/CLI11/tests/OptionTypeTest.cpp b/packages/CLI11/tests/OptionTypeTest.cpp
index a2f893bec..19b69746c 100644
--- a/packages/CLI11/tests/OptionTypeTest.cpp
+++ b/packages/CLI11/tests/OptionTypeTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -240,7 +240,7 @@ TEST_CASE_METHOD(TApp, "CharOption", "[optiontype]") {
 
 TEST_CASE_METHOD(TApp, "vectorDefaults", "[optiontype]") {
     std::vector<int> vals{4, 5};
-    auto opt = app.add_option("--long", vals, "", true);
+    auto opt = app.add_option("--long", vals)->capture_default_str();
 
     args = {"--long", "[1,2,3]"};
 
@@ -269,6 +269,17 @@ TEST_CASE_METHOD(TApp, "vectorDefaults", "[optiontype]") {
     CHECK(std::vector<int>({5}) == res);
 }
 
+TEST_CASE_METHOD(TApp, "mapInput", "[optiontype]") {
+    std::map<int, std::string> vals{};
+    app.add_option("--long", vals);
+
+    args = {"--long", "5", "test"};
+
+    run();
+
+    CHECK(vals.at(5) == "test");
+}
+
 TEST_CASE_METHOD(TApp, "CallbackBoolFlags", "[optiontype]") {
 
     bool value{false};
@@ -320,8 +331,6 @@ TEST_CASE_METHOD(TApp, "pair_check", "[optiontype]") {
     CHECK_THROWS_AS(run(), CLI::ValidationError);
 }
 
-// this will require that modifying the multi-option policy for tuples be allowed which it isn't at present
-
 TEST_CASE_METHOD(TApp, "pair_check_take_first", "[optiontype]") {
     std::string myfile{"pair_check_file2.txt"};
     bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a'));  // create file
@@ -915,3 +924,76 @@ TEST_CASE_METHOD(TApp, "vectorDoubleArg", "[optiontype]") {
     CHECK(2U == cv.size());
     CHECK(2U == extras.size());
 }
+
+TEST_CASE_METHOD(TApp, "OnParseCall", "[optiontype]") {
+
+    int cnt{0};
+
+    auto *opt = app.add_option("-c",
+                               [&cnt](const CLI::results_t &) {
+                                   ++cnt;
+                                   return true;
+                               })
+                    ->expected(1, 20)
+                    ->trigger_on_parse();
+    std::vector<std::string> extras;
+    app.add_option("args", extras);
+    args = {"-c", "1", "-c", "2", "-c", "3"};
+    CHECK(opt->get_trigger_on_parse());
+    run();
+    CHECK(3 == cnt);
+}
+
+TEST_CASE_METHOD(TApp, "OnParseCallVector", "[optiontype]") {
+
+    std::vector<std::string> vec;
+
+    app.add_option("-c", vec)->trigger_on_parse();
+    args = {"-c", "1", "2", "3", "-c", "2", "-c", "3", "4", "5"};
+    run();
+    CHECK(vec.size() == 3U);
+}
+
+TEST_CASE_METHOD(TApp, "force_callback", "[optiontype]") {
+
+    int cnt{0};
+
+    auto *opt = app.add_option("-c",
+                               [&cnt](const CLI::results_t &) {
+                                   ++cnt;
+                                   return true;
+                               })
+                    ->expected(1, 20)
+                    ->force_callback()
+                    ->default_str("5");
+    std::vector<std::string> extras;
+    app.add_option("args", extras);
+    args = {};
+    CHECK(opt->get_force_callback());
+    run();
+    CHECK(1 == cnt);
+    cnt = 0;
+    args = {"-c", "10"};
+    run();
+    CHECK(1 == cnt);
+}
+
+TEST_CASE_METHOD(TApp, "force_callback2", "[optiontype]") {
+
+    int cnt{0};
+
+    app.add_option("-c", cnt)->force_callback()->default_val(5);
+    args = {};
+    run();
+    CHECK(5 == cnt);
+}
+
+TEST_CASE_METHOD(TApp, "force_callback3", "[optiontype]") {
+
+    int cnt{10};
+
+    app.add_option("-c", cnt)->force_callback();
+    args = {};
+    run();
+    CHECK(0 == cnt);
+}
diff --git a/packages/CLI11/tests/OptionalTest.cpp b/packages/CLI11/tests/OptionalTest.cpp
index 4d8da020b..6b07f01c7 100644
--- a/packages/CLI11/tests/OptionalTest.cpp
+++ b/packages/CLI11/tests/OptionalTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/SetTest.cpp b/packages/CLI11/tests/SetTest.cpp
index d34a67a64..5d225ff63 100644
--- a/packages/CLI11/tests/SetTest.cpp
+++ b/packages/CLI11/tests/SetTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -373,7 +373,7 @@ TEST_CASE_METHOD(TApp, "NumericalSets", "[set]") {
 
 TEST_CASE_METHOD(TApp, "SetWithDefaults", "[set]") {
     int someint{2};
-    app.add_option("-a", someint, "", true)->check(CLI::IsMember({1, 2, 3, 4}));
+    app.add_option("-a", someint)->capture_default_str()->check(CLI::IsMember({1, 2, 3, 4}));
 
     args = {"-a1", "-a2"};
 
@@ -382,7 +382,7 @@ TEST_CASE_METHOD(TApp, "SetWithDefaults", "[set]") {
 
 TEST_CASE_METHOD(TApp, "SetWithDefaultsConversion", "[set]") {
     int someint{2};
-    app.add_option("-a", someint, "", true)->check(CLI::IsMember({1, 2, 3, 4}));
+    app.add_option("-a", someint)->capture_default_str()->check(CLI::IsMember({1, 2, 3, 4}));
 
     args = {"-a", "hi"};
 
@@ -391,7 +391,7 @@ TEST_CASE_METHOD(TApp, "SetWithDefaultsConversion", "[set]") {
 
 TEST_CASE_METHOD(TApp, "SetWithDefaultsIC", "[set]") {
     std::string someint = "ho";
-    app.add_option("-a", someint, "", true)->check(CLI::IsMember({"Hi", "Ho"}));
+    app.add_option("-a", someint)->capture_default_str()->check(CLI::IsMember({"Hi", "Ho"}));
 
     args = {"-aHi", "-aHo"};
 
@@ -415,7 +415,7 @@ TEST_CASE_METHOD(TApp, "InSet", "[set]") {
 TEST_CASE_METHOD(TApp, "InSetWithDefault", "[set]") {
 
     std::string choice = "one";
-    app.add_option("-q,--quick", choice, "", true)->check(CLI::IsMember({"one", "two", "three"}));
+    app.add_option("-q,--quick", choice)->capture_default_str()->check(CLI::IsMember({"one", "two", "three"}));
 
     run();
     CHECK(choice == "one");
@@ -432,7 +432,9 @@ TEST_CASE_METHOD(TApp, "InSetWithDefault", "[set]") {
 TEST_CASE_METHOD(TApp, "InCaselessSetWithDefault", "[set]") {
 
     std::string choice = "one";
-    app.add_option("-q,--quick", choice, "", true)->transform(CLI::IsMember({"one", "two", "three"}, CLI::ignore_case));
+    app.add_option("-q,--quick", choice)
+        ->capture_default_str()
+        ->transform(CLI::IsMember({"one", "two", "three"}, CLI::ignore_case));
 
     run();
     CHECK(choice == "one");
@@ -494,7 +496,7 @@ TEST_CASE_METHOD(TApp, "FailMutableSet", "[set]") {
     int choice{0};
     auto vals = std::shared_ptr<std::set<int>>(new std::set<int>({1, 2, 3}));
     app.add_option("-q,--quick", choice)->check(CLI::IsMember(vals));
-    app.add_option("-s,--slow", choice, "", true)->check(CLI::IsMember(vals));
+    app.add_option("-s,--slow", choice)->capture_default_str()->check(CLI::IsMember(vals));
 
     args = {"--quick=hello"};
     CHECK_THROWS_AS(run(), CLI::ValidationError);
@@ -651,7 +653,7 @@ TEST_CASE_METHOD(TApp, "AddRemoveSetItems", "[set]") {
 
     std::string type1, type2;
     app.add_option("--type1", type1)->check(CLI::IsMember(&items));
-    app.add_option("--type2", type2, "", true)->check(CLI::IsMember(&items));
+    app.add_option("--type2", type2)->capture_default_str()->check(CLI::IsMember(&items));
 
     args = {"--type1", "TYPE1", "--type2", "TYPE2"};
 
@@ -682,7 +684,7 @@ TEST_CASE_METHOD(TApp, "AddRemoveSetItemsNoCase", "[set]") {
 
     std::string type1, type2;
     app.add_option("--type1", type1)->transform(CLI::IsMember(&items, CLI::ignore_case));
-    app.add_option("--type2", type2, "", true)->transform(CLI::IsMember(&items, CLI::ignore_case));
+    app.add_option("--type2", type2)->capture_default_str()->transform(CLI::IsMember(&items, CLI::ignore_case));
 
     args = {"--type1", "TYPe1", "--type2", "TyPE2"};
 
diff --git a/packages/CLI11/tests/SimpleTest.cpp b/packages/CLI11/tests/SimpleTest.cpp
index 92262b5e6..3051a46d4 100644
--- a/packages/CLI11/tests/SimpleTest.cpp
+++ b/packages/CLI11/tests/SimpleTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/StringParseTest.cpp b/packages/CLI11/tests/StringParseTest.cpp
index 3a9f7371d..a98424811 100644
--- a/packages/CLI11/tests/StringParseTest.cpp
+++ b/packages/CLI11/tests/StringParseTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -78,3 +78,31 @@ TEST_CASE_METHOD(TApp, "ExistingExeCheckWithLotsOfSpace", "[stringparse]") {
 
     CHECK(std::string("./") + std::string(tmpexe) == app.get_name());
 }
+
+// From GitHub issue #591 https://github.com/CLIUtils/CLI11/issues/591
+TEST_CASE_METHOD(TApp, "ProgNameWithSpace", "[stringparse]") {
+
+    app.add_flag("--foo");
+    CHECK_NOTHROW(app.parse("\"Foo Bar\" --foo", true));
+
+    CHECK(app["--foo"]->as<bool>());
+    CHECK(app.get_name() == "Foo Bar");
+}
+
+TEST_CASE_METHOD(TApp, "ProgNameWithSpaceEmbeddedQuote", "[stringparse]") {
+
+    app.add_flag("--foo");
+    CHECK_NOTHROW(app.parse("\"Foo\\\" Bar\" --foo", true));
+
+    CHECK(app["--foo"]->as<bool>());
+    CHECK(app.get_name() == "Foo\" Bar");
+}
+
+TEST_CASE_METHOD(TApp, "ProgNameWithSpaceSingleQuote", "[stringparse]") {
+
+    app.add_flag("--foo");
+    CHECK_NOTHROW(app.parse(R"('Foo\' Bar' --foo)", true));
+
+    CHECK(app["--foo"]->as<bool>());
+    CHECK(app.get_name() == "Foo' Bar");
+}
diff --git a/packages/CLI11/tests/SubcommandTest.cpp b/packages/CLI11/tests/SubcommandTest.cpp
index eef67bca7..e1ffded6b 100644
--- a/packages/CLI11/tests/SubcommandTest.cpp
+++ b/packages/CLI11/tests/SubcommandTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
@@ -109,7 +109,7 @@ TEST_CASE_METHOD(TApp, "CrazyNameSubcommand", "[subcom]") {
 TEST_CASE_METHOD(TApp, "RequiredAndSubcommands", "[subcom]") {
 
     std::string baz;
-    app.add_option("baz", baz, "Baz Description", true)->required();
+    app.add_option("baz", baz, "Baz Description")->required()->capture_default_str();
     auto foo = app.add_subcommand("foo");
     auto bar = app.add_subcommand("bar");
 
@@ -811,6 +811,18 @@ TEST_CASE_METHOD(TApp, "RequiredPosInSubcommand", "[subcom]") {
     CHECK_THROWS_AS(run(), CLI::RequiredError);
 }
 
+TEST_CASE_METHOD(TApp, "invalidSubcommandName", "[subcom]") {
+
+    bool gotError{false};
+    try {
+        app.add_subcommand("!foo/foo", "Foo a bar");
+    } catch(const CLI::IncorrectConstruction &e) {
+        gotError = true;
+        CHECK_THAT(e.what(), Contains("!"));
+    }
+    CHECK(gotError);
+}
+
 struct SubcommandProgram : public TApp {
 
     CLI::App *start{nullptr};
@@ -1633,6 +1645,28 @@ TEST_CASE_METHOD(TApp, "OptionGroupAlias", "[subcom]") {
     CHECK(-3 == val);
 }
 
+TEST_CASE_METHOD(TApp, "OptionGroupAliasWithSpaces", "[subcom]") {
+    double val{0.0};
+    auto sub = app.add_option_group("sub1");
+    sub->alias("sub2 bb");
+    sub->alias("sub3/b");
+    sub->add_option("-v,--value", val);
+    args = {"sub1", "-v", "-3"};
+    CHECK_THROWS_AS(run(), CLI::ExtrasError);
+
+    args = {"sub2 bb", "--value", "-5"};
+    run();
+    CHECK(-5.0 == val);
+
+    args = {"sub3/b", "-v", "7"};
+    run();
+    CHECK(7 == val);
+
+    args = {"-v", "-3"};
+    run();
+    CHECK(-3 == val);
+}
+
 TEST_CASE_METHOD(TApp, "subcommand_help", "[subcom]") {
     auto sub1 = app.add_subcommand("help")->silent();
     bool flag{false};
@@ -1654,9 +1688,8 @@ TEST_CASE_METHOD(TApp, "AliasErrors", "[subcom]") {
     auto sub1 = app.add_subcommand("sub1");
     auto sub2 = app.add_subcommand("sub2");
 
-    CHECK_THROWS_AS(sub2->alias("this is a not a valid alias"), CLI::IncorrectConstruction);
-    CHECK_THROWS_AS(sub2->alias("-alias"), CLI::IncorrectConstruction);
-    CHECK_THROWS_AS(sub2->alias("alia$"), CLI::IncorrectConstruction);
+    CHECK_THROWS_AS(sub2->alias("this is a not\n a valid alias"), CLI::IncorrectConstruction);
+    CHECK_NOTHROW(sub2->alias("-alias"));  // this is allowed but would be unusable on command line parsers
 
     CHECK_THROWS_AS(app.add_subcommand("--bad_subcommand_name", "documenting the bad subcommand"),
                     CLI::IncorrectConstruction);
@@ -1862,3 +1895,63 @@ TEST_CASE_METHOD(ManySubcommands, "defaultEnabledSubcommand", "[subcom]") {
     CHECK(sub2->get_enabled_by_default());
     CHECK(!sub2->get_disabled());
 }
+
+// #572
+TEST_CASE_METHOD(TApp, "MultiFinalCallbackCounts", "[subcom]") {
+
+    int app_compl = 0;
+    int sub_compl = 0;
+    int subsub_compl = 0;
+    int app_final = 0;
+    int sub_final = 0;
+    int subsub_final = 0;
+
+    app.parse_complete_callback([&app_compl]() { app_compl++; });
+    app.final_callback([&app_final]() { app_final++; });
+
+    auto *sub = app.add_subcommand("sub");
+
+    sub->parse_complete_callback([&sub_compl]() { sub_compl++; });
+    sub->final_callback([&sub_final]() { sub_final++; });
+
+    auto *subsub = sub->add_subcommand("subsub");
+
+    subsub->parse_complete_callback([&subsub_compl]() { subsub_compl++; });
+    subsub->final_callback([&subsub_final]() { subsub_final++; });
+
+    SECTION("No specified subcommands") {
+        args = {};
+        run();
+
+        CHECK(app_compl == 1);
+        CHECK(app_final == 1);
+        CHECK(sub_compl == 0);
+        CHECK(sub_final == 0);
+        CHECK(subsub_compl == 0);
+        CHECK(subsub_final == 0);
+    }
+
+    SECTION("One layer of subcommands") {
+        args = {"sub"};
+        run();
+
+        CHECK(app_compl == 1);
+        CHECK(app_final == 1);
+        CHECK(sub_compl == 1);
+        CHECK(sub_final == 1);
+        CHECK(subsub_compl == 0);
+        CHECK(subsub_final == 0);
+    }
+
+    SECTION("Fully specified subcommands") {
+        args = {"sub", "subsub"};
+        run();
+
+        CHECK(app_compl == 1);
+        CHECK(app_final == 1);
+        CHECK(sub_compl == 1);
+        CHECK(sub_final == 1);
+        CHECK(subsub_compl == 1);
+        CHECK(subsub_final == 1);
+    }
+}
diff --git a/packages/CLI11/tests/TimerTest.cpp b/packages/CLI11/tests/TimerTest.cpp
index 8c88f478a..11e6e1217 100644
--- a/packages/CLI11/tests/TimerTest.cpp
+++ b/packages/CLI11/tests/TimerTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/TransformTest.cpp b/packages/CLI11/tests/TransformTest.cpp
index 84ac544a4..76a1eff83 100644
--- a/packages/CLI11/tests/TransformTest.cpp
+++ b/packages/CLI11/tests/TransformTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/TrueFalseTest.cpp b/packages/CLI11/tests/TrueFalseTest.cpp
index aa8886c09..c3b556c3f 100644
--- a/packages/CLI11/tests/TrueFalseTest.cpp
+++ b/packages/CLI11/tests/TrueFalseTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/WindowsTest.cpp b/packages/CLI11/tests/WindowsTest.cpp
index 847266649..5a75908c2 100644
--- a/packages/CLI11/tests/WindowsTest.cpp
+++ b/packages/CLI11/tests/WindowsTest.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/app_helper.hpp b/packages/CLI11/tests/app_helper.hpp
index 0f72adda2..919916825 100644
--- a/packages/CLI11/tests/app_helper.hpp
+++ b/packages/CLI11/tests/app_helper.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/informational.cpp b/packages/CLI11/tests/informational.cpp
index 92f7dc4c8..f0fc70ba1 100644
--- a/packages/CLI11/tests/informational.cpp
+++ b/packages/CLI11/tests/informational.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/link_test_1.cpp b/packages/CLI11/tests/link_test_1.cpp
index be9103760..447afbf4e 100644
--- a/packages/CLI11/tests/link_test_1.cpp
+++ b/packages/CLI11/tests/link_test_1.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/link_test_2.cpp b/packages/CLI11/tests/link_test_2.cpp
index b8544ab47..abce5493b 100644
--- a/packages/CLI11/tests/link_test_2.cpp
+++ b/packages/CLI11/tests/link_test_2.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/main.cpp b/packages/CLI11/tests/main.cpp
index f1c2725f5..f5fbebd81 100644
--- a/packages/CLI11/tests/main.cpp
+++ b/packages/CLI11/tests/main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
diff --git a/packages/CLI11/tests/mesonTest/main.cpp b/packages/CLI11/tests/mesonTest/main.cpp
index 69813782a..64d45eb6f 100644
--- a/packages/CLI11/tests/mesonTest/main.cpp
+++ b/packages/CLI11/tests/mesonTest/main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020, University of Cincinnati, developed by Henry Schreiner
+// Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner
 // under NSF AWARD 1414736 and by the respective contributors.
 // All rights reserved.
 //
-- 
GitLab