Commit efb99b97b37001536a45d3bf158f8a81ccf75eb3

Authored by Henry Schreiner
Committed by GitHub
1 parent 4917b8b7

Tutorial book (#318)

* Clean up book merge

* Book building in place
.ci/build_docs.sh deleted
1   -#!/bin/sh
2   -################################################################################
3   -# Title : generateDocumentationAndDeploy.sh
4   -# Date created : 2016/02/22
5   -# Notes :
6   -# Author : Jeroen de Bruijn
7   -# Preconditions:
8   -# - Packages doxygen doxygen-doc doxygen-latex doxygen-gui graphviz
9   -# must be installed.
10   -# - Doxygen configuration file must have the destination directory empty and
11   -# source code directory with a $(TRAVIS_BUILD_DIR) prefix.
12   -# - An gh-pages branch should already exist. See below for mor info on hoe to
13   -# create a gh-pages branch.
14   -#
15   -# Required global variables:
16   -# - TRAVIS_BUILD_NUMBER : The number of the current build.
17   -# - TRAVIS_COMMIT : The commit that the current build is testing.
18   -# - DOXYFILE : The Doxygen configuration file.
19   -# - TRAVIS_REPO_SLUG : The username / reponame for the repository.
20   -# - GH_REPO_TOKEN : Secure token to the github repository.
21   -#
22   -# For information on how to encrypt variables for Travis CI please go to
23   -# https://docs.travis-ci.com/user/environment-variables/#Encrypted-Variables
24   -# or https://gist.github.com/vidavidorra/7ed6166a46c537d3cbd2
25   -# For information on how to create a clean gh-pages branch from the master
26   -# branch, please go to https://gist.github.com/vidavidorra/846a2fc7dd51f4fe56a0
27   -#
28   -# This script will generate Doxygen documentation and push the documentation to
29   -# the gh-pages branch of a repository specified by GH_REPO_REF.
30   -# Before this script is used there should already be a gh-pages branch in the
31   -# repository.
32   -#
33   -################################################################################
34   -
35   -################################################################################
36   -##### Setup this script and get the current gh-pages branch. #####
37   -echo 'Setting up the script...'
38   -# Exit with nonzero exit code if anything fails
39   -set -e
40   -
41   -GH_REPO_ORG=$(echo $TRAVIS_REPO_SLUG | cut -d "/" -f 1)
42   -GH_REPO_NAME=$(echo $TRAVIS_REPO_SLUG | cut -d "/" -f 2)
43   -GH_REPO_REF="github.com/$GH_REPO_ORG/$GH_REPO_NAME.git"
44   -
45   -# Create a clean working directory for this script.
46   -# Get the current gh-pages branch
47   -cd docs
48   -git clone -b gh-pages https://git@$GH_REPO_REF html
49   -cd html
50   -
51   -##### Configure git.
52   -# Set the push default to simple i.e. push only the current branch.
53   -git config --global push.default simple
54   -# Pretend to be an user called Travis CI.
55   -git config user.name "Travis CI"
56   -git config user.email "travis@travis-ci.org"
57   -
58   -# Remove everything currently in the gh-pages branch.
59   -# GitHub is smart enough to know which files have changed and which files have
60   -# stayed the same and will only update the changed files. So the gh-pages branch
61   -# can be safely cleaned, and it is sure that everything pushed later is the new
62   -# documentation.
63   -rm -rf *
64   -
65   -# Need to create a .nojekyll file to allow filenames starting with an underscore
66   -# to be seen on the gh-pages site. Therefore creating an empty .nojekyll file.
67   -# Presumably this is only needed when the SHORT_NAMES option in Doxygen is set
68   -# to NO, which it is by default. So creating the file just in case.
69   -echo "" > .nojekyll
70   -
71   -################################################################################
72   -##### Generate the Doxygen code documentation and log the output. #####
73   -echo 'Generating Doxygen code documentation...'
74   -# Redirect both stderr and stdout to the log file AND the console.
75   -cd ..
76   -doxygen $DOXYFILE 2>&1 | tee doxygen.log
77   -
78   -################################################################################
79   -##### Upload the documentation to the gh-pages branch of the repository. #####
80   -# Only upload if Doxygen successfully created the documentation.
81   -# Check this by verifying that the html directory and the file html/index.html
82   -# both exist. This is a good indication that Doxygen did it's work.
83   -if [ -d "html" ] && [ -f "html/index.html" ]; then
84   -
85   - cd html
86   - echo 'Uploading documentation to the gh-pages branch...'
87   - # Add everything in this directory (the Doxygen code documentation) to the
88   - # gh-pages branch.
89   - # GitHub is smart enough to know which files have changed and which files have
90   - # stayed the same and will only update the changed files.
91   - git add --all
92   -
93   - # Commit the added files with a title and description containing the Travis CI
94   - # build number and the GitHub commit reference that issued this build.
95   - git commit -m "Deploy code docs to GitHub Pages Travis build: ${TRAVIS_BUILD_NUMBER}" -m "Commit: ${TRAVIS_COMMIT}"
96   -
97   - # Force push to the remote gh-pages branch.
98   - # The ouput is redirected to /dev/null to hide any sensitive credential data
99   - # that might otherwise be exposed.
100   - git push --force "https://${GH_REPO_TOKEN}@${GH_REPO_REF}" > /dev/null 2>&1
101   -else
102   - echo '' >&2
103   - echo 'Warning: No documentation (html) files have been found!' >&2
104   - echo 'Warning: Not going to push the documentation to GitHub!' >&2
105   - exit 1
106   -fi
.gitignore
... ... @@ -6,4 +6,5 @@ a.out*
6 6 /CMakeFiles/*
7 7 /cmake_install.cmake
8 8 /*.kdev4
  9 +/html/*
9 10 !/meson.build
... ...
.travis.yml
... ... @@ -38,19 +38,14 @@ matrix:
38 38 - export CXX=clang++-3.5
39 39 - npm install gitbook-cli -g
40 40 - gitbook fetch 3.2.3
41   - - (cd book && gitbook install)
  41 + - gitbook install book
42 42 script:
43 43 - .ci/make_and_test.sh 11
44 44 after_success:
45   - - export DOXYFILE=$TRAVIS_BUILD_DIR/docs/Doxyfile
46 45 - export DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
47   - - |
48   - if [ "${TRAVIS_BRANCH}" == "master" ] && [ "${TRAVIS_PULL_REQUEST}" == "false" ]
49   - then
50   - . .ci/build_doxygen.sh
51   - .ci/build_docs.sh
52   - fi
53   - - (cd book && gitbook build . ../docs/html/book)
  46 + - . .ci/build_doxygen.sh
  47 + - doxygen docs/Doxyfile
  48 + - gitbook build book html/book
54 49  
55 50 # GCC 7 and coverage (8 does not support lcov, wait till 9 and new lcov)
56 51 - compiler: gcc
... ... @@ -110,7 +105,15 @@ script:
110 105  
111 106  
112 107 deploy:
113   - provider: releases
  108 +- provider: pages
  109 + skip_cleanup: true
  110 + github_token: $GITHUB_REPO_TOKEN
  111 + keep_history: true
  112 + local_dir: ${TRAVIS_BUILD_DIR}/html
  113 + on:
  114 + branch: master
  115 + condition: "$DEPLOY_MAT = yes"
  116 +- provider: releases
114 117 api_key:
115 118 secure: L1svZ5J+RiR67dj1fNk/XiZRvYfGJC4c5/dKSvDH+yuKSzZ6ODaTiVmYF8NtMJ7/3AQenEa0OuRBVQ0YpngFz3ugIcRsGCDUHtCMK/Bti0+6ZFdICbqcv6W3BlRIM8s7EOBPhjfbCV+ae7xep9B24HmwBPKukMFjDIj4nwBsmwCHZK9iNFtfaW2J2cr2TJo7QPY01J0W1k/boaj91KzHf9UuhEH8KYqp7szv+6kV00W8bRBtugw419dIm25eXFXgXDT9s/OA7qXV7o5FXWWpkyJ5AINVbY9DerkYag5TStrdOyKk+S1FexRG6TMG4L4Jyu/QxQGhMdu0m1yRCLvIekGtWLDnjNrI2SZrd5HbKprQ0O8j1770Is4q5blVPqAZ6O9jVMJRtVEaYbsJwItz1BJWkPT4S9GFbDL1dq2Z5jR2f5gd/cz2yYH56b47iYHWtzSqEfVhsXiN+atD+tWyQFA4Q/av0bGHwJ6LX0A1q0OCHruUMoxcw1QKfYtV1bkf/folL4Z4Hx3CL+NB0Lkqs8LFsQHxODP4a26I5DS/kaDHofotho8wsWlKFDtonZa+CExORGFFMPnGRz2qX5tMgGoo84wcqrprfoQv2llqeUr3gISPl2qxrljAhj3/Dcl7iI7k0Er7Ji8ENpgjSec4aqnBx8Ke2yaDEmBvwbouFCM=
116 119 skip_cleanup: true
... ... @@ -119,6 +122,7 @@ deploy:
119 122 repo: CLIUtils/CLI11
120 123 tags: true
121 124 condition: "$DEPLOY_MAT = yes"
  125 +
122 126 notifications:
123 127 webhooks:
124 128 urls:
... ... @@ -126,6 +130,7 @@ notifications:
126 130 on_success: change
127 131 on_failure: always
128 132 on_start: never
  133 +
129 134 env:
130 135 global:
131 136 - secure: cY0OI609iTAxLRYuYQnNMi+H6n0dBwioTAoFXGGRTnngw2V9om3UmY5eUu4HQEQsQZovHdYpNhlSgRmdwQ4UqSp3FGyrwobf0kzacV4bVnMDeXDmHt8RzE5wP/LwDd8elNF6RRYjElY99f0k0FyXVd0fIvuVkGKQECNLOtEk0jQo+4YTh7dhuCxRhBYgTbNiRL6UJynfrcK0YN+DQ+8CJNupu2VxgaEpCSngTfvDHLcddcrXwpvn3MPc3FsDUbtN389ZCIe41qqIL0ATv46DQaTw4FOevyVfRyrBOznONoGCVeAYKL6VBdrk01Fh6aytF5zgI3hKaKobgEn+QFfzR6l68c6APvqA0Qv39iLjuh6KbdIV2YsqXfyt6FBgqP2xZuNEZW1jZ8LxUOLl2I40UEh87nFutvnSbfIzN+FcLrajm2H2jV2kZGNKAMx+4qxkZuXSre4JPkENfJm2WNFAKlqPt4ZSEQarkDYzZPcEr2I9fbGjQYVJICoN4LikCv9K5z7ujpTxCTNbVpQWZcEOT6QQBc6Vml/N/NKAIl9o2OeTLiXCmT31+KQMeO492KYNQ6VmkeqrVhGExOUcJdNyDJV9C+3mSekb3Sq78SneYRKDechkWbMl0ol07wGTdBwQQwgaorjRyn07x1rDxpPr3z19/+eubnpPUW4UQ5MYsjs=
... ...
book/code/CLI11.hpp deleted
1   -#pragma once
2   -
3   -// CLI11: Version 1.7.1
4   -// Originally designed by Henry Schreiner
5   -// https://github.com/CLIUtils/CLI11
6   -//
7   -// This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts
8   -// from: v1.7.1
9   -//
10   -// From LICENSE:
11   -//
12   -// CLI11 1.7 Copyright (c) 2017-2019 University of Cincinnati, developed by Henry
13   -// Schreiner under NSF AWARD 1414736. All rights reserved.
14   -//
15   -// Redistribution and use in source and binary forms of CLI11, with or without
16   -// modification, are permitted provided that the following conditions are met:
17   -//
18   -// 1. Redistributions of source code must retain the above copyright notice, this
19   -// list of conditions and the following disclaimer.
20   -// 2. Redistributions in binary form must reproduce the above copyright notice,
21   -// this list of conditions and the following disclaimer in the documentation
22   -// and/or other materials provided with the distribution.
23   -// 3. Neither the name of the copyright holder nor the names of its contributors
24   -// may be used to endorse or promote products derived from this software without
25   -// specific prior written permission.
26   -//
27   -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
28   -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29   -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30   -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
31   -// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32   -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33   -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
34   -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35   -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36   -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37   -
38   -// Standard combined includes:
39   -
40   -#include <algorithm>
41   -#include <deque>
42   -#include <exception>
43   -#include <fstream>
44   -#include <functional>
45   -#include <iomanip>
46   -#include <iostream>
47   -#include <istream>
48   -#include <iterator>
49   -#include <locale>
50   -#include <map>
51   -#include <memory>
52   -#include <numeric>
53   -#include <set>
54   -#include <sstream>
55   -#include <stdexcept>
56   -#include <string>
57   -#include <sys/stat.h>
58   -#include <sys/types.h>
59   -#include <tuple>
60   -#include <type_traits>
61   -#include <utility>
62   -#include <vector>
63   -
64   -// Verbatim copy from CLI/Version.hpp:
65   -
66   -#define CLI11_VERSION_MAJOR 1
67   -#define CLI11_VERSION_MINOR 7
68   -#define CLI11_VERSION_PATCH 1
69   -#define CLI11_VERSION "1.7.1"
70   -
71   -// Verbatim copy from CLI/Macros.hpp:
72   -
73   -// The following version macro is very similar to the one in PyBind11
74   -#if !(defined(_MSC_VER) && __cplusplus == 199711L) && !defined(__INTEL_COMPILER)
75   -#if __cplusplus >= 201402L
76   -#define CLI11_CPP14
77   -#if __cplusplus >= 201703L
78   -#define CLI11_CPP17
79   -#if __cplusplus > 201703L
80   -#define CLI11_CPP20
81   -#endif
82   -#endif
83   -#endif
84   -#elif defined(_MSC_VER) && __cplusplus == 199711L
85   -// MSVC sets _MSVC_LANG rather than __cplusplus (supposedly until the standard is fully implemented)
86   -// Unless you use the /Zc:__cplusplus flag on Visual Studio 2017 15.7 Preview 3 or newer
87   -#if _MSVC_LANG >= 201402L
88   -#define CLI11_CPP14
89   -#if _MSVC_LANG > 201402L && _MSC_VER >= 1910
90   -#define CLI11_CPP17
91   -#if __MSVC_LANG > 201703L && _MSC_VER >= 1910
92   -#define CLI11_CPP20
93   -#endif
94   -#endif
95   -#endif
96   -#endif
97   -
98   -#if defined(CLI11_CPP14)
99   -#define CLI11_DEPRECATED(reason) [[deprecated(reason)]]
100   -#elif defined(_MSC_VER)
101   -#define CLI11_DEPRECATED(reason) __declspec(deprecated(reason))
102   -#else
103   -#define CLI11_DEPRECATED(reason) __attribute__((deprecated(reason)))
104   -#endif
105   -
106   -// Verbatim copy from CLI/Optional.hpp:
107   -
108   -#ifdef __has_include
109   -
110   -// You can explicitly enable or disable support
111   -// by defining these to 1 or 0.
112   -#if defined(CLI11_CPP17) && __has_include(<optional>) && \
113   - !defined(CLI11_STD_OPTIONAL)
114   -#define CLI11_STD_OPTIONAL 1
115   -#elif !defined(CLI11_STD_OPTIONAL)
116   -#define CLI11_STD_OPTIONAL 0
117   -#endif
118   -
119   -#if defined(CLI11_CPP14) && __has_include(<experimental/optional>) && \
120   - !defined(CLI11_EXPERIMENTAL_OPTIONAL) \
121   - && (!defined(CLI11_STD_OPTIONAL) || CLI11_STD_OPTIONAL == 0)
122   -#define CLI11_EXPERIMENTAL_OPTIONAL 1
123   -#elif !defined(CLI11_EXPERIMENTAL_OPTIONAL)
124   -#define CLI11_EXPERIMENTAL_OPTIONAL 0
125   -#endif
126   -
127   -#if __has_include(<boost/optional.hpp>) && !defined(CLI11_BOOST_OPTIONAL)
128   -#include <boost/version.hpp>
129   -#if BOOST_VERSION >= 105800
130   -#define CLI11_BOOST_OPTIONAL 1
131   -#endif
132   -#elif !defined(CLI11_BOOST_OPTIONAL)
133   -#define CLI11_BOOST_OPTIONAL 0
134   -#endif
135   -
136   -#endif
137   -
138   -#if CLI11_STD_OPTIONAL
139   -#include <optional>
140   -#endif
141   -#if CLI11_EXPERIMENTAL_OPTIONAL
142   -#include <experimental/optional>
143   -#endif
144   -#if CLI11_BOOST_OPTIONAL
145   -#include <boost/optional.hpp>
146   -#endif
147   -
148   -// From CLI/Version.hpp:
149   -
150   -// From CLI/Macros.hpp:
151   -
152   -// From CLI/Optional.hpp:
153   -
154   -namespace CLI {
155   -
156   -#if CLI11_STD_OPTIONAL
157   -template <typename T> std::istream &operator>>(std::istream &in, std::optional<T> &val) {
158   - T v;
159   - in >> v;
160   - val = v;
161   - return in;
162   -}
163   -#endif
164   -
165   -#if CLI11_EXPERIMENTAL_OPTIONAL
166   -template <typename T> std::istream &operator>>(std::istream &in, std::experimental::optional<T> &val) {
167   - T v;
168   - in >> v;
169   - val = v;
170   - return in;
171   -}
172   -#endif
173   -
174   -#if CLI11_BOOST_OPTIONAL
175   -template <typename T> std::istream &operator>>(std::istream &in, boost::optional<T> &val) {
176   - T v;
177   - in >> v;
178   - val = v;
179   - return in;
180   -}
181   -#endif
182   -
183   -// Export the best optional to the CLI namespace
184   -#if CLI11_STD_OPTIONAL
185   -using std::optional;
186   -#elif CLI11_EXPERIMENTAL_OPTIONAL
187   -using std::experimental::optional;
188   -#elif CLI11_BOOST_OPTIONAL
189   -using boost::optional;
190   -#endif
191   -
192   -// This is true if any optional is found
193   -#if CLI11_STD_OPTIONAL || CLI11_EXPERIMENTAL_OPTIONAL || CLI11_BOOST_OPTIONAL
194   -#define CLI11_OPTIONAL 1
195   -#endif
196   -
197   -} // namespace CLI
198   -
199   -// From CLI/StringTools.hpp:
200   -
201   -namespace CLI {
202   -namespace detail {
203   -
204   -// Based on http://stackoverflow.com/questions/236129/split-a-string-in-c
205   -/// Split a string by a delim
206   -inline std::vector<std::string> split(const std::string &s, char delim) {
207   - std::vector<std::string> elems;
208   - // Check to see if empty string, give consistent result
209   - if(s.empty())
210   - elems.emplace_back("");
211   - else {
212   - std::stringstream ss;
213   - ss.str(s);
214   - std::string item;
215   - while(std::getline(ss, item, delim)) {
216   - elems.push_back(item);
217   - }
218   - }
219   - return elems;
220   -}
221   -
222   -/// Simple function to join a string
223   -template <typename T> std::string join(const T &v, std::string delim = ",") {
224   - std::ostringstream s;
225   - size_t start = 0;
226   - for(const auto &i : v) {
227   - if(start++ > 0)
228   - s << delim;
229   - s << i;
230   - }
231   - return s.str();
232   -}
233   -
234   -/// Join a string in reverse order
235   -template <typename T> std::string rjoin(const T &v, std::string delim = ",") {
236   - std::ostringstream s;
237   - for(size_t start = 0; start < v.size(); start++) {
238   - if(start > 0)
239   - s << delim;
240   - s << v[v.size() - start - 1];
241   - }
242   - return s.str();
243   -}
244   -
245   -// Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string
246   -
247   -/// Trim whitespace from left of string
248   -inline std::string &ltrim(std::string &str) {
249   - auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });
250   - str.erase(str.begin(), it);
251   - return str;
252   -}
253   -
254   -/// Trim anything from left of string
255   -inline std::string &ltrim(std::string &str, const std::string &filter) {
256   - auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });
257   - str.erase(str.begin(), it);
258   - return str;
259   -}
260   -
261   -/// Trim whitespace from right of string
262   -inline std::string &rtrim(std::string &str) {
263   - auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });
264   - str.erase(it.base(), str.end());
265   - return str;
266   -}
267   -
268   -/// Trim anything from right of string
269   -inline std::string &rtrim(std::string &str, const std::string &filter) {
270   - auto it =
271   - std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });
272   - str.erase(it.base(), str.end());
273   - return str;
274   -}
275   -
276   -/// Trim whitespace from string
277   -inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); }
278   -
279   -/// Trim anything from string
280   -inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); }
281   -
282   -/// Make a copy of the string and then trim it
283   -inline std::string trim_copy(const std::string &str) {
284   - std::string s = str;
285   - return trim(s);
286   -}
287   -
288   -/// Make a copy of the string and then trim it, any filter string can be used (any char in string is filtered)
289   -inline std::string trim_copy(const std::string &str, const std::string &filter) {
290   - std::string s = str;
291   - return trim(s, filter);
292   -}
293   -/// Print a two part "help" string
294   -inline std::ostream &format_help(std::ostream &out, std::string name, std::string description, size_t wid) {
295   - name = " " + name;
296   - out << std::setw(static_cast<int>(wid)) << std::left << name;
297   - if(!description.empty()) {
298   - if(name.length() >= wid)
299   - out << "\n" << std::setw(static_cast<int>(wid)) << "";
300   - out << description;
301   - }
302   - out << "\n";
303   - return out;
304   -}
305   -
306   -/// Verify the first character of an option
307   -template <typename T> bool valid_first_char(T c) { return std::isalpha(c, std::locale()) || c == '_'; }
308   -
309   -/// Verify following characters of an option
310   -template <typename T> bool valid_later_char(T c) {
311   - return std::isalnum(c, std::locale()) || c == '_' || c == '.' || c == '-';
312   -}
313   -
314   -/// Verify an option name
315   -inline bool valid_name_string(const std::string &str) {
316   - if(str.empty() || !valid_first_char(str[0]))
317   - return false;
318   - for(auto c : str.substr(1))
319   - if(!valid_later_char(c))
320   - return false;
321   - return true;
322   -}
323   -
324   -/// Return a lower case version of a string
325   -inline std::string to_lower(std::string str) {
326   - std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) {
327   - return std::tolower(x, std::locale());
328   - });
329   - return str;
330   -}
331   -
332   -/// remove underscores from a string
333   -inline std::string remove_underscore(std::string str) {
334   - str.erase(std::remove(std::begin(str), std::end(str), '_'), std::end(str));
335   - return str;
336   -}
337   -
338   -/// Find and replace a substring with another substring
339   -inline std::string find_and_replace(std::string str, std::string from, std::string to) {
340   -
341   - size_t start_pos = 0;
342   -
343   - while((start_pos = str.find(from, start_pos)) != std::string::npos) {
344   - str.replace(start_pos, from.length(), to);
345   - start_pos += to.length();
346   - }
347   -
348   - return str;
349   -}
350   -
351   -/// Find a trigger string and call a modify callable function that takes the current string and starting position of the
352   -/// trigger and returns the position in the string to search for the next trigger string
353   -template <typename Callable> inline std::string find_and_modify(std::string str, std::string trigger, Callable modify) {
354   - size_t start_pos = 0;
355   - while((start_pos = str.find(trigger, start_pos)) != std::string::npos) {
356   - start_pos = modify(str, start_pos);
357   - }
358   - return str;
359   -}
360   -
361   -/// Split a string '"one two" "three"' into 'one two', 'three'
362   -/// Quote characters can be ` ' or "
363   -inline std::vector<std::string> split_up(std::string str) {
364   -
365   - const std::string delims("\'\"`");
366   - auto find_ws = [](char ch) { return std::isspace<char>(ch, std::locale()); };
367   - trim(str);
368   -
369   - std::vector<std::string> output;
370   - bool embeddedQuote = false;
371   - char keyChar = ' ';
372   - while(!str.empty()) {
373   - if(delims.find_first_of(str[0]) != std::string::npos) {
374   - keyChar = str[0];
375   - auto end = str.find_first_of(keyChar, 1);
376   - while((end != std::string::npos) && (str[end - 1] == '\\')) { // deal with escaped quotes
377   - end = str.find_first_of(keyChar, end + 1);
378   - embeddedQuote = true;
379   - }
380   - if(end != std::string::npos) {
381   - output.push_back(str.substr(1, end - 1));
382   - str = str.substr(end + 1);
383   - } else {
384   - output.push_back(str.substr(1));
385   - str = "";
386   - }
387   - } else {
388   - auto it = std::find_if(std::begin(str), std::end(str), find_ws);
389   - if(it != std::end(str)) {
390   - std::string value = std::string(str.begin(), it);
391   - output.push_back(value);
392   - str = std::string(it, str.end());
393   - } else {
394   - output.push_back(str);
395   - str = "";
396   - }
397   - }
398   - // transform any embedded quotes into the regular character
399   - if(embeddedQuote) {
400   - output.back() = find_and_replace(output.back(), std::string("\\") + keyChar, std::string(1, keyChar));
401   - embeddedQuote = false;
402   - }
403   - trim(str);
404   - }
405   - return output;
406   -}
407   -
408   -/// Add a leader to the beginning of all new lines (nothing is added
409   -/// at the start of the first line). `"; "` would be for ini files
410   -///
411   -/// Can't use Regex, or this would be a subs.
412   -inline std::string fix_newlines(std::string leader, std::string input) {
413   - std::string::size_type n = 0;
414   - while(n != std::string::npos && n < input.size()) {
415   - n = input.find('\n', n);
416   - if(n != std::string::npos) {
417   - input = input.substr(0, n + 1) + leader + input.substr(n + 1);
418   - n += leader.size();
419   - }
420   - }
421   - return input;
422   -}
423   -
424   -/// This function detects an equal or colon followed by an escaped quote after an argument
425   -/// then modifies the string to replace the equality with a space. This is needed
426   -/// to allow the split up function to work properly and is intended to be used with the find_and_modify function
427   -/// the return value is the offset+1 which is required by the find_and_modify function.
428   -inline size_t escape_detect(std::string &str, size_t offset) {
429   - auto next = str[offset + 1];
430   - if((next == '\"') || (next == '\'') || (next == '`')) {
431   - auto astart = str.find_last_of("-/ \"\'`", offset - 1);
432   - if(astart != std::string::npos) {
433   - if(str[astart] == ((str[offset] == '=') ? '-' : '/'))
434   - str[offset] = ' '; // interpret this as a space so the split_up works properly
435   - }
436   - }
437   - return offset + 1;
438   -}
439   -
440   -/// Add quotes if the string contains spaces
441   -inline std::string &add_quotes_if_needed(std::string &str) {
442   - if((str.front() != '"' && str.front() != '\'') || str.front() != str.back()) {
443   - char quote = str.find('"') < str.find('\'') ? '\'' : '"';
444   - if(str.find(' ') != std::string::npos) {
445   - str.insert(0, 1, quote);
446   - str.append(1, quote);
447   - }
448   - }
449   - return str;
450   -}
451   -
452   -} // namespace detail
453   -} // namespace CLI
454   -
455   -// From CLI/Error.hpp:
456   -
457   -namespace CLI {
458   -
459   -// Use one of these on all error classes.
460   -// These are temporary and are undef'd at the end of this file.
461   -#define CLI11_ERROR_DEF(parent, name) \
462   - protected: \
463   - name(std::string ename, std::string msg, int exit_code) : parent(std::move(ename), std::move(msg), exit_code) {} \
464   - name(std::string ename, std::string msg, ExitCodes exit_code) \
465   - : parent(std::move(ename), std::move(msg), exit_code) {} \
466   - \
467   - public: \
468   - name(std::string msg, ExitCodes exit_code) : parent(#name, std::move(msg), exit_code) {} \
469   - name(std::string msg, int exit_code) : parent(#name, std::move(msg), exit_code) {}
470   -
471   -// This is added after the one above if a class is used directly and builds its own message
472   -#define CLI11_ERROR_SIMPLE(name) \
473   - explicit name(std::string msg) : name(#name, msg, ExitCodes::name) {}
474   -
475   -/// These codes are part of every error in CLI. They can be obtained from e using e.exit_code or as a quick shortcut,
476   -/// int values from e.get_error_code().
477   -enum class ExitCodes {
478   - Success = 0,
479   - IncorrectConstruction = 100,
480   - BadNameString,
481   - OptionAlreadyAdded,
482   - FileError,
483   - ConversionError,
484   - ValidationError,
485   - RequiredError,
486   - RequiresError,
487   - ExcludesError,
488   - ExtrasError,
489   - ConfigError,
490   - InvalidError,
491   - HorribleError,
492   - OptionNotFound,
493   - ArgumentMismatch,
494   - BaseClass = 127
495   -};
496   -
497   -// Error definitions
498   -
499   -/// @defgroup error_group Errors
500   -/// @brief Errors thrown by CLI11
501   -///
502   -/// These are the errors that can be thrown. Some of them, like CLI::Success, are not really errors.
503   -/// @{
504   -
505   -/// All errors derive from this one
506   -class Error : public std::runtime_error {
507   - int actual_exit_code;
508   - std::string error_name{"Error"};
509   -
510   - public:
511   - int get_exit_code() const { return actual_exit_code; }
512   -
513   - std::string get_name() const { return error_name; }
514   -
515   - Error(std::string name, std::string msg, int exit_code = static_cast<int>(ExitCodes::BaseClass))
516   - : runtime_error(msg), actual_exit_code(exit_code), error_name(std::move(name)) {}
517   -
518   - Error(std::string name, std::string msg, ExitCodes exit_code) : Error(name, msg, static_cast<int>(exit_code)) {}
519   -};
520   -
521   -// Note: Using Error::Error constructors does not work on GCC 4.7
522   -
523   -/// Construction errors (not in parsing)
524   -class ConstructionError : public Error {
525   - CLI11_ERROR_DEF(Error, ConstructionError)
526   -};
527   -
528   -/// Thrown when an option is set to conflicting values (non-vector and multi args, for example)
529   -class IncorrectConstruction : public ConstructionError {
530   - CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction)
531   - CLI11_ERROR_SIMPLE(IncorrectConstruction)
532   - static IncorrectConstruction PositionalFlag(std::string name) {
533   - return IncorrectConstruction(name + ": Flags cannot be positional");
534   - }
535   - static IncorrectConstruction Set0Opt(std::string name) {
536   - return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead");
537   - }
538   - static IncorrectConstruction SetFlag(std::string name) {
539   - return IncorrectConstruction(name + ": Cannot set an expected number for flags");
540   - }
541   - static IncorrectConstruction ChangeNotVector(std::string name) {
542   - return IncorrectConstruction(name + ": You can only change the expected arguments for vectors");
543   - }
544   - static IncorrectConstruction AfterMultiOpt(std::string name) {
545   - return IncorrectConstruction(
546   - name + ": You can't change expected arguments after you've changed the multi option policy!");
547   - }
548   - static IncorrectConstruction MissingOption(std::string name) {
549   - return IncorrectConstruction("Option " + name + " is not defined");
550   - }
551   - static IncorrectConstruction MultiOptionPolicy(std::string name) {
552   - return IncorrectConstruction(name + ": multi_option_policy only works for flags and exact value options");
553   - }
554   -};
555   -
556   -/// Thrown on construction of a bad name
557   -class BadNameString : public ConstructionError {
558   - CLI11_ERROR_DEF(ConstructionError, BadNameString)
559   - CLI11_ERROR_SIMPLE(BadNameString)
560   - static BadNameString OneCharName(std::string name) { return BadNameString("Invalid one char name: " + name); }
561   - static BadNameString BadLongName(std::string name) { return BadNameString("Bad long name: " + name); }
562   - static BadNameString DashesOnly(std::string name) {
563   - return BadNameString("Must have a name, not just dashes: " + name);
564   - }
565   - static BadNameString MultiPositionalNames(std::string name) {
566   - return BadNameString("Only one positional name allowed, remove: " + name);
567   - }
568   -};
569   -
570   -/// Thrown when an option already exists
571   -class OptionAlreadyAdded : public ConstructionError {
572   - CLI11_ERROR_DEF(ConstructionError, OptionAlreadyAdded)
573   - explicit OptionAlreadyAdded(std::string name)
574   - : OptionAlreadyAdded(name + " is already added", ExitCodes::OptionAlreadyAdded) {}
575   - static OptionAlreadyAdded Requires(std::string name, std::string other) {
576   - return OptionAlreadyAdded(name + " requires " + other, ExitCodes::OptionAlreadyAdded);
577   - }
578   - static OptionAlreadyAdded Excludes(std::string name, std::string other) {
579   - return OptionAlreadyAdded(name + " excludes " + other, ExitCodes::OptionAlreadyAdded);
580   - }
581   -};
582   -
583   -// Parsing errors
584   -
585   -/// Anything that can error in Parse
586   -class ParseError : public Error {
587   - CLI11_ERROR_DEF(Error, ParseError)
588   -};
589   -
590   -// Not really "errors"
591   -
592   -/// This is a successful completion on parsing, supposed to exit
593   -class Success : public ParseError {
594   - CLI11_ERROR_DEF(ParseError, Success)
595   - Success() : Success("Successfully completed, should be caught and quit", ExitCodes::Success) {}
596   -};
597   -
598   -/// -h or --help on command line
599   -class CallForHelp : public ParseError {
600   - CLI11_ERROR_DEF(ParseError, CallForHelp)
601   - CallForHelp() : CallForHelp("This should be caught in your main function, see examples", ExitCodes::Success) {}
602   -};
603   -
604   -/// Usually something like --help-all on command line
605   -class CallForAllHelp : public ParseError {
606   - CLI11_ERROR_DEF(ParseError, CallForAllHelp)
607   - CallForAllHelp()
608   - : CallForAllHelp("This should be caught in your main function, see examples", ExitCodes::Success) {}
609   -};
610   -
611   -/// Does not output a diagnostic in CLI11_PARSE, but allows to return from main() with a specific error code.
612   -class RuntimeError : public ParseError {
613   - CLI11_ERROR_DEF(ParseError, RuntimeError)
614   - explicit RuntimeError(int exit_code = 1) : RuntimeError("Runtime error", exit_code) {}
615   -};
616   -
617   -/// Thrown when parsing an INI file and it is missing
618   -class FileError : public ParseError {
619   - CLI11_ERROR_DEF(ParseError, FileError)
620   - CLI11_ERROR_SIMPLE(FileError)
621   - static FileError Missing(std::string name) { return FileError(name + " was not readable (missing?)"); }
622   -};
623   -
624   -/// Thrown when conversion call back fails, such as when an int fails to coerce to a string
625   -class ConversionError : public ParseError {
626   - CLI11_ERROR_DEF(ParseError, ConversionError)
627   - CLI11_ERROR_SIMPLE(ConversionError)
628   - ConversionError(std::string member, std::string name)
629   - : ConversionError("The value " + member + " is not an allowed value for " + name) {}
630   - ConversionError(std::string name, std::vector<std::string> results)
631   - : ConversionError("Could not convert: " + name + " = " + detail::join(results)) {}
632   - static ConversionError TooManyInputsFlag(std::string name) {
633   - return ConversionError(name + ": too many inputs for a flag");
634   - }
635   - static ConversionError TrueFalse(std::string name) {
636   - return ConversionError(name + ": Should be true/false or a number");
637   - }
638   -};
639   -
640   -/// Thrown when validation of results fails
641   -class ValidationError : public ParseError {
642   - CLI11_ERROR_DEF(ParseError, ValidationError)
643   - CLI11_ERROR_SIMPLE(ValidationError)
644   - explicit ValidationError(std::string name, std::string msg) : ValidationError(name + ": " + msg) {}
645   -};
646   -
647   -/// Thrown when a required option is missing
648   -class RequiredError : public ParseError {
649   - CLI11_ERROR_DEF(ParseError, RequiredError)
650   - explicit RequiredError(std::string name) : RequiredError(name + " is required", ExitCodes::RequiredError) {}
651   - static RequiredError Subcommand(size_t min_subcom) {
652   - if(min_subcom == 1)
653   - return RequiredError("A subcommand");
654   - else
655   - return RequiredError("Requires at least " + std::to_string(min_subcom) + " subcommands",
656   - ExitCodes::RequiredError);
657   - }
658   -};
659   -
660   -/// Thrown when the wrong number of arguments has been received
661   -class ArgumentMismatch : public ParseError {
662   - CLI11_ERROR_DEF(ParseError, ArgumentMismatch)
663   - CLI11_ERROR_SIMPLE(ArgumentMismatch)
664   - ArgumentMismatch(std::string name, int expected, size_t recieved)
665   - : ArgumentMismatch(expected > 0 ? ("Expected exactly " + std::to_string(expected) + " arguments to " + name +
666   - ", got " + std::to_string(recieved))
667   - : ("Expected at least " + std::to_string(-expected) + " arguments to " + name +
668   - ", got " + std::to_string(recieved)),
669   - ExitCodes::ArgumentMismatch) {}
670   -
671   - static ArgumentMismatch AtLeast(std::string name, int num) {
672   - return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required");
673   - }
674   - static ArgumentMismatch TypedAtLeast(std::string name, int num, std::string type) {
675   - return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing");
676   - }
677   -};
678   -
679   -/// Thrown when a requires option is missing
680   -class RequiresError : public ParseError {
681   - CLI11_ERROR_DEF(ParseError, RequiresError)
682   - RequiresError(std::string curname, std::string subname)
683   - : RequiresError(curname + " requires " + subname, ExitCodes::RequiresError) {}
684   -};
685   -
686   -/// Thrown when an excludes option is present
687   -class ExcludesError : public ParseError {
688   - CLI11_ERROR_DEF(ParseError, ExcludesError)
689   - ExcludesError(std::string curname, std::string subname)
690   - : ExcludesError(curname + " excludes " + subname, ExitCodes::ExcludesError) {}
691   -};
692   -
693   -/// Thrown when too many positionals or options are found
694   -class ExtrasError : public ParseError {
695   - CLI11_ERROR_DEF(ParseError, ExtrasError)
696   - explicit ExtrasError(std::vector<std::string> args)
697   - : ExtrasError((args.size() > 1 ? "The following arguments were not expected: "
698   - : "The following argument was not expected: ") +
699   - detail::rjoin(args, " "),
700   - ExitCodes::ExtrasError) {}
701   -};
702   -
703   -/// Thrown when extra values are found in an INI file
704   -class ConfigError : public ParseError {
705   - CLI11_ERROR_DEF(ParseError, ConfigError)
706   - CLI11_ERROR_SIMPLE(ConfigError)
707   - static ConfigError Extras(std::string item) { return ConfigError("INI was not able to parse " + item); }
708   - static ConfigError NotConfigurable(std::string item) {
709   - return ConfigError(item + ": This option is not allowed in a configuration file");
710   - }
711   -};
712   -
713   -/// Thrown when validation fails before parsing
714   -class InvalidError : public ParseError {
715   - CLI11_ERROR_DEF(ParseError, InvalidError)
716   - explicit InvalidError(std::string name)
717   - : InvalidError(name + ": Too many positional arguments with unlimited expected args", ExitCodes::InvalidError) {
718   - }
719   -};
720   -
721   -/// This is just a safety check to verify selection and parsing match - you should not ever see it
722   -/// Strings are directly added to this error, but again, it should never be seen.
723   -class HorribleError : public ParseError {
724   - CLI11_ERROR_DEF(ParseError, HorribleError)
725   - CLI11_ERROR_SIMPLE(HorribleError)
726   -};
727   -
728   -// After parsing
729   -
730   -/// Thrown when counting a non-existent option
731   -class OptionNotFound : public Error {
732   - CLI11_ERROR_DEF(Error, OptionNotFound)
733   - explicit OptionNotFound(std::string name) : OptionNotFound(name + " not found", ExitCodes::OptionNotFound) {}
734   -};
735   -
736   -#undef CLI11_ERROR_DEF
737   -#undef CLI11_ERROR_SIMPLE
738   -
739   -/// @}
740   -
741   -} // namespace CLI
742   -
743   -// From CLI/TypeTools.hpp:
744   -
745   -namespace CLI {
746   -
747   -// Type tools
748   -
749   -/// A copy of enable_if_t from C++14, compatible with C++11.
750   -///
751   -/// We could check to see if C++14 is being used, but it does not hurt to redefine this
752   -/// (even Google does this: https://github.com/google/skia/blob/master/include/private/SkTLogic.h)
753   -/// It is not in the std namespace anyway, so no harm done.
754   -
755   -template <bool B, class T = void> using enable_if_t = typename std::enable_if<B, T>::type;
756   -
757   -/// Check to see if something is a vector (fail check by default)
758   -template <typename T> struct is_vector { static const bool value = false; };
759   -
760   -/// Check to see if something is a vector (true if actually a vector)
761   -template <class T, class A> struct is_vector<std::vector<T, A>> { static bool const value = true; };
762   -
763   -/// Check to see if something is bool (fail check by default)
764   -template <typename T> struct is_bool { static const bool value = false; };
765   -
766   -/// Check to see if something is bool (true if actually a bool)
767   -template <> struct is_bool<bool> { static bool const value = true; };
768   -
769   -namespace detail {
770   -// Based generally on https://rmf.io/cxx11/almost-static-if
771   -/// Simple empty scoped class
772   -enum class enabler {};
773   -
774   -/// An instance to use in EnableIf
775   -constexpr enabler dummy = {};
776   -
777   -// Type name print
778   -
779   -/// Was going to be based on
780   -/// http://stackoverflow.com/questions/1055452/c-get-name-of-type-in-template
781   -/// But this is cleaner and works better in this case
782   -
783   -template <typename T,
784   - enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, detail::enabler> = detail::dummy>
785   -constexpr const char *type_name() {
786   - return "INT";
787   -}
788   -
789   -template <typename T,
790   - enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value, detail::enabler> = detail::dummy>
791   -constexpr const char *type_name() {
792   - return "UINT";
793   -}
794   -
795   -template <typename T, enable_if_t<std::is_floating_point<T>::value, detail::enabler> = detail::dummy>
796   -constexpr const char *type_name() {
797   - return "FLOAT";
798   -}
799   -
800   -/// This one should not be used, since vector types print the internal type
801   -template <typename T, enable_if_t<is_vector<T>::value, detail::enabler> = detail::dummy>
802   -constexpr const char *type_name() {
803   - return "VECTOR";
804   -}
805   -
806   -template <typename T,
807   - enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value && !is_vector<T>::value,
808   - detail::enabler> = detail::dummy>
809   -constexpr const char *type_name() {
810   - return "TEXT";
811   -}
812   -
813   -// Lexical cast
814   -
815   -/// Signed integers / enums
816   -template <typename T,
817   - enable_if_t<(std::is_integral<T>::value && std::is_signed<T>::value), detail::enabler> = detail::dummy>
818   -bool lexical_cast(std::string input, T &output) {
819   - try {
820   - size_t n = 0;
821   - long long output_ll = std::stoll(input, &n, 0);
822   - output = static_cast<T>(output_ll);
823   - return n == input.size() && static_cast<long long>(output) == output_ll;
824   - } catch(const std::invalid_argument &) {
825   - return false;
826   - } catch(const std::out_of_range &) {
827   - return false;
828   - }
829   -}
830   -
831   -/// Unsigned integers
832   -template <typename T,
833   - enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value, detail::enabler> = detail::dummy>
834   -bool lexical_cast(std::string input, T &output) {
835   - if(!input.empty() && input.front() == '-')
836   - return false; // std::stoull happily converts negative values to junk without any errors.
837   -
838   - try {
839   - size_t n = 0;
840   - unsigned long long output_ll = std::stoull(input, &n, 0);
841   - output = static_cast<T>(output_ll);
842   - return n == input.size() && static_cast<unsigned long long>(output) == output_ll;
843   - } catch(const std::invalid_argument &) {
844   - return false;
845   - } catch(const std::out_of_range &) {
846   - return false;
847   - }
848   -}
849   -
850   -/// Floats
851   -template <typename T, enable_if_t<std::is_floating_point<T>::value, detail::enabler> = detail::dummy>
852   -bool lexical_cast(std::string input, T &output) {
853   - try {
854   - size_t n = 0;
855   - output = static_cast<T>(std::stold(input, &n));
856   - return n == input.size();
857   - } catch(const std::invalid_argument &) {
858   - return false;
859   - } catch(const std::out_of_range &) {
860   - return false;
861   - }
862   -}
863   -
864   -/// String and similar
865   -template <typename T,
866   - enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value &&
867   - std::is_assignable<T &, std::string>::value,
868   - detail::enabler> = detail::dummy>
869   -bool lexical_cast(std::string input, T &output) {
870   - output = input;
871   - return true;
872   -}
873   -
874   -/// Non-string parsable
875   -template <typename T,
876   - enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value &&
877   - !std::is_assignable<T &, std::string>::value,
878   - detail::enabler> = detail::dummy>
879   -bool lexical_cast(std::string input, T &output) {
880   - std::istringstream is;
881   -
882   - is.str(input);
883   - is >> output;
884   - return !is.fail() && !is.rdbuf()->in_avail();
885   -}
886   -
887   -} // namespace detail
888   -} // namespace CLI
889   -
890   -// From CLI/Split.hpp:
891   -
892   -namespace CLI {
893   -namespace detail {
894   -
895   -// Returns false if not a short option. Otherwise, sets opt name and rest and returns true
896   -inline bool split_short(const std::string &current, std::string &name, std::string &rest) {
897   - if(current.size() > 1 && current[0] == '-' && valid_first_char(current[1])) {
898   - name = current.substr(1, 1);
899   - rest = current.substr(2);
900   - return true;
901   - } else
902   - return false;
903   -}
904   -
905   -// Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true
906   -inline bool split_long(const std::string &current, std::string &name, std::string &value) {
907   - if(current.size() > 2 && current.substr(0, 2) == "--" && valid_first_char(current[2])) {
908   - auto loc = current.find_first_of('=');
909   - if(loc != std::string::npos) {
910   - name = current.substr(2, loc - 2);
911   - value = current.substr(loc + 1);
912   - } else {
913   - name = current.substr(2);
914   - value = "";
915   - }
916   - return true;
917   - } else
918   - return false;
919   -}
920   -
921   -// Returns false if not a windows style option. Otherwise, sets opt name and value and returns true
922   -inline bool split_windows(const std::string &current, std::string &name, std::string &value) {
923   - if(current.size() > 1 && current[0] == '/' && valid_first_char(current[1])) {
924   - auto loc = current.find_first_of(':');
925   - if(loc != std::string::npos) {
926   - name = current.substr(1, loc - 1);
927   - value = current.substr(loc + 1);
928   - } else {
929   - name = current.substr(1);
930   - value = "";
931   - }
932   - return true;
933   - } else
934   - return false;
935   -}
936   -
937   -// Splits a string into multiple long and short names
938   -inline std::vector<std::string> split_names(std::string current) {
939   - std::vector<std::string> output;
940   - size_t val;
941   - while((val = current.find(",")) != std::string::npos) {
942   - output.push_back(trim_copy(current.substr(0, val)));
943   - current = current.substr(val + 1);
944   - }
945   - output.push_back(trim_copy(current));
946   - return output;
947   -}
948   -
949   -/// Get a vector of short names, one of long names, and a single name
950   -inline std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>
951   -get_names(const std::vector<std::string> &input) {
952   -
953   - std::vector<std::string> short_names;
954   - std::vector<std::string> long_names;
955   - std::string pos_name;
956   -
957   - for(std::string name : input) {
958   - if(name.length() == 0)
959   - continue;
960   - else if(name.length() > 1 && name[0] == '-' && name[1] != '-') {
961   - if(name.length() == 2 && valid_first_char(name[1]))
962   - short_names.emplace_back(1, name[1]);
963   - else
964   - throw BadNameString::OneCharName(name);
965   - } else if(name.length() > 2 && name.substr(0, 2) == "--") {
966   - name = name.substr(2);
967   - if(valid_name_string(name))
968   - long_names.push_back(name);
969   - else
970   - throw BadNameString::BadLongName(name);
971   - } else if(name == "-" || name == "--") {
972   - throw BadNameString::DashesOnly(name);
973   - } else {
974   - if(pos_name.length() > 0)
975   - throw BadNameString::MultiPositionalNames(name);
976   - pos_name = name;
977   - }
978   - }
979   -
980   - return std::tuple<std::vector<std::string>, std::vector<std::string>, std::string>(
981   - short_names, long_names, pos_name);
982   -}
983   -
984   -} // namespace detail
985   -} // namespace CLI
986   -
987   -// From CLI/ConfigFwd.hpp:
988   -
989   -namespace CLI {
990   -
991   -class App;
992   -
993   -namespace detail {
994   -
995   -/// Comma separated join, adds quotes if needed
996   -inline std::string ini_join(std::vector<std::string> args) {
997   - std::ostringstream s;
998   - size_t start = 0;
999   - for(const auto &arg : args) {
1000   - if(start++ > 0)
1001   - s << " ";
1002   -
1003   - auto it = std::find_if(arg.begin(), arg.end(), [](char ch) { return std::isspace<char>(ch, std::locale()); });
1004   - if(it == arg.end())
1005   - s << arg;
1006   - else if(arg.find(R"(")") == std::string::npos)
1007   - s << R"(")" << arg << R"(")";
1008   - else
1009   - s << R"(')" << arg << R"(')";
1010   - }
1011   -
1012   - return s.str();
1013   -}
1014   -
1015   -} // namespace detail
1016   -
1017   -/// Holds values to load into Options
1018   -struct ConfigItem {
1019   - /// This is the list of parents
1020   - std::vector<std::string> parents;
1021   -
1022   - /// This is the name
1023   - std::string name;
1024   -
1025   - /// Listing of inputs
1026   - std::vector<std::string> inputs;
1027   -
1028   - /// The list of parents and name joined by "."
1029   - std::string fullname() const {
1030   - std::vector<std::string> tmp = parents;
1031   - tmp.emplace_back(name);
1032   - return detail::join(tmp, ".");
1033   - }
1034   -};
1035   -
1036   -/// This class provides a converter for configuration files.
1037   -class Config {
1038   - protected:
1039   - std::vector<ConfigItem> items;
1040   -
1041   - public:
1042   - /// Convert an app into a configuration
1043   - virtual std::string to_config(const App *, bool, bool, std::string) const = 0;
1044   -
1045   - /// Convert a configuration into an app
1046   - virtual std::vector<ConfigItem> from_config(std::istream &) const = 0;
1047   -
1048   - /// Convert a flag to a bool
1049   - virtual std::vector<std::string> to_flag(const ConfigItem &item) const {
1050   - if(item.inputs.size() == 1) {
1051   - std::string val = item.inputs.at(0);
1052   - val = detail::to_lower(val);
1053   -
1054   - if(val == "true" || val == "on" || val == "yes") {
1055   - return std::vector<std::string>(1);
1056   - } else if(val == "false" || val == "off" || val == "no") {
1057   - return std::vector<std::string>();
1058   - } else {
1059   - try {
1060   - size_t ui = std::stoul(val);
1061   - return std::vector<std::string>(ui);
1062   - } catch(const std::invalid_argument &) {
1063   - throw ConversionError::TrueFalse(item.fullname());
1064   - }
1065   - }
1066   - } else {
1067   - throw ConversionError::TooManyInputsFlag(item.fullname());
1068   - }
1069   - }
1070   -
1071   - /// Parse a config file, throw an error (ParseError:ConfigParseError or FileError) on failure
1072   - std::vector<ConfigItem> from_file(const std::string &name) {
1073   - std::ifstream input{name};
1074   - if(!input.good())
1075   - throw FileError::Missing(name);
1076   -
1077   - return from_config(input);
1078   - }
1079   -
1080   - /// virtual destructor
1081   - virtual ~Config() = default;
1082   -};
1083   -
1084   -/// This converter works with INI files
1085   -class ConfigINI : public Config {
1086   - public:
1087   - std::string to_config(const App *, bool default_also, bool write_description, std::string prefix) const override;
1088   -
1089   - std::vector<ConfigItem> from_config(std::istream &input) const override {
1090   - std::string line;
1091   - std::string section = "default";
1092   -
1093   - std::vector<ConfigItem> output;
1094   -
1095   - while(getline(input, line)) {
1096   - std::vector<std::string> items_buffer;
1097   -
1098   - detail::trim(line);
1099   - size_t len = line.length();
1100   - if(len > 1 && line[0] == '[' && line[len - 1] == ']') {
1101   - section = line.substr(1, len - 2);
1102   - } else if(len > 0 && line[0] != ';') {
1103   - output.emplace_back();
1104   - ConfigItem &out = output.back();
1105   -
1106   - // Find = in string, split and recombine
1107   - auto pos = line.find('=');
1108   - if(pos != std::string::npos) {
1109   - out.name = detail::trim_copy(line.substr(0, pos));
1110   - std::string item = detail::trim_copy(line.substr(pos + 1));
1111   - items_buffer = detail::split_up(item);
1112   - } else {
1113   - out.name = detail::trim_copy(line);
1114   - items_buffer = {"ON"};
1115   - }
1116   -
1117   - if(detail::to_lower(section) != "default") {
1118   - out.parents = {section};
1119   - }
1120   -
1121   - if(out.name.find('.') != std::string::npos) {
1122   - std::vector<std::string> plist = detail::split(out.name, '.');
1123   - out.name = plist.back();
1124   - plist.pop_back();
1125   - out.parents.insert(out.parents.end(), plist.begin(), plist.end());
1126   - }
1127   -
1128   - out.inputs.insert(std::end(out.inputs), std::begin(items_buffer), std::end(items_buffer));
1129   - }
1130   - }
1131   - return output;
1132   - }
1133   -};
1134   -
1135   -} // namespace CLI
1136   -
1137   -// From CLI/Validators.hpp:
1138   -
1139   -namespace CLI {
1140   -
1141   -/// @defgroup validator_group Validators
1142   -
1143   -/// @brief Some validators that are provided
1144   -///
1145   -/// These are simple `std::string(const std::string&)` validators that are useful. They return
1146   -/// a string if the validation fails. A custom struct is provided, as well, with the same user
1147   -/// semantics, but with the ability to provide a new type name.
1148   -/// @{
1149   -
1150   -///
1151   -struct Validator {
1152   - /// This is the type name, if empty the type name will not be changed
1153   - std::string tname;
1154   -
1155   - /// This it the base function that is to be called.
1156   - /// Returns a string error message if validation fails.
1157   - std::function<std::string(const std::string &)> func;
1158   -
1159   - /// This is the required operator for a validator - provided to help
1160   - /// users (CLI11 uses the member `func` directly)
1161   - std::string operator()(const std::string &str) const { return func(str); };
1162   -
1163   - /// Combining validators is a new validator
1164   - Validator operator&(const Validator &other) const {
1165   - Validator newval;
1166   - newval.tname = (tname == other.tname ? tname : "");
1167   -
1168   - // Give references (will make a copy in lambda function)
1169   - const std::function<std::string(const std::string &filename)> &f1 = func;
1170   - const std::function<std::string(const std::string &filename)> &f2 = other.func;
1171   -
1172   - newval.func = [f1, f2](const std::string &filename) {
1173   - std::string s1 = f1(filename);
1174   - std::string s2 = f2(filename);
1175   - if(!s1.empty() && !s2.empty())
1176   - return s1 + " & " + s2;
1177   - else
1178   - return s1 + s2;
1179   - };
1180   - return newval;
1181   - }
1182   -
1183   - /// Combining validators is a new validator
1184   - Validator operator|(const Validator &other) const {
1185   - Validator newval;
1186   - newval.tname = (tname == other.tname ? tname : "");
1187   -
1188   - // Give references (will make a copy in lambda function)
1189   - const std::function<std::string(const std::string &filename)> &f1 = func;
1190   - const std::function<std::string(const std::string &filename)> &f2 = other.func;
1191   -
1192   - newval.func = [f1, f2](const std::string &filename) {
1193   - std::string s1 = f1(filename);
1194   - std::string s2 = f2(filename);
1195   - if(s1.empty() || s2.empty())
1196   - return std::string();
1197   - else
1198   - return s1 + " & " + s2;
1199   - };
1200   - return newval;
1201   - }
1202   -};
1203   -
1204   -// The implementation of the built in validators is using the Validator class;
1205   -// the user is only expected to use the const (static) versions (since there's no setup).
1206   -// Therefore, this is in detail.
1207   -namespace detail {
1208   -
1209   -/// Check for an existing file (returns error message if check fails)
1210   -struct ExistingFileValidator : public Validator {
1211   - ExistingFileValidator() {
1212   - tname = "FILE";
1213   - func = [](const std::string &filename) {
1214   - struct stat buffer;
1215   - bool exist = stat(filename.c_str(), &buffer) == 0;
1216   - bool is_dir = (buffer.st_mode & S_IFDIR) != 0;
1217   - if(!exist) {
1218   - return "File does not exist: " + filename;
1219   - } else if(is_dir) {
1220   - return "File is actually a directory: " + filename;
1221   - }
1222   - return std::string();
1223   - };
1224   - }
1225   -};
1226   -
1227   -/// Check for an existing directory (returns error message if check fails)
1228   -struct ExistingDirectoryValidator : public Validator {
1229   - ExistingDirectoryValidator() {
1230   - tname = "DIR";
1231   - func = [](const std::string &filename) {
1232   - struct stat buffer;
1233   - bool exist = stat(filename.c_str(), &buffer) == 0;
1234   - bool is_dir = (buffer.st_mode & S_IFDIR) != 0;
1235   - if(!exist) {
1236   - return "Directory does not exist: " + filename;
1237   - } else if(!is_dir) {
1238   - return "Directory is actually a file: " + filename;
1239   - }
1240   - return std::string();
1241   - };
1242   - }
1243   -};
1244   -
1245   -/// Check for an existing path
1246   -struct ExistingPathValidator : public Validator {
1247   - ExistingPathValidator() {
1248   - tname = "PATH";
1249   - func = [](const std::string &filename) {
1250   - struct stat buffer;
1251   - bool const exist = stat(filename.c_str(), &buffer) == 0;
1252   - if(!exist) {
1253   - return "Path does not exist: " + filename;
1254   - }
1255   - return std::string();
1256   - };
1257   - }
1258   -};
1259   -
1260   -/// Check for an non-existing path
1261   -struct NonexistentPathValidator : public Validator {
1262   - NonexistentPathValidator() {
1263   - tname = "PATH";
1264   - func = [](const std::string &filename) {
1265   - struct stat buffer;
1266   - bool exist = stat(filename.c_str(), &buffer) == 0;
1267   - if(exist) {
1268   - return "Path already exists: " + filename;
1269   - }
1270   - return std::string();
1271   - };
1272   - }
1273   -};
1274   -} // namespace detail
1275   -
1276   -// Static is not needed here, because global const implies static.
1277   -
1278   -/// Check for existing file (returns error message if check fails)
1279   -const detail::ExistingFileValidator ExistingFile;
1280   -
1281   -/// Check for an existing directory (returns error message if check fails)
1282   -const detail::ExistingDirectoryValidator ExistingDirectory;
1283   -
1284   -/// Check for an existing path
1285   -const detail::ExistingPathValidator ExistingPath;
1286   -
1287   -/// Check for an non-existing path
1288   -const detail::NonexistentPathValidator NonexistentPath;
1289   -
1290   -/// Produce a range (factory). Min and max are inclusive.
1291   -struct Range : public Validator {
1292   - /// This produces a range with min and max inclusive.
1293   - ///
1294   - /// Note that the constructor is templated, but the struct is not, so C++17 is not
1295   - /// needed to provide nice syntax for Range(a,b).
1296   - template <typename T> Range(T min, T max) {
1297   - std::stringstream out;
1298   - out << detail::type_name<T>() << " in [" << min << " - " << max << "]";
1299   -
1300   - tname = out.str();
1301   - func = [min, max](std::string input) {
1302   - T val;
1303   - detail::lexical_cast(input, val);
1304   - if(val < min || val > max)
1305   - return "Value " + input + " not in range " + std::to_string(min) + " to " + std::to_string(max);
1306   -
1307   - return std::string();
1308   - };
1309   - }
1310   -
1311   - /// Range of one value is 0 to value
1312   - template <typename T> explicit Range(T max) : Range(static_cast<T>(0), max) {}
1313   -};
1314   -
1315   -namespace detail {
1316   -/// split a string into a program name and command line arguments
1317   -/// the string is assumed to contain a file name followed by other arguments
1318   -/// the return value contains is a pair with the first argument containing the program name and the second everything
1319   -/// else
1320   -inline std::pair<std::string, std::string> split_program_name(std::string commandline) {
1321   - // try to determine the programName
1322   - std::pair<std::string, std::string> vals;
1323   - trim(commandline);
1324   - auto esp = commandline.find_first_of(' ', 1);
1325   - while(!ExistingFile(commandline.substr(0, esp)).empty()) {
1326   - esp = commandline.find_first_of(' ', esp + 1);
1327   - if(esp == std::string::npos) {
1328   - // if we have reached the end and haven't found a valid file just assume the first argument is the
1329   - // program name
1330   - esp = commandline.find_first_of(' ', 1);
1331   - break;
1332   - }
1333   - }
1334   - vals.first = commandline.substr(0, esp);
1335   - rtrim(vals.first);
1336   - // strip the program name
1337   - vals.second = (esp != std::string::npos) ? commandline.substr(esp + 1) : std::string{};
1338   - ltrim(vals.second);
1339   - return vals;
1340   -}
1341   -} // namespace detail
1342   -/// @}
1343   -
1344   -} // namespace CLI
1345   -
1346   -// From CLI/FormatterFwd.hpp:
1347   -
1348   -namespace CLI {
1349   -
1350   -class Option;
1351   -class App;
1352   -
1353   -/// This enum signifies the type of help requested
1354   -///
1355   -/// This is passed in by App; all user classes must accept this as
1356   -/// the second argument.
1357   -
1358   -enum class AppFormatMode {
1359   - Normal, //< The normal, detailed help
1360   - All, //< A fully expanded help
1361   - Sub, //< Used when printed as part of expanded subcommand
1362   -};
1363   -
1364   -/// This is the minimum requirements to run a formatter.
1365   -///
1366   -/// A user can subclass this is if they do not care at all
1367   -/// about the structure in CLI::Formatter.
1368   -class FormatterBase {
1369   - protected:
1370   - /// @name Options
1371   - ///@{
1372   -
1373   - /// The width of the first column
1374   - size_t column_width_{30};
1375   -
1376   - /// @brief The required help printout labels (user changeable)
1377   - /// Values are Needs, Excludes, etc.
1378   - std::map<std::string, std::string> labels_;
1379   -
1380   - ///@}
1381   - /// @name Basic
1382   - ///@{
1383   -
1384   - public:
1385   - FormatterBase() = default;
1386   - FormatterBase(const FormatterBase &) = default;
1387   - FormatterBase(FormatterBase &&) = default;
1388   - virtual ~FormatterBase() = default;
1389   -
1390   - /// This is the key method that puts together help
1391   - virtual std::string make_help(const App *, std::string, AppFormatMode) const = 0;
1392   -
1393   - ///@}
1394   - /// @name Setters
1395   - ///@{
1396   -
1397   - /// Set the "REQUIRED" label
1398   - void label(std::string key, std::string val) { labels_[key] = val; }
1399   -
1400   - /// Set the column width
1401   - void column_width(size_t val) { column_width_ = val; }
1402   -
1403   - ///@}
1404   - /// @name Getters
1405   - ///@{
1406   -
1407   - /// Get the current value of a name (REQUIRED, etc.)
1408   - std::string get_label(std::string key) const {
1409   - if(labels_.find(key) == labels_.end())
1410   - return key;
1411   - else
1412   - return labels_.at(key);
1413   - }
1414   -
1415   - /// Get the current column width
1416   - size_t get_column_width() const { return column_width_; }
1417   -
1418   - ///@}
1419   -};
1420   -
1421   -/// This is a specialty override for lambda functions
1422   -class FormatterLambda final : public FormatterBase {
1423   - using funct_t = std::function<std::string(const App *, std::string, AppFormatMode)>;
1424   -
1425   - /// The lambda to hold and run
1426   - funct_t lambda_;
1427   -
1428   - public:
1429   - /// Create a FormatterLambda with a lambda function
1430   - explicit FormatterLambda(funct_t funct) : lambda_(std::move(funct)) {}
1431   -
1432   - /// This will simply call the lambda function
1433   - std::string make_help(const App *app, std::string name, AppFormatMode mode) const override {
1434   - return lambda_(app, name, mode);
1435   - }
1436   -};
1437   -
1438   -/// This is the default Formatter for CLI11. It pretty prints help output, and is broken into quite a few
1439   -/// overridable methods, to be highly customizable with minimal effort.
1440   -class Formatter : public FormatterBase {
1441   - public:
1442   - Formatter() = default;
1443   - Formatter(const Formatter &) = default;
1444   - Formatter(Formatter &&) = default;
1445   -
1446   - /// @name Overridables
1447   - ///@{
1448   -
1449   - /// This prints out a group of options with title
1450   - ///
1451   - virtual std::string make_group(std::string group, bool is_positional, std::vector<const Option *> opts) const;
1452   -
1453   - /// This prints out just the positionals "group"
1454   - virtual std::string make_positionals(const App *app) const;
1455   -
1456   - /// This prints out all the groups of options
1457   - std::string make_groups(const App *app, AppFormatMode mode) const;
1458   -
1459   - /// This prints out all the subcommands
1460   - virtual std::string make_subcommands(const App *app, AppFormatMode mode) const;
1461   -
1462   - /// This prints out a subcommand
1463   - virtual std::string make_subcommand(const App *sub) const;
1464   -
1465   - /// This prints out a subcommand in help-all
1466   - virtual std::string make_expanded(const App *sub) const;
1467   -
1468   - /// This prints out all the groups of options
1469   - virtual std::string make_footer(const App *app) const;
1470   -
1471   - /// This displays the description line
1472   - virtual std::string make_description(const App *app) const;
1473   -
1474   - /// This displays the usage line
1475   - virtual std::string make_usage(const App *app, std::string name) const;
1476   -
1477   - /// This puts everything together
1478   - std::string make_help(const App *, std::string, AppFormatMode) const override;
1479   -
1480   - ///@}
1481   - /// @name Options
1482   - ///@{
1483   -
1484   - /// This prints out an option help line, either positional or optional form
1485   - virtual std::string make_option(const Option *opt, bool is_positional) const {
1486   - std::stringstream out;
1487   - detail::format_help(
1488   - out, make_option_name(opt, is_positional) + make_option_opts(opt), make_option_desc(opt), column_width_);
1489   - return out.str();
1490   - }
1491   -
1492   - /// @brief This is the name part of an option, Default: left column
1493   - virtual std::string make_option_name(const Option *, bool) const;
1494   -
1495   - /// @brief This is the options part of the name, Default: combined into left column
1496   - virtual std::string make_option_opts(const Option *) const;
1497   -
1498   - /// @brief This is the description. Default: Right column, on new line if left column too large
1499   - virtual std::string make_option_desc(const Option *) const;
1500   -
1501   - /// @brief This is used to print the name on the USAGE line
1502   - virtual std::string make_option_usage(const Option *opt) const;
1503   -
1504   - ///@}
1505   -};
1506   -
1507   -} // namespace CLI
1508   -
1509   -// From CLI/Option.hpp:
1510   -
1511   -namespace CLI {
1512   -
1513   -using results_t = std::vector<std::string>;
1514   -using callback_t = std::function<bool(results_t)>;
1515   -
1516   -class Option;
1517   -class App;
1518   -
1519   -using Option_p = std::unique_ptr<Option>;
1520   -
1521   -enum class MultiOptionPolicy { Throw, TakeLast, TakeFirst, Join };
1522   -
1523   -/// This is the CRTP base class for Option and OptionDefaults. It was designed this way
1524   -/// to share parts of the class; an OptionDefaults can copy to an Option.
1525   -template <typename CRTP> class OptionBase {
1526   - friend App;
1527   -
1528   - protected:
1529   - /// The group membership
1530   - std::string group_ = std::string("Options");
1531   -
1532   - /// True if this is a required option
1533   - bool required_{false};
1534   -
1535   - /// Ignore the case when matching (option, not value)
1536   - bool ignore_case_{false};
1537   -
1538   - /// Ignore underscores when matching (option, not value)
1539   - bool ignore_underscore_{false};
1540   -
1541   - /// Allow this option to be given in a configuration file
1542   - bool configurable_{true};
1543   -
1544   - /// Policy for multiple arguments when `expected_ == 1` (can be set on bool flags, too)
1545   - MultiOptionPolicy multi_option_policy_{MultiOptionPolicy::Throw};
1546   -
1547   - /// Copy the contents to another similar class (one based on OptionBase)
1548   - template <typename T> void copy_to(T *other) const {
1549   - other->group(group_);
1550   - other->required(required_);
1551   - other->ignore_case(ignore_case_);
1552   - other->ignore_underscore(ignore_underscore_);
1553   - other->configurable(configurable_);
1554   - other->multi_option_policy(multi_option_policy_);
1555   - }
1556   -
1557   - public:
1558   - // setters
1559   -
1560   - /// Changes the group membership
1561   - CRTP *group(std::string name) {
1562   - group_ = name;
1563   - return static_cast<CRTP *>(this);
1564   - ;
1565   - }
1566   -
1567   - /// Set the option as required
1568   - CRTP *required(bool value = true) {
1569   - required_ = value;
1570   - return static_cast<CRTP *>(this);
1571   - }
1572   -
1573   - /// Support Plumbum term
1574   - CRTP *mandatory(bool value = true) { return required(value); }
1575   -
1576   - // Getters
1577   -
1578   - /// Get the group of this option
1579   - const std::string &get_group() const { return group_; }
1580   -
1581   - /// True if this is a required option
1582   - bool get_required() const { return required_; }
1583   -
1584   - /// The status of ignore case
1585   - bool get_ignore_case() const { return ignore_case_; }
1586   -
1587   - /// The status of ignore_underscore
1588   - bool get_ignore_underscore() const { return ignore_underscore_; }
1589   -
1590   - /// The status of configurable
1591   - bool get_configurable() const { return configurable_; }
1592   -
1593   - /// The status of the multi option policy
1594   - MultiOptionPolicy get_multi_option_policy() const { return multi_option_policy_; }
1595   -
1596   - // Shortcuts for multi option policy
1597   -
1598   - /// Set the multi option policy to take last
1599   - CRTP *take_last() {
1600   - auto self = static_cast<CRTP *>(this);
1601   - self->multi_option_policy(MultiOptionPolicy::TakeLast);
1602   - return self;
1603   - }
1604   -
1605   - /// Set the multi option policy to take last
1606   - CRTP *take_first() {
1607   - auto self = static_cast<CRTP *>(this);
1608   - self->multi_option_policy(MultiOptionPolicy::TakeFirst);
1609   - return self;
1610   - }
1611   -
1612   - /// Set the multi option policy to take last
1613   - CRTP *join() {
1614   - auto self = static_cast<CRTP *>(this);
1615   - self->multi_option_policy(MultiOptionPolicy::Join);
1616   - return self;
1617   - }
1618   -
1619   - /// Allow in a configuration file
1620   - CRTP *configurable(bool value = true) {
1621   - configurable_ = value;
1622   - return static_cast<CRTP *>(this);
1623   - }
1624   -};
1625   -
1626   -/// This is a version of OptionBase that only supports setting values,
1627   -/// for defaults. It is stored as the default option in an App.
1628   -class OptionDefaults : public OptionBase<OptionDefaults> {
1629   - public:
1630   - OptionDefaults() = default;
1631   -
1632   - // Methods here need a different implementation if they are Option vs. OptionDefault
1633   -
1634   - /// Take the last argument if given multiple times
1635   - OptionDefaults *multi_option_policy(MultiOptionPolicy value = MultiOptionPolicy::Throw) {
1636   - multi_option_policy_ = value;
1637   - return this;
1638   - }
1639   -
1640   - /// Ignore the case of the option name
1641   - OptionDefaults *ignore_case(bool value = true) {
1642   - ignore_case_ = value;
1643   - return this;
1644   - }
1645   -
1646   - /// Ignore underscores in the option name
1647   - OptionDefaults *ignore_underscore(bool value = true) {
1648   - ignore_underscore_ = value;
1649   - return this;
1650   - }
1651   -};
1652   -
1653   -class Option : public OptionBase<Option> {
1654   - friend App;
1655   -
1656   - protected:
1657   - /// @name Names
1658   - ///@{
1659   -
1660   - /// A list of the short names (`-a`) without the leading dashes
1661   - std::vector<std::string> snames_;
1662   -
1663   - /// A list of the long names (`--a`) without the leading dashes
1664   - std::vector<std::string> lnames_;
1665   -
1666   - /// A positional name
1667   - std::string pname_;
1668   -
1669   - /// If given, check the environment for this option
1670   - std::string envname_;
1671   -
1672   - ///@}
1673   - /// @name Help
1674   - ///@{
1675   -
1676   - /// The description for help strings
1677   - std::string description_;
1678   -
1679   - /// A human readable default value, usually only set if default is true in creation
1680   - std::string defaultval_;
1681   -
1682   - /// A human readable type value, set when App creates this
1683   - ///
1684   - /// This is a lambda function so "types" can be dynamic, such as when a set prints its contents.
1685   - std::function<std::string()> type_name_{[]() { return std::string(); }};
1686   -
1687   - /// True if this option has a default
1688   - bool default_{false};
1689   -
1690   - ///@}
1691   - /// @name Configuration
1692   - ///@{
1693   -
1694   - /// The number of arguments that make up one option. -1=unlimited (vector-like), 0=flag, 1=normal option,
1695   - /// 2=complex/pair, etc. Set only when the option is created; this is intrinsic to the type. Eventually, -2 may mean
1696   - /// vector of pairs.
1697   - int type_size_{1};
1698   -
1699   - /// The number of expected values, type_size_ must be < 0. Ignored for flag. N < 0 means at least -N values.
1700   - int expected_{1};
1701   -
1702   - /// A list of validators to run on each value parsed
1703   - std::vector<std::function<std::string(std::string &)>> validators_;
1704   -
1705   - /// A list of options that are required with this option
1706   - std::set<Option *> needs_;
1707   -
1708   - /// A list of options that are excluded with this option
1709   - std::set<Option *> excludes_;
1710   -
1711   - ///@}
1712   - /// @name Other
1713   - ///@{
1714   -
1715   - /// Remember the parent app
1716   - App *parent_;
1717   -
1718   - /// Options store a callback to do all the work
1719   - callback_t callback_;
1720   -
1721   - ///@}
1722   - /// @name Parsing results
1723   - ///@{
1724   -
1725   - /// Results of parsing
1726   - results_t results_;
1727   -
1728   - /// Whether the callback has run (needed for INI parsing)
1729   - bool callback_run_{false};
1730   -
1731   - ///@}
1732   -
1733   - /// Making an option by hand is not defined, it must be made by the App class
1734   - Option(std::string option_name,
1735   - std::string description,
1736   - std::function<bool(results_t)> callback,
1737   - bool defaulted,
1738   - App *parent)
1739   - : description_(std::move(description)), default_(defaulted), parent_(parent),
1740   - callback_(callback ? std::move(callback) : [](results_t) { return true; }) {
1741   - std::tie(snames_, lnames_, pname_) = detail::get_names(detail::split_names(option_name));
1742   - }
1743   -
1744   - public:
1745   - /// @name Basic
1746   - ///@{
1747   -
1748   - /// Count the total number of times an option was passed
1749   - size_t count() const { return results_.size(); }
1750   -
1751   - /// True if the option was not passed
1752   - size_t empty() const { return results_.empty(); }
1753   -
1754   - /// This class is true if option is passed.
1755   - operator bool() const { return !empty(); }
1756   -
1757   - /// Clear the parsed results (mostly for testing)
1758   - void clear() { results_.clear(); }
1759   -
1760   - ///@}
1761   - /// @name Setting options
1762   - ///@{
1763   -
1764   - /// Set the number of expected arguments (Flags don't use this)
1765   - Option *expected(int value) {
1766   - // Break if this is a flag
1767   - if(type_size_ == 0)
1768   - throw IncorrectConstruction::SetFlag(get_name(true, true));
1769   -
1770   - // Setting 0 is not allowed
1771   - else if(value == 0)
1772   - throw IncorrectConstruction::Set0Opt(get_name());
1773   -
1774   - // No change is okay, quit now
1775   - else if(expected_ == value)
1776   - return this;
1777   -
1778   - // Type must be a vector
1779   - else if(type_size_ >= 0)
1780   - throw IncorrectConstruction::ChangeNotVector(get_name());
1781   -
1782   - // TODO: Can support multioption for non-1 values (except for join)
1783   - else if(value != 1 && multi_option_policy_ != MultiOptionPolicy::Throw)
1784   - throw IncorrectConstruction::AfterMultiOpt(get_name());
1785   -
1786   - expected_ = value;
1787   - return this;
1788   - }
1789   -
1790   - /// Adds a validator with a built in type name
1791   - Option *check(const Validator &validator) {
1792   - validators_.emplace_back(validator.func);
1793   - if(!validator.tname.empty())
1794   - type_name(validator.tname);
1795   - return this;
1796   - }
1797   -
1798   - /// Adds a validator. Takes a const string& and returns an error message (empty if conversion/check is okay).
1799   - Option *check(std::function<std::string(const std::string &)> validator) {
1800   - validators_.emplace_back(validator);
1801   - return this;
1802   - }
1803   -
1804   - /// Adds a validator-like function that can change result
1805   - Option *transform(std::function<std::string(std::string)> func) {
1806   - validators_.emplace_back([func](std::string &inout) {
1807   - try {
1808   - inout = func(inout);
1809   - } catch(const ValidationError &e) {
1810   - return std::string(e.what());
1811   - }
1812   - return std::string();
1813   - });
1814   - return this;
1815   - }
1816   -
1817   - /// Adds a user supplied function to run on each item passed in (communicate though lambda capture)
1818   - Option *each(std::function<void(std::string)> func) {
1819   - validators_.emplace_back([func](std::string &inout) {
1820   - func(inout);
1821   - return std::string();
1822   - });
1823   - return this;
1824   - }
1825   -
1826   - /// Sets required options
1827   - Option *needs(Option *opt) {
1828   - auto tup = needs_.insert(opt);
1829   - if(!tup.second)
1830   - throw OptionAlreadyAdded::Requires(get_name(), opt->get_name());
1831   - return this;
1832   - }
1833   -
1834   - /// Can find a string if needed
1835   - template <typename T = App> Option *needs(std::string opt_name) {
1836   - for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
1837   - if(opt.get() != this && opt->check_name(opt_name))
1838   - return needs(opt.get());
1839   - throw IncorrectConstruction::MissingOption(opt_name);
1840   - }
1841   -
1842   - /// Any number supported, any mix of string and Opt
1843   - template <typename A, typename B, typename... ARG> Option *needs(A opt, B opt1, ARG... args) {
1844   - needs(opt);
1845   - return needs(opt1, args...);
1846   - }
1847   -
1848   - /// Remove needs link from an option. Returns true if the option really was in the needs list.
1849   - bool remove_needs(Option *opt) {
1850   - auto iterator = std::find(std::begin(needs_), std::end(needs_), opt);
1851   -
1852   - if(iterator != std::end(needs_)) {
1853   - needs_.erase(iterator);
1854   - return true;
1855   - } else {
1856   - return false;
1857   - }
1858   - }
1859   -
1860   - /// Sets excluded options
1861   - Option *excludes(Option *opt) {
1862   - excludes_.insert(opt);
1863   -
1864   - // Help text should be symmetric - excluding a should exclude b
1865   - opt->excludes_.insert(this);
1866   -
1867   - // Ignoring the insert return value, excluding twice is now allowed.
1868   - // (Mostly to allow both directions to be excluded by user, even though the library does it for you.)
1869   -
1870   - return this;
1871   - }
1872   -
1873   - /// Can find a string if needed
1874   - template <typename T = App> Option *excludes(std::string opt_name) {
1875   - for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
1876   - if(opt.get() != this && opt->check_name(opt_name))
1877   - return excludes(opt.get());
1878   - throw IncorrectConstruction::MissingOption(opt_name);
1879   - }
1880   -
1881   - /// Any number supported, any mix of string and Opt
1882   - template <typename A, typename B, typename... ARG> Option *excludes(A opt, B opt1, ARG... args) {
1883   - excludes(opt);
1884   - return excludes(opt1, args...);
1885   - }
1886   -
1887   - /// Remove needs link from an option. Returns true if the option really was in the needs list.
1888   - bool remove_excludes(Option *opt) {
1889   - auto iterator = std::find(std::begin(excludes_), std::end(excludes_), opt);
1890   -
1891   - if(iterator != std::end(excludes_)) {
1892   - excludes_.erase(iterator);
1893   - return true;
1894   - } else {
1895   - return false;
1896   - }
1897   - }
1898   -
1899   - /// Sets environment variable to read if no option given
1900   - Option *envname(std::string name) {
1901   - envname_ = name;
1902   - return this;
1903   - }
1904   -
1905   - /// Ignore case
1906   - ///
1907   - /// The template hides the fact that we don't have the definition of App yet.
1908   - /// You are never expected to add an argument to the template here.
1909   - template <typename T = App> Option *ignore_case(bool value = true) {
1910   - ignore_case_ = value;
1911   - auto *parent = dynamic_cast<T *>(parent_);
1912   -
1913   - for(const Option_p &opt : parent->options_)
1914   - if(opt.get() != this && *opt == *this)
1915   - throw OptionAlreadyAdded(opt->get_name(true, true));
1916   -
1917   - return this;
1918   - }
1919   -
1920   - /// Ignore underscores in the option names
1921   - ///
1922   - /// The template hides the fact that we don't have the definition of App yet.
1923   - /// You are never expected to add an argument to the template here.
1924   - template <typename T = App> Option *ignore_underscore(bool value = true) {
1925   - ignore_underscore_ = value;
1926   - auto *parent = dynamic_cast<T *>(parent_);
1927   - for(const Option_p &opt : parent->options_)
1928   - if(opt.get() != this && *opt == *this)
1929   - throw OptionAlreadyAdded(opt->get_name(true, true));
1930   -
1931   - return this;
1932   - }
1933   -
1934   - /// Take the last argument if given multiple times (or another policy)
1935   - Option *multi_option_policy(MultiOptionPolicy value = MultiOptionPolicy::Throw) {
1936   -
1937   - if(get_items_expected() < 0)
1938   - throw IncorrectConstruction::MultiOptionPolicy(get_name());
1939   - multi_option_policy_ = value;
1940   - return this;
1941   - }
1942   -
1943   - ///@}
1944   - /// @name Accessors
1945   - ///@{
1946   -
1947   - /// The number of arguments the option expects
1948   - int get_type_size() const { return type_size_; }
1949   -
1950   - /// The environment variable associated to this value
1951   - std::string get_envname() const { return envname_; }
1952   -
1953   - /// The set of options needed
1954   - std::set<Option *> get_needs() const { return needs_; }
1955   -
1956   - /// The set of options excluded
1957   - std::set<Option *> get_excludes() const { return excludes_; }
1958   -
1959   - /// The default value (for help printing)
1960   - std::string get_defaultval() const { return defaultval_; }
1961   -
1962   - /// Get the callback function
1963   - callback_t get_callback() const { return callback_; }
1964   -
1965   - /// Get the long names
1966   - const std::vector<std::string> get_lnames() const { return lnames_; }
1967   -
1968   - /// Get the short names
1969   - const std::vector<std::string> get_snames() const { return snames_; }
1970   -
1971   - /// The number of times the option expects to be included
1972   - int get_expected() const { return expected_; }
1973   -
1974   - /// \brief The total number of expected values (including the type)
1975   - /// This is positive if exactly this number is expected, and negative for at least N values
1976   - ///
1977   - /// v = fabs(size_type*expected)
1978   - /// !MultiOptionPolicy::Throw
1979   - /// | Expected < 0 | Expected == 0 | Expected > 0
1980   - /// Size < 0 | -v | 0 | -v
1981   - /// Size == 0 | 0 | 0 | 0
1982   - /// Size > 0 | -v | 0 | -v // Expected must be 1
1983   - ///
1984   - /// MultiOptionPolicy::Throw
1985   - /// | Expected < 0 | Expected == 0 | Expected > 0
1986   - /// Size < 0 | -v | 0 | v
1987   - /// Size == 0 | 0 | 0 | 0
1988   - /// Size > 0 | v | 0 | v // Expected must be 1
1989   - ///
1990   - int get_items_expected() const {
1991   - return std::abs(type_size_ * expected_) *
1992   - ((multi_option_policy_ != MultiOptionPolicy::Throw || (expected_ < 0 && type_size_ < 0) ? -1 : 1));
1993   - }
1994   -
1995   - /// True if this has a default value
1996   - int get_default() const { return default_; }
1997   -
1998   - /// True if the argument can be given directly
1999   - bool get_positional() const { return pname_.length() > 0; }
2000   -
2001   - /// True if option has at least one non-positional name
2002   - bool nonpositional() const { return (snames_.size() + lnames_.size()) > 0; }
2003   -
2004   - /// True if option has description
2005   - bool has_description() const { return description_.length() > 0; }
2006   -
2007   - /// Get the description
2008   - const std::string &get_description() const { return description_; }
2009   -
2010   - /// Set the description
2011   - Option *description(const std::string &description) {
2012   - description_ = description;
2013   - return this;
2014   - }
2015   -
2016   - ///@}
2017   - /// @name Help tools
2018   - ///@{
2019   -
2020   - /// \brief Gets a comma separated list of names.
2021   - /// Will include / prefer the positional name if positional is true.
2022   - /// If all_options is false, pick just the most descriptive name to show.
2023   - /// Use `get_name(true)` to get the positional name (replaces `get_pname`)
2024   - std::string get_name(bool positional = false, //<[input] Show the positional name
2025   - bool all_options = false //<[input] Show every option
2026   - ) const {
2027   -
2028   - if(all_options) {
2029   -
2030   - std::vector<std::string> name_list;
2031   -
2032   - /// The all list will never include a positional unless asked or that's the only name.
2033   - if((positional && pname_.length()) || (snames_.empty() && lnames_.empty()))
2034   - name_list.push_back(pname_);
2035   -
2036   - for(const std::string &sname : snames_)
2037   - name_list.push_back("-" + sname);
2038   -
2039   - for(const std::string &lname : lnames_)
2040   - name_list.push_back("--" + lname);
2041   -
2042   - return detail::join(name_list);
2043   -
2044   - } else {
2045   -
2046   - // This returns the positional name no matter what
2047   - if(positional)
2048   - return pname_;
2049   -
2050   - // Prefer long name
2051   - else if(!lnames_.empty())
2052   - return std::string("--") + lnames_[0];
2053   -
2054   - // Or short name if no long name
2055   - else if(!snames_.empty())
2056   - return std::string("-") + snames_[0];
2057   -
2058   - // If positional is the only name, it's okay to use that
2059   - else
2060   - return pname_;
2061   - }
2062   - }
2063   -
2064   - ///@}
2065   - /// @name Parser tools
2066   - ///@{
2067   -
2068   - /// Process the callback
2069   - void run_callback() {
2070   -
2071   - callback_run_ = true;
2072   -
2073   - // Run the validators (can change the string)
2074   - if(!validators_.empty()) {
2075   - for(std::string &result : results_)
2076   - for(const std::function<std::string(std::string &)> &vali : validators_) {
2077   - std::string err_msg = vali(result);
2078   - if(!err_msg.empty())
2079   - throw ValidationError(get_name(), err_msg);
2080   - }
2081   - }
2082   -
2083   - bool local_result;
2084   -
2085   - // Num items expected or length of vector, always at least 1
2086   - // Only valid for a trimming policy
2087   - int trim_size =
2088   - std::min<int>(std::max<int>(std::abs(get_items_expected()), 1), static_cast<int>(results_.size()));
2089   -
2090   - // Operation depends on the policy setting
2091   - if(multi_option_policy_ == MultiOptionPolicy::TakeLast) {
2092   - // Allow multi-option sizes (including 0)
2093   - results_t partial_result{results_.end() - trim_size, results_.end()};
2094   - local_result = !callback_(partial_result);
2095   -
2096   - } else if(multi_option_policy_ == MultiOptionPolicy::TakeFirst) {
2097   - results_t partial_result{results_.begin(), results_.begin() + trim_size};
2098   - local_result = !callback_(partial_result);
2099   -
2100   - } else if(multi_option_policy_ == MultiOptionPolicy::Join) {
2101   - results_t partial_result = {detail::join(results_, "\n")};
2102   - local_result = !callback_(partial_result);
2103   -
2104   - } else {
2105   - // Exact number required
2106   - if(get_items_expected() > 0) {
2107   - if(results_.size() != static_cast<size_t>(get_items_expected()))
2108   - throw ArgumentMismatch(get_name(), get_items_expected(), results_.size());
2109   - // Variable length list
2110   - } else if(get_items_expected() < 0) {
2111   - // Require that this be a multiple of expected size and at least as many as expected
2112   - if(results_.size() < static_cast<size_t>(-get_items_expected()) ||
2113   - results_.size() % static_cast<size_t>(std::abs(get_type_size())) != 0)
2114   - throw ArgumentMismatch(get_name(), get_items_expected(), results_.size());
2115   - }
2116   - local_result = !callback_(results_);
2117   - }
2118   -
2119   - if(local_result)
2120   - throw ConversionError(get_name(), results_);
2121   - }
2122   -
2123   - /// If options share any of the same names, they are equal (not counting positional)
2124   - bool operator==(const Option &other) const {
2125   - for(const std::string &sname : snames_)
2126   - if(other.check_sname(sname))
2127   - return true;
2128   - for(const std::string &lname : lnames_)
2129   - if(other.check_lname(lname))
2130   - return true;
2131   - // We need to do the inverse, just in case we are ignore_case or ignore underscore
2132   - for(const std::string &sname : other.snames_)
2133   - if(check_sname(sname))
2134   - return true;
2135   - for(const std::string &lname : other.lnames_)
2136   - if(check_lname(lname))
2137   - return true;
2138   - return false;
2139   - }
2140   -
2141   - /// Check a name. Requires "-" or "--" for short / long, supports positional name
2142   - bool check_name(std::string name) const {
2143   -
2144   - if(name.length() > 2 && name.substr(0, 2) == "--")
2145   - return check_lname(name.substr(2));
2146   - else if(name.length() > 1 && name.substr(0, 1) == "-")
2147   - return check_sname(name.substr(1));
2148   - else {
2149   - std::string local_pname = pname_;
2150   - if(ignore_case_) {
2151   - local_pname = detail::to_lower(local_pname);
2152   - name = detail::to_lower(name);
2153   - }
2154   - if(ignore_underscore_) {
2155   - local_pname = detail::remove_underscore(local_pname);
2156   - name = detail::remove_underscore(name);
2157   - }
2158   - return name == local_pname;
2159   - }
2160   - }
2161   -
2162   - /// Requires "-" to be removed from string
2163   - bool check_sname(std::string name) const {
2164   - if(ignore_case_) { // there can be no extra underscores in check_sname
2165   - name = detail::to_lower(name);
2166   - return std::find_if(std::begin(snames_), std::end(snames_), [&name](std::string local_sname) {
2167   - return detail::to_lower(local_sname) == name;
2168   - }) != std::end(snames_);
2169   - } else
2170   - return std::find(std::begin(snames_), std::end(snames_), name) != std::end(snames_);
2171   - }
2172   -
2173   - /// Requires "--" to be removed from string
2174   - bool check_lname(std::string name) const {
2175   - if(ignore_case_) {
2176   - if(ignore_underscore_) {
2177   - name = detail::to_lower(detail::remove_underscore(name));
2178   - return std::find_if(std::begin(lnames_), std::end(lnames_), [&name](std::string local_sname) {
2179   - return detail::to_lower(detail::remove_underscore(local_sname)) == name;
2180   - }) != std::end(lnames_);
2181   - } else {
2182   - name = detail::to_lower(name);
2183   - return std::find_if(std::begin(lnames_), std::end(lnames_), [&name](std::string local_sname) {
2184   - return detail::to_lower(local_sname) == name;
2185   - }) != std::end(lnames_);
2186   - }
2187   -
2188   - } else if(ignore_underscore_) {
2189   - name = detail::remove_underscore(name);
2190   - return std::find_if(std::begin(lnames_), std::end(lnames_), [&name](std::string local_sname) {
2191   - return detail::remove_underscore(local_sname) == name;
2192   - }) != std::end(lnames_);
2193   - } else
2194   - return std::find(std::begin(lnames_), std::end(lnames_), name) != std::end(lnames_);
2195   - }
2196   -
2197   - /// Puts a result at the end
2198   - Option *add_result(std::string s) {
2199   - results_.push_back(s);
2200   - callback_run_ = false;
2201   - return this;
2202   - }
2203   -
2204   - /// Set the results vector all at once
2205   - Option *set_results(std::vector<std::string> result_vector) {
2206   - results_ = std::move(result_vector);
2207   - callback_run_ = false;
2208   - return this;
2209   - }
2210   -
2211   - /// Get a copy of the results
2212   - std::vector<std::string> results() const { return results_; }
2213   -
2214   - /// See if the callback has been run already
2215   - bool get_callback_run() const { return callback_run_; }
2216   -
2217   - ///@}
2218   - /// @name Custom options
2219   - ///@{
2220   -
2221   - /// Set the type function to run when displayed on this option
2222   - Option *type_name_fn(std::function<std::string()> typefun) {
2223   - type_name_ = typefun;
2224   - return this;
2225   - }
2226   -
2227   - /// Set a custom option typestring
2228   - Option *type_name(std::string typeval) {
2229   - type_name_fn([typeval]() { return typeval; });
2230   - return this;
2231   - }
2232   -
2233   - /// Set a custom option size
2234   - Option *type_size(int option_type_size) {
2235   - type_size_ = option_type_size;
2236   - if(type_size_ == 0)
2237   - required_ = false;
2238   - if(option_type_size < 0)
2239   - expected_ = -1;
2240   - return this;
2241   - }
2242   -
2243   - /// Set the default value string representation
2244   - Option *default_str(std::string val) {
2245   - defaultval_ = val;
2246   - return this;
2247   - }
2248   -
2249   - /// Set the default value string representation and evaluate
2250   - Option *default_val(std::string val) {
2251   - default_str(val);
2252   - auto old_results = results_;
2253   - results_ = {val};
2254   - run_callback();
2255   - results_ = std::move(old_results);
2256   - return this;
2257   - }
2258   -
2259   - /// Get the typename for this option
2260   - std::string get_type_name() const { return type_name_(); }
2261   -};
2262   -
2263   -} // namespace CLI
2264   -
2265   -// From CLI/App.hpp:
2266   -
2267   -namespace CLI {
2268   -
2269   -#ifndef CLI11_PARSE
2270   -#define CLI11_PARSE(app, argc, argv) \
2271   - try { \
2272   - (app).parse((argc), (argv)); \
2273   - } catch(const CLI::ParseError &e) { \
2274   - return (app).exit(e); \
2275   - }
2276   -#endif
2277   -
2278   -namespace detail {
2279   -enum class Classifier { NONE, POSITIONAL_MARK, SHORT, LONG, WINDOWS, SUBCOMMAND };
2280   -struct AppFriend;
2281   -} // namespace detail
2282   -
2283   -namespace FailureMessage {
2284   -std::string simple(const App *app, const Error &e);
2285   -std::string help(const App *app, const Error &e);
2286   -} // namespace FailureMessage
2287   -
2288   -class App;
2289   -
2290   -using App_p = std::unique_ptr<App>;
2291   -
2292   -/// Creates a command line program, with very few defaults.
2293   -/** To use, create a new `Program()` instance with `argc`, `argv`, and a help description. The templated
2294   - * add_option methods make it easy to prepare options. Remember to call `.start` before starting your
2295   - * program, so that the options can be evaluated and the help option doesn't accidentally run your program. */
2296   -class App {
2297   - friend Option;
2298   - friend detail::AppFriend;
2299   -
2300   - protected:
2301   - // This library follows the Google style guide for member names ending in underscores
2302   -
2303   - /// @name Basics
2304   - ///@{
2305   -
2306   - /// Subcommand name or program name (from parser if name is empty)
2307   - std::string name_;
2308   -
2309   - /// Description of the current program/subcommand
2310   - std::string description_;
2311   -
2312   - /// If true, allow extra arguments (ie, don't throw an error). INHERITABLE
2313   - bool allow_extras_{false};
2314   -
2315   - /// If true, allow extra arguments in the ini file (ie, don't throw an error). INHERITABLE
2316   - bool allow_config_extras_{false};
2317   -
2318   - /// If true, return immediately on an unrecognised option (implies allow_extras) INHERITABLE
2319   - bool prefix_command_{false};
2320   -
2321   - /// This is a function that runs when complete. Great for subcommands. Can throw.
2322   - std::function<void()> callback_;
2323   -
2324   - ///@}
2325   - /// @name Options
2326   - ///@{
2327   -
2328   - /// The default values for options, customizable and changeable INHERITABLE
2329   - OptionDefaults option_defaults_;
2330   -
2331   - /// The list of options, stored locally
2332   - std::vector<Option_p> options_;
2333   -
2334   - ///@}
2335   - /// @name Help
2336   - ///@{
2337   -
2338   - /// Footer to put after all options in the help output INHERITABLE
2339   - std::string footer_;
2340   -
2341   - /// A pointer to the help flag if there is one INHERITABLE
2342   - Option *help_ptr_{nullptr};
2343   -
2344   - /// A pointer to the help all flag if there is one INHERITABLE
2345   - Option *help_all_ptr_{nullptr};
2346   -
2347   - /// This is the formatter for help printing. Default provided. INHERITABLE (same pointer)
2348   - std::shared_ptr<FormatterBase> formatter_{new Formatter()};
2349   -
2350   - /// The error message printing function INHERITABLE
2351   - std::function<std::string(const App *, const Error &e)> failure_message_ = FailureMessage::simple;
2352   -
2353   - ///@}
2354   - /// @name Parsing
2355   - ///@{
2356   -
2357   - using missing_t = std::vector<std::pair<detail::Classifier, std::string>>;
2358   -
2359   - /// Pair of classifier, string for missing options. (extra detail is removed on returning from parse)
2360   - ///
2361   - /// This is faster and cleaner than storing just a list of strings and reparsing. This may contain the -- separator.
2362   - missing_t missing_;
2363   -
2364   - /// This is a list of pointers to options with the original parse order
2365   - std::vector<Option *> parse_order_;
2366   -
2367   - /// This is a list of the subcommands collected, in order
2368   - std::vector<App *> parsed_subcommands_;
2369   -
2370   - ///@}
2371   - /// @name Subcommands
2372   - ///@{
2373   -
2374   - /// Storage for subcommand list
2375   - std::vector<App_p> subcommands_;
2376   -
2377   - /// If true, the program name is not case sensitive INHERITABLE
2378   - bool ignore_case_{false};
2379   -
2380   - /// If true, the program should ignore underscores INHERITABLE
2381   - bool ignore_underscore_{false};
2382   -
2383   - /// Allow subcommand fallthrough, so that parent commands can collect commands after subcommand. INHERITABLE
2384   - bool fallthrough_{false};
2385   -
2386   - /// Allow '/' for options for Windows like options. Defaults to true on Windows, false otherwise. INHERITABLE
2387   - bool allow_windows_style_options_{
2388   -#ifdef _WIN32
2389   - true
2390   -#else
2391   - false
2392   -#endif
2393   - };
2394   -
2395   - /// A pointer to the parent if this is a subcommand
2396   - App *parent_{nullptr};
2397   -
2398   - /// Counts the number of times this command/subcommand was parsed
2399   - size_t parsed_ = 0;
2400   -
2401   - /// Minimum required subcommands (not inheritable!)
2402   - size_t require_subcommand_min_ = 0;
2403   -
2404   - /// Max number of subcommands allowed (parsing stops after this number). 0 is unlimited INHERITABLE
2405   - size_t require_subcommand_max_ = 0;
2406   -
2407   - /// The group membership INHERITABLE
2408   - std::string group_{"Subcommands"};
2409   -
2410   - ///@}
2411   - /// @name Config
2412   - ///@{
2413   -
2414   - /// The name of the connected config file
2415   - std::string config_name_;
2416   -
2417   - /// True if ini is required (throws if not present), if false simply keep going.
2418   - bool config_required_{false};
2419   -
2420   - /// Pointer to the config option
2421   - Option *config_ptr_{nullptr};
2422   -
2423   - /// This is the formatter for help printing. Default provided. INHERITABLE (same pointer)
2424   - std::shared_ptr<Config> config_formatter_{new ConfigINI()};
2425   -
2426   - ///@}
2427   -
2428   - /// Special private constructor for subcommand
2429   - App(std::string description, std::string app_name, App *parent)
2430   - : name_(std::move(app_name)), description_(std::move(description)), parent_(parent) {
2431   - // Inherit if not from a nullptr
2432   - if(parent_ != nullptr) {
2433   - if(parent_->help_ptr_ != nullptr)
2434   - set_help_flag(parent_->help_ptr_->get_name(false, true), parent_->help_ptr_->get_description());
2435   - if(parent_->help_all_ptr_ != nullptr)
2436   - set_help_all_flag(parent_->help_all_ptr_->get_name(false, true),
2437   - parent_->help_all_ptr_->get_description());
2438   -
2439   - /// OptionDefaults
2440   - option_defaults_ = parent_->option_defaults_;
2441   -
2442   - // INHERITABLE
2443   - failure_message_ = parent_->failure_message_;
2444   - allow_extras_ = parent_->allow_extras_;
2445   - allow_config_extras_ = parent_->allow_config_extras_;
2446   - prefix_command_ = parent_->prefix_command_;
2447   - ignore_case_ = parent_->ignore_case_;
2448   - ignore_underscore_ = parent_->ignore_underscore_;
2449   - fallthrough_ = parent_->fallthrough_;
2450   - allow_windows_style_options_ = parent_->allow_windows_style_options_;
2451   - group_ = parent_->group_;
2452   - footer_ = parent_->footer_;
2453   - formatter_ = parent_->formatter_;
2454   - config_formatter_ = parent_->config_formatter_;
2455   - require_subcommand_max_ = parent_->require_subcommand_max_;
2456   - }
2457   - }
2458   -
2459   - public:
2460   - /// @name Basic
2461   - ///@{
2462   -
2463   - /// Create a new program. Pass in the same arguments as main(), along with a help string.
2464   - explicit App(std::string description = "", std::string app_name = "") : App(description, app_name, nullptr) {
2465   - set_help_flag("-h,--help", "Print this help message and exit");
2466   - }
2467   -
2468   - /// virtual destructor
2469   - virtual ~App() = default;
2470   -
2471   - /// Set a callback for the end of parsing.
2472   - ///
2473   - /// Due to a bug in c++11,
2474   - /// it is not possible to overload on std::function (fixed in c++14
2475   - /// and backported to c++11 on newer compilers). Use capture by reference
2476   - /// to get a pointer to App if needed.
2477   - App *callback(std::function<void()> app_callback) {
2478   - callback_ = std::move(app_callback);
2479   - return this;
2480   - }
2481   -
2482   - /// Set a name for the app (empty will use parser to set the name)
2483   - App *name(std::string app_name = "") {
2484   - name_ = app_name;
2485   - return this;
2486   - }
2487   -
2488   - /// Remove the error when extras are left over on the command line.
2489   - App *allow_extras(bool allow = true) {
2490   - allow_extras_ = allow;
2491   - return this;
2492   - }
2493   -
2494   - /// Remove the error when extras are left over on the command line.
2495   - /// Will also call App::allow_extras().
2496   - App *allow_config_extras(bool allow = true) {
2497   - allow_extras(allow);
2498   - allow_config_extras_ = allow;
2499   - return this;
2500   - }
2501   -
2502   - /// Do not parse anything after the first unrecognized option and return
2503   - App *prefix_command(bool allow = true) {
2504   - prefix_command_ = allow;
2505   - return this;
2506   - }
2507   -
2508   - /// Ignore case. Subcommands inherit value.
2509   - App *ignore_case(bool value = true) {
2510   - ignore_case_ = value;
2511   - if(parent_ != nullptr) {
2512   - for(const auto &subc : parent_->subcommands_) {
2513   - if(subc.get() != this && (this->check_name(subc->name_) || subc->check_name(this->name_)))
2514   - throw OptionAlreadyAdded(subc->name_);
2515   - }
2516   - }
2517   - return this;
2518   - }
2519   -
2520   - /// Allow windows style options, such as `/opt`. First matching short or long name used. Subcommands inherit value.
2521   - App *allow_windows_style_options(bool value = true) {
2522   - allow_windows_style_options_ = value;
2523   - return this;
2524   - }
2525   -
2526   - /// Ignore underscore. Subcommands inherit value.
2527   - App *ignore_underscore(bool value = true) {
2528   - ignore_underscore_ = value;
2529   - if(parent_ != nullptr) {
2530   - for(const auto &subc : parent_->subcommands_) {
2531   - if(subc.get() != this && (this->check_name(subc->name_) || subc->check_name(this->name_)))
2532   - throw OptionAlreadyAdded(subc->name_);
2533   - }
2534   - }
2535   - return this;
2536   - }
2537   -
2538   - /// Set the help formatter
2539   - App *formatter(std::shared_ptr<FormatterBase> fmt) {
2540   - formatter_ = fmt;
2541   - return this;
2542   - }
2543   -
2544   - /// Set the help formatter
2545   - App *formatter_fn(std::function<std::string(const App *, std::string, AppFormatMode)> fmt) {
2546   - formatter_ = std::make_shared<FormatterLambda>(fmt);
2547   - return this;
2548   - }
2549   -
2550   - /// Set the config formatter
2551   - App *config_formatter(std::shared_ptr<Config> fmt) {
2552   - config_formatter_ = fmt;
2553   - return this;
2554   - }
2555   -
2556   - /// Check to see if this subcommand was parsed, true only if received on command line.
2557   - bool parsed() const { return parsed_ > 0; }
2558   -
2559   - /// Get the OptionDefault object, to set option defaults
2560   - OptionDefaults *option_defaults() { return &option_defaults_; }
2561   -
2562   - ///@}
2563   - /// @name Adding options
2564   - ///@{
2565   -
2566   - /// Add an option, will automatically understand the type for common types.
2567   - ///
2568   - /// To use, create a variable with the expected type, and pass it in after the name.
2569   - /// After start is called, you can use count to see if the value was passed, and
2570   - /// the value will be initialized properly. Numbers, vectors, and strings are supported.
2571   - ///
2572   - /// ->required(), ->default, and the validators are options,
2573   - /// The positional options take an optional number of arguments.
2574   - ///
2575   - /// For example,
2576   - ///
2577   - /// std::string filename;
2578   - /// program.add_option("filename", filename, "description of filename");
2579   - ///
2580   - Option *add_option(std::string option_name,
2581   - callback_t option_callback,
2582   - std::string description = "",
2583   - bool defaulted = false) {
2584   - Option myopt{option_name, description, option_callback, defaulted, this};
2585   -
2586   - if(std::find_if(std::begin(options_), std::end(options_), [&myopt](const Option_p &v) {
2587   - return *v == myopt;
2588   - }) == std::end(options_)) {
2589   - options_.emplace_back();
2590   - Option_p &option = options_.back();
2591   - option.reset(new Option(option_name, description, option_callback, defaulted, this));
2592   - option_defaults_.copy_to(option.get());
2593   - return option.get();
2594   - } else
2595   - throw OptionAlreadyAdded(myopt.get_name());
2596   - }
2597   -
2598   - /// Add option for non-vectors (duplicate copy needed without defaulted to avoid `iostream << value`)
2599   - template <typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy>
2600   - Option *add_option(std::string option_name,
2601   - T &variable, ///< The variable to set
2602   - std::string description = "") {
2603   -
2604   - CLI::callback_t fun = [&variable](CLI::results_t res) { return detail::lexical_cast(res[0], variable); };
2605   -
2606   - Option *opt = add_option(option_name, fun, description, false);
2607   - opt->type_name(detail::type_name<T>());
2608   - return opt;
2609   - }
2610   -
2611   - /// Add option for non-vectors with a default print
2612   - template <typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy>
2613   - Option *add_option(std::string option_name,
2614   - T &variable, ///< The variable to set
2615   - std::string description,
2616   - bool defaulted) {
2617   -
2618   - CLI::callback_t fun = [&variable](CLI::results_t res) { return detail::lexical_cast(res[0], variable); };
2619   -
2620   - Option *opt = add_option(option_name, fun, description, defaulted);
2621   - opt->type_name(detail::type_name<T>());
2622   - if(defaulted) {
2623   - std::stringstream out;
2624   - out << variable;
2625   - opt->default_str(out.str());
2626   - }
2627   - return opt;
2628   - }
2629   -
2630   - /// Add option for vectors (no default)
2631   - template <typename T>
2632   - Option *add_option(std::string option_name,
2633   - std::vector<T> &variable, ///< The variable vector to set
2634   - std::string description = "") {
2635   -
2636   - CLI::callback_t fun = [&variable](CLI::results_t res) {
2637   - bool retval = true;
2638   - variable.clear();
2639   - for(const auto &a : res) {
2640   - variable.emplace_back();
2641   - retval &= detail::lexical_cast(a, variable.back());
2642   - }
2643   - return (!variable.empty()) && retval;
2644   - };
2645   -
2646   - Option *opt = add_option(option_name, fun, description, false);
2647   - opt->type_name(detail::type_name<T>())->type_size(-1);
2648   - return opt;
2649   - }
2650   -
2651   - /// Add option for vectors
2652   - template <typename T>
2653   - Option *add_option(std::string option_name,
2654   - std::vector<T> &variable, ///< The variable vector to set
2655   - std::string description,
2656   - bool defaulted) {
2657   -
2658   - CLI::callback_t fun = [&variable](CLI::results_t res) {
2659   - bool retval = true;
2660   - variable.clear();
2661   - for(const auto &a : res) {
2662   - variable.emplace_back();
2663   - retval &= detail::lexical_cast(a, variable.back());
2664   - }
2665   - return (!variable.empty()) && retval;
2666   - };
2667   -
2668   - Option *opt = add_option(option_name, fun, description, defaulted);
2669   - opt->type_name(detail::type_name<T>())->type_size(-1);
2670   - if(defaulted)
2671   - opt->default_str("[" + detail::join(variable) + "]");
2672   - return opt;
2673   - }
2674   -
2675   - /// Set a help flag, replace the existing one if present
2676   - Option *set_help_flag(std::string flag_name = "", std::string description = "") {
2677   - if(help_ptr_ != nullptr) {
2678   - remove_option(help_ptr_);
2679   - help_ptr_ = nullptr;
2680   - }
2681   -
2682   - // Empty name will simply remove the help flag
2683   - if(!flag_name.empty()) {
2684   - help_ptr_ = add_flag(flag_name, description);
2685   - help_ptr_->configurable(false);
2686   - }
2687   -
2688   - return help_ptr_;
2689   - }
2690   -
2691   - /// Set a help all flag, replaced the existing one if present
2692   - Option *set_help_all_flag(std::string help_name = "", std::string description = "") {
2693   - if(help_all_ptr_ != nullptr) {
2694   - remove_option(help_all_ptr_);
2695   - help_all_ptr_ = nullptr;
2696   - }
2697   -
2698   - // Empty name will simply remove the help all flag
2699   - if(!help_name.empty()) {
2700   - help_all_ptr_ = add_flag(help_name, description);
2701   - help_all_ptr_->configurable(false);
2702   - }
2703   -
2704   - return help_all_ptr_;
2705   - }
2706   -
2707   - /// Add option for flag
2708   - Option *add_flag(std::string flag_name, std::string description = "") {
2709   - CLI::callback_t fun = [](CLI::results_t) { return true; };
2710   -
2711   - Option *opt = add_option(flag_name, fun, description, false);
2712   - if(opt->get_positional())
2713   - throw IncorrectConstruction::PositionalFlag(flag_name);
2714   - opt->type_size(0);
2715   - return opt;
2716   - }
2717   -
2718   - /// Add option for flag integer
2719   - template <typename T,
2720   - enable_if_t<std::is_integral<T>::value && !is_bool<T>::value, detail::enabler> = detail::dummy>
2721   - Option *add_flag(std::string flag_name,
2722   - T &flag_count, ///< A variable holding the count
2723   - std::string description = "") {
2724   -
2725   - flag_count = 0;
2726   - CLI::callback_t fun = [&flag_count](CLI::results_t res) {
2727   - flag_count = static_cast<T>(res.size());
2728   - return true;
2729   - };
2730   -
2731   - Option *opt = add_option(flag_name, fun, description, false);
2732   - if(opt->get_positional())
2733   - throw IncorrectConstruction::PositionalFlag(flag_name);
2734   - opt->type_size(0);
2735   - return opt;
2736   - }
2737   -
2738   - /// Bool version - defaults to allowing multiple passings, but can be forced to one if
2739   - /// `multi_option_policy(CLI::MultiOptionPolicy::Throw)` is used.
2740   - template <typename T, enable_if_t<is_bool<T>::value, detail::enabler> = detail::dummy>
2741   - Option *add_flag(std::string flag_name,
2742   - T &flag_count, ///< A variable holding true if passed
2743   - std::string description = "") {
2744   -
2745   - flag_count = false;
2746   - CLI::callback_t fun = [&flag_count](CLI::results_t res) {
2747   - flag_count = true;
2748   - return res.size() == 1;
2749   - };
2750   -
2751   - Option *opt = add_option(flag_name, fun, description, false);
2752   - if(opt->get_positional())
2753   - throw IncorrectConstruction::PositionalFlag(flag_name);
2754   - opt->type_size(0);
2755   - opt->multi_option_policy(CLI::MultiOptionPolicy::TakeLast);
2756   - return opt;
2757   - }
2758   -
2759   - /// Add option for callback
2760   - Option *add_flag_function(std::string flag_name,
2761   - std::function<void(size_t)> function, ///< A function to call, void(size_t)
2762   - std::string description = "") {
2763   -
2764   - CLI::callback_t fun = [function](CLI::results_t res) {
2765   - function(res.size());
2766   - return true;
2767   - };
2768   -
2769   - Option *opt = add_option(flag_name, fun, description, false);
2770   - if(opt->get_positional())
2771   - throw IncorrectConstruction::PositionalFlag(flag_name);
2772   - opt->type_size(0);
2773   - return opt;
2774   - }
2775   -
2776   -#ifdef CLI11_CPP14
2777   - /// Add option for callback (C++14 or better only)
2778   - Option *add_flag(std::string flag_name,
2779   - std::function<void(size_t)> function, ///< A function to call, void(size_t)
2780   - std::string description = "") {
2781   - return add_flag_function(flag_name, std::move(function), description);
2782   - }
2783   -#endif
2784   -
2785   - /// Add set of options (No default, temp reference, such as an inline set)
2786   - template <typename T>
2787   - Option *add_set(std::string option_name,
2788   - T &member, ///< The selected member of the set
2789   - std::set<T> options, ///< The set of possibilities
2790   - std::string description = "") {
2791   -
2792   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
2793   - CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
2794   - bool retval = detail::lexical_cast(res[0], member);
2795   - if(!retval)
2796   - throw ConversionError(res[0], simple_name);
2797   - return std::find(std::begin(options), std::end(options), member) != std::end(options);
2798   - };
2799   -
2800   - Option *opt = add_option(option_name, fun, description, false);
2801   - std::string typeval = detail::type_name<T>();
2802   - typeval += " in {" + detail::join(options) + "}";
2803   - opt->type_name(typeval);
2804   - return opt;
2805   - }
2806   -
2807   - /// Add set of options (No default, set can be changed afterwords - do not destroy the set)
2808   - template <typename T>
2809   - Option *add_mutable_set(std::string option_name,
2810   - T &member, ///< The selected member of the set
2811   - const std::set<T> &options, ///< The set of possibilities
2812   - std::string description = "") {
2813   -
2814   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
2815   - CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
2816   - bool retval = detail::lexical_cast(res[0], member);
2817   - if(!retval)
2818   - throw ConversionError(res[0], simple_name);
2819   - return std::find(std::begin(options), std::end(options), member) != std::end(options);
2820   - };
2821   -
2822   - Option *opt = add_option(option_name, fun, description, false);
2823   - opt->type_name_fn(
2824   - [&options]() { return std::string(detail::type_name<T>()) + " in {" + detail::join(options) + "}"; });
2825   -
2826   - return opt;
2827   - }
2828   -
2829   - /// Add set of options (with default, static set, such as an inline set)
2830   - template <typename T>
2831   - Option *add_set(std::string option_name,
2832   - T &member, ///< The selected member of the set
2833   - std::set<T> options, ///< The set of possibilities
2834   - std::string description,
2835   - bool defaulted) {
2836   -
2837   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
2838   - CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
2839   - bool retval = detail::lexical_cast(res[0], member);
2840   - if(!retval)
2841   - throw ConversionError(res[0], simple_name);
2842   - return std::find(std::begin(options), std::end(options), member) != std::end(options);
2843   - };
2844   -
2845   - Option *opt = add_option(option_name, fun, description, defaulted);
2846   - std::string typeval = detail::type_name<T>();
2847   - typeval += " in {" + detail::join(options) + "}";
2848   - opt->type_name(typeval);
2849   - if(defaulted) {
2850   - std::stringstream out;
2851   - out << member;
2852   - opt->default_str(out.str());
2853   - }
2854   - return opt;
2855   - }
2856   -
2857   - /// Add set of options (with default, set can be changed afterwards - do not destroy the set)
2858   - template <typename T>
2859   - Option *add_mutable_set(std::string option_name,
2860   - T &member, ///< The selected member of the set
2861   - const std::set<T> &options, ///< The set of possibilities
2862   - std::string description,
2863   - bool defaulted) {
2864   -
2865   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
2866   - CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
2867   - bool retval = detail::lexical_cast(res[0], member);
2868   - if(!retval)
2869   - throw ConversionError(res[0], simple_name);
2870   - return std::find(std::begin(options), std::end(options), member) != std::end(options);
2871   - };
2872   -
2873   - Option *opt = add_option(option_name, fun, description, defaulted);
2874   - opt->type_name_fn(
2875   - [&options]() { return std::string(detail::type_name<T>()) + " in {" + detail::join(options) + "}"; });
2876   - if(defaulted) {
2877   - std::stringstream out;
2878   - out << member;
2879   - opt->default_str(out.str());
2880   - }
2881   - return opt;
2882   - }
2883   -
2884   - /// Add set of options, string only, ignore case (no default, static set)
2885   - Option *add_set_ignore_case(std::string option_name,
2886   - std::string &member, ///< The selected member of the set
2887   - std::set<std::string> options, ///< The set of possibilities
2888   - std::string description = "") {
2889   -
2890   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
2891   - CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
2892   - member = detail::to_lower(res[0]);
2893   - auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
2894   - return detail::to_lower(val) == member;
2895   - });
2896   - if(iter == std::end(options))
2897   - throw ConversionError(member, simple_name);
2898   - else {
2899   - member = *iter;
2900   - return true;
2901   - }
2902   - };
2903   -
2904   - Option *opt = add_option(option_name, fun, description, false);
2905   - std::string typeval = detail::type_name<std::string>();
2906   - typeval += " in {" + detail::join(options) + "}";
2907   - opt->type_name(typeval);
2908   -
2909   - return opt;
2910   - }
2911   -
2912   - /// Add set of options, string only, ignore case (no default, set can be changed afterwards - do not destroy the
2913   - /// set)
2914   - Option *add_mutable_set_ignore_case(std::string option_name,
2915   - std::string &member, ///< The selected member of the set
2916   - const std::set<std::string> &options, ///< The set of possibilities
2917   - std::string description = "") {
2918   -
2919   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
2920   - CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
2921   - member = detail::to_lower(res[0]);
2922   - auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
2923   - return detail::to_lower(val) == member;
2924   - });
2925   - if(iter == std::end(options))
2926   - throw ConversionError(member, simple_name);
2927   - else {
2928   - member = *iter;
2929   - return true;
2930   - }
2931   - };
2932   -
2933   - Option *opt = add_option(option_name, fun, description, false);
2934   - opt->type_name_fn([&options]() {
2935   - return std::string(detail::type_name<std::string>()) + " in {" + detail::join(options) + "}";
2936   - });
2937   -
2938   - return opt;
2939   - }
2940   -
2941   - /// Add set of options, string only, ignore case (default, static set)
2942   - Option *add_set_ignore_case(std::string option_name,
2943   - std::string &member, ///< The selected member of the set
2944   - std::set<std::string> options, ///< The set of possibilities
2945   - std::string description,
2946   - bool defaulted) {
2947   -
2948   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
2949   - CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
2950   - member = detail::to_lower(res[0]);
2951   - auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
2952   - return detail::to_lower(val) == member;
2953   - });
2954   - if(iter == std::end(options))
2955   - throw ConversionError(member, simple_name);
2956   - else {
2957   - member = *iter;
2958   - return true;
2959   - }
2960   - };
2961   -
2962   - Option *opt = add_option(option_name, fun, description, defaulted);
2963   - std::string typeval = detail::type_name<std::string>();
2964   - typeval += " in {" + detail::join(options) + "}";
2965   - opt->type_name(typeval);
2966   - if(defaulted) {
2967   - opt->default_str(member);
2968   - }
2969   - return opt;
2970   - }
2971   -
2972   - /// Add set of options, string only, ignore case (default, set can be changed afterwards - do not destroy the set)
2973   - Option *add_mutable_set_ignore_case(std::string option_name,
2974   - std::string &member, ///< The selected member of the set
2975   - const std::set<std::string> &options, ///< The set of possibilities
2976   - std::string description,
2977   - bool defaulted) {
2978   -
2979   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
2980   - CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
2981   - member = detail::to_lower(res[0]);
2982   - auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
2983   - return detail::to_lower(val) == member;
2984   - });
2985   - if(iter == std::end(options))
2986   - throw ConversionError(member, simple_name);
2987   - else {
2988   - member = *iter;
2989   - return true;
2990   - }
2991   - };
2992   -
2993   - Option *opt = add_option(option_name, fun, description, defaulted);
2994   - opt->type_name_fn([&options]() {
2995   - return std::string(detail::type_name<std::string>()) + " in {" + detail::join(options) + "}";
2996   - });
2997   - if(defaulted) {
2998   - opt->default_str(member);
2999   - }
3000   - return opt;
3001   - }
3002   -
3003   - /// Add set of options, string only, ignore underscore (no default, static set)
3004   - Option *add_set_ignore_underscore(std::string option_name,
3005   - std::string &member, ///< The selected member of the set
3006   - std::set<std::string> options, ///< The set of possibilities
3007   - std::string description = "") {
3008   -
3009   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
3010   - CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
3011   - member = detail::remove_underscore(res[0]);
3012   - auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
3013   - return detail::remove_underscore(val) == member;
3014   - });
3015   - if(iter == std::end(options))
3016   - throw ConversionError(member, simple_name);
3017   - else {
3018   - member = *iter;
3019   - return true;
3020   - }
3021   - };
3022   -
3023   - Option *opt = add_option(option_name, fun, description, false);
3024   - std::string typeval = detail::type_name<std::string>();
3025   - typeval += " in {" + detail::join(options) + "}";
3026   - opt->type_name(typeval);
3027   -
3028   - return opt;
3029   - }
3030   -
3031   - /// Add set of options, string only, ignore underscore (no default, set can be changed afterwards - do not destroy
3032   - /// the set)
3033   - Option *add_mutable_set_ignore_underscore(std::string option_name,
3034   - std::string &member, ///< The selected member of the set
3035   - const std::set<std::string> &options, ///< The set of possibilities
3036   - std::string description = "") {
3037   -
3038   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
3039   - CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
3040   - member = detail::remove_underscore(res[0]);
3041   - auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
3042   - return detail::remove_underscore(val) == member;
3043   - });
3044   - if(iter == std::end(options))
3045   - throw ConversionError(member, simple_name);
3046   - else {
3047   - member = *iter;
3048   - return true;
3049   - }
3050   - };
3051   -
3052   - Option *opt = add_option(option_name, fun, description, false);
3053   - opt->type_name_fn([&options]() {
3054   - return std::string(detail::type_name<std::string>()) + " in {" + detail::join(options) + "}";
3055   - });
3056   -
3057   - return opt;
3058   - }
3059   -
3060   - /// Add set of options, string only, ignore underscore (default, static set)
3061   - Option *add_set_ignore_underscore(std::string option_name,
3062   - std::string &member, ///< The selected member of the set
3063   - std::set<std::string> options, ///< The set of possibilities
3064   - std::string description,
3065   - bool defaulted) {
3066   -
3067   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
3068   - CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
3069   - member = detail::remove_underscore(res[0]);
3070   - auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
3071   - return detail::remove_underscore(val) == member;
3072   - });
3073   - if(iter == std::end(options))
3074   - throw ConversionError(member, simple_name);
3075   - else {
3076   - member = *iter;
3077   - return true;
3078   - }
3079   - };
3080   -
3081   - Option *opt = add_option(option_name, fun, description, defaulted);
3082   - std::string typeval = detail::type_name<std::string>();
3083   - typeval += " in {" + detail::join(options) + "}";
3084   - opt->type_name(typeval);
3085   - if(defaulted) {
3086   - opt->default_str(member);
3087   - }
3088   - return opt;
3089   - }
3090   -
3091   - /// Add set of options, string only, ignore underscore (default, set can be changed afterwards - do not destroy the
3092   - /// set)
3093   - Option *add_mutable_set_ignore_underscore(std::string option_name,
3094   - std::string &member, ///< The selected member of the set
3095   - const std::set<std::string> &options, ///< The set of possibilities
3096   - std::string description,
3097   - bool defaulted) {
3098   -
3099   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
3100   - CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
3101   - member = detail::remove_underscore(res[0]);
3102   - auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
3103   - return detail::remove_underscore(val) == member;
3104   - });
3105   - if(iter == std::end(options))
3106   - throw ConversionError(member, simple_name);
3107   - else {
3108   - member = *iter;
3109   - return true;
3110   - }
3111   - };
3112   -
3113   - Option *opt = add_option(option_name, fun, description, defaulted);
3114   - opt->type_name_fn([&options]() {
3115   - return std::string(detail::type_name<std::string>()) + " in {" + detail::join(options) + "}";
3116   - });
3117   - if(defaulted) {
3118   - opt->default_str(member);
3119   - }
3120   - return opt;
3121   - }
3122   -
3123   - /// Add set of options, string only, ignore underscore and case (no default, static set)
3124   - Option *add_set_ignore_case_underscore(std::string option_name,
3125   - std::string &member, ///< The selected member of the set
3126   - std::set<std::string> options, ///< The set of possibilities
3127   - std::string description = "") {
3128   -
3129   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
3130   - CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
3131   - member = detail::to_lower(detail::remove_underscore(res[0]));
3132   - auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
3133   - return detail::to_lower(detail::remove_underscore(val)) == member;
3134   - });
3135   - if(iter == std::end(options))
3136   - throw ConversionError(member, simple_name);
3137   - else {
3138   - member = *iter;
3139   - return true;
3140   - }
3141   - };
3142   -
3143   - Option *opt = add_option(option_name, fun, description, false);
3144   - std::string typeval = detail::type_name<std::string>();
3145   - typeval += " in {" + detail::join(options) + "}";
3146   - opt->type_name(typeval);
3147   -
3148   - return opt;
3149   - }
3150   -
3151   - /// Add set of options, string only, ignore underscore and case (no default, set can be changed afterwards - do not
3152   - /// destroy the set)
3153   - Option *add_mutable_set_ignore_case_underscore(std::string option_name,
3154   - std::string &member, ///< The selected member of the set
3155   - const std::set<std::string> &options, ///< The set of possibilities
3156   - std::string description = "") {
3157   -
3158   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
3159   - CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
3160   - member = detail::to_lower(detail::remove_underscore(res[0]));
3161   - auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
3162   - return detail::to_lower(detail::remove_underscore(val)) == member;
3163   - });
3164   - if(iter == std::end(options))
3165   - throw ConversionError(member, simple_name);
3166   - else {
3167   - member = *iter;
3168   - return true;
3169   - }
3170   - };
3171   -
3172   - Option *opt = add_option(option_name, fun, description, false);
3173   - opt->type_name_fn([&options]() {
3174   - return std::string(detail::type_name<std::string>()) + " in {" + detail::join(options) + "}";
3175   - });
3176   -
3177   - return opt;
3178   - }
3179   -
3180   - /// Add set of options, string only, ignore underscore and case (default, static set)
3181   - Option *add_set_ignore_case_underscore(std::string option_name,
3182   - std::string &member, ///< The selected member of the set
3183   - std::set<std::string> options, ///< The set of possibilities
3184   - std::string description,
3185   - bool defaulted) {
3186   -
3187   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
3188   - CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
3189   - member = detail::to_lower(detail::remove_underscore(res[0]));
3190   - auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
3191   - return detail::to_lower(detail::remove_underscore(val)) == member;
3192   - });
3193   - if(iter == std::end(options))
3194   - throw ConversionError(member, simple_name);
3195   - else {
3196   - member = *iter;
3197   - return true;
3198   - }
3199   - };
3200   -
3201   - Option *opt = add_option(option_name, fun, description, defaulted);
3202   - std::string typeval = detail::type_name<std::string>();
3203   - typeval += " in {" + detail::join(options) + "}";
3204   - opt->type_name(typeval);
3205   - if(defaulted) {
3206   - opt->default_str(member);
3207   - }
3208   - return opt;
3209   - }
3210   -
3211   - /// Add set of options, string only, ignore underscore and case (default, set can be changed afterwards - do not
3212   - /// destroy the set)
3213   - Option *add_mutable_set_ignore_case_underscore(std::string option_name,
3214   - std::string &member, ///< The selected member of the set
3215   - const std::set<std::string> &options, ///< The set of possibilities
3216   - std::string description,
3217   - bool defaulted) {
3218   -
3219   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
3220   - CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
3221   - member = detail::to_lower(detail::remove_underscore(res[0]));
3222   - auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
3223   - return detail::to_lower(detail::remove_underscore(val)) == member;
3224   - });
3225   - if(iter == std::end(options))
3226   - throw ConversionError(member, simple_name);
3227   - else {
3228   - member = *iter;
3229   - return true;
3230   - }
3231   - };
3232   -
3233   - Option *opt = add_option(option_name, fun, description, defaulted);
3234   - opt->type_name_fn([&options]() {
3235   - return std::string(detail::type_name<std::string>()) + " in {" + detail::join(options) + "}";
3236   - });
3237   - if(defaulted) {
3238   - opt->default_str(member);
3239   - }
3240   - return opt;
3241   - }
3242   -
3243   - /// Add a complex number
3244   - template <typename T>
3245   - Option *add_complex(std::string option_name,
3246   - T &variable,
3247   - std::string description = "",
3248   - bool defaulted = false,
3249   - std::string label = "COMPLEX") {
3250   -
3251   - std::string simple_name = CLI::detail::split(option_name, ',').at(0);
3252   - CLI::callback_t fun = [&variable, simple_name, label](results_t res) {
3253   - if(res[1].back() == 'i')
3254   - res[1].pop_back();
3255   - double x, y;
3256   - bool worked = detail::lexical_cast(res[0], x) && detail::lexical_cast(res[1], y);
3257   - if(worked)
3258   - variable = T(x, y);
3259   - return worked;
3260   - };
3261   -
3262   - CLI::Option *opt = add_option(option_name, fun, description, defaulted);
3263   - opt->type_name(label)->type_size(2);
3264   - if(defaulted) {
3265   - std::stringstream out;
3266   - out << variable;
3267   - opt->default_str(out.str());
3268   - }
3269   - return opt;
3270   - }
3271   -
3272   - /// Set a configuration ini file option, or clear it if no name passed
3273   - Option *set_config(std::string option_name = "",
3274   - std::string default_filename = "",
3275   - std::string help_message = "Read an ini file",
3276   - bool required = false) {
3277   -
3278   - // Remove existing config if present
3279   - if(config_ptr_ != nullptr)
3280   - remove_option(config_ptr_);
3281   -
3282   - // Only add config if option passed
3283   - if(!option_name.empty()) {
3284   - config_name_ = default_filename;
3285   - config_required_ = required;
3286   - config_ptr_ = add_option(option_name, config_name_, help_message, !default_filename.empty());
3287   - config_ptr_->configurable(false);
3288   - }
3289   -
3290   - return config_ptr_;
3291   - }
3292   -
3293   - /// Removes an option from the App. Takes an option pointer. Returns true if found and removed.
3294   - bool remove_option(Option *opt) {
3295   - // Make sure no links exist
3296   - for(Option_p &op : options_) {
3297   - op->remove_needs(opt);
3298   - op->remove_excludes(opt);
3299   - }
3300   -
3301   - if(help_ptr_ == opt)
3302   - help_ptr_ = nullptr;
3303   - if(help_all_ptr_ == opt)
3304   - help_all_ptr_ = nullptr;
3305   -
3306   - auto iterator =
3307   - std::find_if(std::begin(options_), std::end(options_), [opt](const Option_p &v) { return v.get() == opt; });
3308   - if(iterator != std::end(options_)) {
3309   - options_.erase(iterator);
3310   - return true;
3311   - }
3312   - return false;
3313   - }
3314   -
3315   - ///@}
3316   - /// @name Subcommmands
3317   - ///@{
3318   -
3319   - /// Add a subcommand. Inherits INHERITABLE and OptionDefaults, and help flag
3320   - App *add_subcommand(std::string subcommand_name, std::string description = "") {
3321   - CLI::App_p subcom(new App(description, subcommand_name, this));
3322   - for(const auto &subc : subcommands_)
3323   - if(subc->check_name(subcommand_name) || subcom->check_name(subc->name_))
3324   - throw OptionAlreadyAdded(subc->name_);
3325   - subcommands_.push_back(std::move(subcom));
3326   - return subcommands_.back().get();
3327   - }
3328   -
3329   - /// Check to see if a subcommand is part of this command (doesn't have to be in command line)
3330   - App *get_subcommand(App *subcom) const {
3331   - for(const App_p &subcomptr : subcommands_)
3332   - if(subcomptr.get() == subcom)
3333   - return subcom;
3334   - throw OptionNotFound(subcom->get_name());
3335   - }
3336   -
3337   - /// Check to see if a subcommand is part of this command (text version)
3338   - App *get_subcommand(std::string subcom) const {
3339   - for(const App_p &subcomptr : subcommands_)
3340   - if(subcomptr->check_name(subcom))
3341   - return subcomptr.get();
3342   - throw OptionNotFound(subcom);
3343   - }
3344   -
3345   - /// No argument version of count counts the number of times this subcommand was
3346   - /// passed in. The main app will return 1.
3347   - size_t count() const { return parsed_; }
3348   -
3349   - /// Changes the group membership
3350   - App *group(std::string group_name) {
3351   - group_ = group_name;
3352   - return this;
3353   - }
3354   -
3355   - /// The argumentless form of require subcommand requires 1 or more subcommands
3356   - App *require_subcommand() {
3357   - require_subcommand_min_ = 1;
3358   - require_subcommand_max_ = 0;
3359   - return this;
3360   - }
3361   -
3362   - /// Require a subcommand to be given (does not affect help call)
3363   - /// The number required can be given. Negative values indicate maximum
3364   - /// number allowed (0 for any number). Max number inheritable.
3365   - App *require_subcommand(int value) {
3366   - if(value < 0) {
3367   - require_subcommand_min_ = 0;
3368   - require_subcommand_max_ = static_cast<size_t>(-value);
3369   - } else {
3370   - require_subcommand_min_ = static_cast<size_t>(value);
3371   - require_subcommand_max_ = static_cast<size_t>(value);
3372   - }
3373   - return this;
3374   - }
3375   -
3376   - /// Explicitly control the number of subcommands required. Setting 0
3377   - /// for the max means unlimited number allowed. Max number inheritable.
3378   - App *require_subcommand(size_t min, size_t max) {
3379   - require_subcommand_min_ = min;
3380   - require_subcommand_max_ = max;
3381   - return this;
3382   - }
3383   -
3384   - /// Stop subcommand fallthrough, so that parent commands cannot collect commands after subcommand.
3385   - /// Default from parent, usually set on parent.
3386   - App *fallthrough(bool value = true) {
3387   - fallthrough_ = value;
3388   - return this;
3389   - }
3390   -
3391   - /// Check to see if this subcommand was parsed, true only if received on command line.
3392   - /// This allows the subcommand to be directly checked.
3393   - operator bool() const { return parsed_ > 0; }
3394   -
3395   - ///@}
3396   - /// @name Extras for subclassing
3397   - ///@{
3398   -
3399   - /// This allows subclasses to inject code before callbacks but after parse.
3400   - ///
3401   - /// This does not run if any errors or help is thrown.
3402   - virtual void pre_callback() {}
3403   -
3404   - ///@}
3405   - /// @name Parsing
3406   - ///@{
3407   - //
3408   - /// Reset the parsed data
3409   - void clear() {
3410   -
3411   - parsed_ = false;
3412   - missing_.clear();
3413   - parsed_subcommands_.clear();
3414   -
3415   - for(const Option_p &opt : options_) {
3416   - opt->clear();
3417   - }
3418   - for(const App_p &app : subcommands_) {
3419   - app->clear();
3420   - }
3421   - }
3422   -
3423   - /// Parses the command line - throws errors.
3424   - /// This must be called after the options are in but before the rest of the program.
3425   - void parse(int argc, const char *const *argv) {
3426   - // If the name is not set, read from command line
3427   - if(name_.empty())
3428   - name_ = argv[0];
3429   -
3430   - std::vector<std::string> args;
3431   - for(int i = argc - 1; i > 0; i--)
3432   - args.emplace_back(argv[i]);
3433   - parse(args);
3434   - }
3435   -
3436   - /// Parse a single string as if it contained command line arguments.
3437   - /// This function splits the string into arguments then calls parse(std::vector<std::string> &)
3438   - /// the function takes an optional boolean argument specifying if the programName is included in the string to
3439   - /// process
3440   - void parse(std::string commandline, bool program_name_included = false) {
3441   -
3442   - if(program_name_included) {
3443   - auto nstr = detail::split_program_name(commandline);
3444   - if(name_.empty()) {
3445   - name_ = nstr.first;
3446   - }
3447   - commandline = std::move(nstr.second);
3448   - } else
3449   - detail::trim(commandline);
3450   - // the next section of code is to deal with quoted arguments after an '=' or ':' for windows like operations
3451   - if(!commandline.empty()) {
3452   - commandline = detail::find_and_modify(commandline, "=", detail::escape_detect);
3453   - if(allow_windows_style_options_)
3454   - commandline = detail::find_and_modify(commandline, ":", detail::escape_detect);
3455   - }
3456   -
3457   - auto args = detail::split_up(std::move(commandline));
3458   - // remove all empty strings
3459   - args.erase(std::remove(args.begin(), args.end(), std::string()), args.end());
3460   - std::reverse(args.begin(), args.end());
3461   -
3462   - parse(args);
3463   - }
3464   -
3465   - /// The real work is done here. Expects a reversed vector.
3466   - /// Changes the vector to the remaining options.
3467   - void parse(std::vector<std::string> &args) {
3468   - // Clear if parsed
3469   - if(parsed_ > 0)
3470   - clear();
3471   -
3472   - // _parse is incremented in commands/subcommands,
3473   - // but placed here to make sure this is cleared when
3474   - // running parse after an error is thrown, even by _validate.
3475   - parsed_ = 1;
3476   - _validate();
3477   - parsed_ = 0;
3478   -
3479   - _parse(args);
3480   - run_callback();
3481   - }
3482   -
3483   - /// Provide a function to print a help message. The function gets access to the App pointer and error.
3484   - void failure_message(std::function<std::string(const App *, const Error &e)> function) {
3485   - failure_message_ = function;
3486   - }
3487   -
3488   - /// Print a nice error message and return the exit code
3489   - int exit(const Error &e, std::ostream &out = std::cout, std::ostream &err = std::cerr) const {
3490   -
3491   - /// Avoid printing anything if this is a CLI::RuntimeError
3492   - if(dynamic_cast<const CLI::RuntimeError *>(&e) != nullptr)
3493   - return e.get_exit_code();
3494   -
3495   - if(dynamic_cast<const CLI::CallForHelp *>(&e) != nullptr) {
3496   - out << help();
3497   - return e.get_exit_code();
3498   - }
3499   -
3500   - if(dynamic_cast<const CLI::CallForAllHelp *>(&e) != nullptr) {
3501   - out << help("", AppFormatMode::All);
3502   - return e.get_exit_code();
3503   - }
3504   -
3505   - if(e.get_exit_code() != static_cast<int>(ExitCodes::Success)) {
3506   - if(failure_message_)
3507   - err << failure_message_(this, e) << std::flush;
3508   - }
3509   -
3510   - return e.get_exit_code();
3511   - }
3512   -
3513   - ///@}
3514   - /// @name Post parsing
3515   - ///@{
3516   -
3517   - /// Counts the number of times the given option was passed.
3518   - size_t count(std::string option_name) const {
3519   - for(const Option_p &opt : options_) {
3520   - if(opt->check_name(option_name)) {
3521   - return opt->count();
3522   - }
3523   - }
3524   - throw OptionNotFound(option_name);
3525   - }
3526   -
3527   - /// Get a subcommand pointer list to the currently selected subcommands (after parsing by by default, in command
3528   - /// line order; use parsed = false to get the original definition list.)
3529   - std::vector<App *> get_subcommands() const { return parsed_subcommands_; }
3530   -
3531   - /// Get a filtered subcommand pointer list from the original definition list. An empty function will provide all
3532   - /// subcommands (const)
3533   - std::vector<const App *> get_subcommands(const std::function<bool(const App *)> &filter) const {
3534   - std::vector<const App *> subcomms(subcommands_.size());
3535   - std::transform(std::begin(subcommands_), std::end(subcommands_), std::begin(subcomms), [](const App_p &v) {
3536   - return v.get();
3537   - });
3538   -
3539   - if(filter) {
3540   - subcomms.erase(std::remove_if(std::begin(subcomms),
3541   - std::end(subcomms),
3542   - [&filter](const App *app) { return !filter(app); }),
3543   - std::end(subcomms));
3544   - }
3545   -
3546   - return subcomms;
3547   - }
3548   -
3549   - /// Get a filtered subcommand pointer list from the original definition list. An empty function will provide all
3550   - /// subcommands
3551   - std::vector<App *> get_subcommands(const std::function<bool(App *)> &filter) {
3552   - std::vector<App *> subcomms(subcommands_.size());
3553   - std::transform(std::begin(subcommands_), std::end(subcommands_), std::begin(subcomms), [](const App_p &v) {
3554   - return v.get();
3555   - });
3556   -
3557   - if(filter) {
3558   - subcomms.erase(
3559   - std::remove_if(std::begin(subcomms), std::end(subcomms), [&filter](App *app) { return !filter(app); }),
3560   - std::end(subcomms));
3561   - }
3562   -
3563   - return subcomms;
3564   - }
3565   -
3566   - /// Check to see if given subcommand was selected
3567   - bool got_subcommand(App *subcom) const {
3568   - // get subcom needed to verify that this was a real subcommand
3569   - return get_subcommand(subcom)->parsed_ > 0;
3570   - }
3571   -
3572   - /// Check with name instead of pointer to see if subcommand was selected
3573   - bool got_subcommand(std::string subcommand_name) const { return get_subcommand(subcommand_name)->parsed_ > 0; }
3574   -
3575   - ///@}
3576   - /// @name Help
3577   - ///@{
3578   -
3579   - /// Set footer.
3580   - App *footer(std::string footer_string) {
3581   - footer_ = std::move(footer_string);
3582   - return this;
3583   - }
3584   -
3585   - /// Produce a string that could be read in as a config of the current values of the App. Set default_also to
3586   - /// include default arguments. Prefix will add a string to the beginning of each option.
3587   - std::string config_to_str(bool default_also = false, bool write_description = false) const {
3588   - return config_formatter_->to_config(this, default_also, write_description, "");
3589   - }
3590   -
3591   - /// Makes a help message, using the currently configured formatter
3592   - /// Will only do one subcommand at a time
3593   - std::string help(std::string prev = "", AppFormatMode mode = AppFormatMode::Normal) const {
3594   - if(prev.empty())
3595   - prev = get_name();
3596   - else
3597   - prev += " " + get_name();
3598   -
3599   - // Delegate to subcommand if needed
3600   - auto selected_subcommands = get_subcommands();
3601   - if(!selected_subcommands.empty())
3602   - return selected_subcommands.at(0)->help(prev, mode);
3603   - else
3604   - return formatter_->make_help(this, prev, mode);
3605   - }
3606   -
3607   - ///@}
3608   - /// @name Getters
3609   - ///@{
3610   -
3611   - /// Access the formatter
3612   - std::shared_ptr<FormatterBase> get_formatter() const { return formatter_; }
3613   -
3614   - /// Access the config formatter
3615   - std::shared_ptr<Config> get_config_formatter() const { return config_formatter_; }
3616   -
3617   - /// Get the app or subcommand description
3618   - std::string get_description() const { return description_; }
3619   -
3620   - /// Set the description
3621   - App *description(const std::string &description) {
3622   - description_ = description;
3623   - return this;
3624   - }
3625   -
3626   - /// Get the list of options (user facing function, so returns raw pointers), has optional filter function
3627   - std::vector<const Option *> get_options(const std::function<bool(const Option *)> filter = {}) const {
3628   - std::vector<const Option *> options(options_.size());
3629   - std::transform(std::begin(options_), std::end(options_), std::begin(options), [](const Option_p &val) {
3630   - return val.get();
3631   - });
3632   -
3633   - if(filter) {
3634   - options.erase(std::remove_if(std::begin(options),
3635   - std::end(options),
3636   - [&filter](const Option *opt) { return !filter(opt); }),
3637   - std::end(options));
3638   - }
3639   -
3640   - return options;
3641   - }
3642   -
3643   - /// Get an option by name
3644   - const Option *get_option(std::string option_name) const {
3645   - for(const Option_p &opt : options_) {
3646   - if(opt->check_name(option_name)) {
3647   - return opt.get();
3648   - }
3649   - }
3650   - throw OptionNotFound(option_name);
3651   - }
3652   -
3653   - /// Get an option by name (non-const version)
3654   - Option *get_option(std::string option_name) {
3655   - for(Option_p &opt : options_) {
3656   - if(opt->check_name(option_name)) {
3657   - return opt.get();
3658   - }
3659   - }
3660   - throw OptionNotFound(option_name);
3661   - }
3662   -
3663   - /// Check the status of ignore_case
3664   - bool get_ignore_case() const { return ignore_case_; }
3665   -
3666   - /// Check the status of ignore_underscore
3667   - bool get_ignore_underscore() const { return ignore_underscore_; }
3668   -
3669   - /// Check the status of fallthrough
3670   - bool get_fallthrough() const { return fallthrough_; }
3671   -
3672   - /// Check the status of the allow windows style options
3673   - bool get_allow_windows_style_options() const { return allow_windows_style_options_; }
3674   -
3675   - /// Get the group of this subcommand
3676   - const std::string &get_group() const { return group_; }
3677   -
3678   - /// Get footer.
3679   - std::string get_footer() const { return footer_; }
3680   -
3681   - /// Get the required min subcommand value
3682   - size_t get_require_subcommand_min() const { return require_subcommand_min_; }
3683   -
3684   - /// Get the required max subcommand value
3685   - size_t get_require_subcommand_max() const { return require_subcommand_max_; }
3686   -
3687   - /// Get the prefix command status
3688   - bool get_prefix_command() const { return prefix_command_; }
3689   -
3690   - /// Get the status of allow extras
3691   - bool get_allow_extras() const { return allow_extras_; }
3692   -
3693   - /// Get the status of allow extras
3694   - bool get_allow_config_extras() const { return allow_config_extras_; }
3695   -
3696   - /// Get a pointer to the help flag.
3697   - Option *get_help_ptr() { return help_ptr_; }
3698   -
3699   - /// Get a pointer to the help flag. (const)
3700   - const Option *get_help_ptr() const { return help_ptr_; }
3701   -
3702   - /// Get a pointer to the help all flag. (const)
3703   - const Option *get_help_all_ptr() const { return help_all_ptr_; }
3704   -
3705   - /// Get a pointer to the config option.
3706   - Option *get_config_ptr() { return config_ptr_; }
3707   -
3708   - /// Get a pointer to the config option. (const)
3709   - const Option *get_config_ptr() const { return config_ptr_; }
3710   -
3711   - /// Get the parent of this subcommand (or nullptr if master app)
3712   - App *get_parent() { return parent_; }
3713   -
3714   - /// Get the parent of this subcommand (or nullptr if master app) (const version)
3715   - const App *get_parent() const { return parent_; }
3716   -
3717   - /// Get the name of the current app
3718   - std::string get_name() const { return name_; }
3719   -
3720   - /// Check the name, case insensitive and underscore insensitive if set
3721   - bool check_name(std::string name_to_check) const {
3722   - std::string local_name = name_;
3723   - if(ignore_underscore_) {
3724   - local_name = detail::remove_underscore(name_);
3725   - name_to_check = detail::remove_underscore(name_to_check);
3726   - }
3727   - if(ignore_case_) {
3728   - local_name = detail::to_lower(name_);
3729   - name_to_check = detail::to_lower(name_to_check);
3730   - }
3731   -
3732   - return local_name == name_to_check;
3733   - }
3734   -
3735   - /// Get the groups available directly from this option (in order)
3736   - std::vector<std::string> get_groups() const {
3737   - std::vector<std::string> groups;
3738   -
3739   - for(const Option_p &opt : options_) {
3740   - // Add group if it is not already in there
3741   - if(std::find(groups.begin(), groups.end(), opt->get_group()) == groups.end()) {
3742   - groups.push_back(opt->get_group());
3743   - }
3744   - }
3745   -
3746   - return groups;
3747   - }
3748   -
3749   - /// This gets a vector of pointers with the original parse order
3750   - const std::vector<Option *> &parse_order() const { return parse_order_; }
3751   -
3752   - /// This returns the missing options from the current subcommand
3753   - std::vector<std::string> remaining(bool recurse = false) const {
3754   - std::vector<std::string> miss_list;
3755   - for(const std::pair<detail::Classifier, std::string> &miss : missing_) {
3756   - miss_list.push_back(std::get<1>(miss));
3757   - }
3758   -
3759   - // Recurse into subcommands
3760   - if(recurse) {
3761   - for(const App *sub : parsed_subcommands_) {
3762   - std::vector<std::string> output = sub->remaining(recurse);
3763   - std::copy(std::begin(output), std::end(output), std::back_inserter(miss_list));
3764   - }
3765   - }
3766   - return miss_list;
3767   - }
3768   -
3769   - /// This returns the number of remaining options, minus the -- separator
3770   - size_t remaining_size(bool recurse = false) const {
3771   - auto remaining_options = static_cast<size_t>(std::count_if(
3772   - std::begin(missing_), std::end(missing_), [](const std::pair<detail::Classifier, std::string> &val) {
3773   - return val.first != detail::Classifier::POSITIONAL_MARK;
3774   - }));
3775   - if(recurse) {
3776   - for(const App_p &sub : subcommands_) {
3777   - remaining_options += sub->remaining_size(recurse);
3778   - }
3779   - }
3780   - return remaining_options;
3781   - }
3782   -
3783   - ///@}
3784   -
3785   - protected:
3786   - /// Check the options to make sure there are no conflicts.
3787   - ///
3788   - /// Currently checks to see if multiple positionals exist with -1 args
3789   - void _validate() const {
3790   - auto pcount = std::count_if(std::begin(options_), std::end(options_), [](const Option_p &opt) {
3791   - return opt->get_items_expected() < 0 && opt->get_positional();
3792   - });
3793   - if(pcount > 1)
3794   - throw InvalidError(name_);
3795   - for(const App_p &app : subcommands_)
3796   - app->_validate();
3797   - }
3798   -
3799   - /// Internal function to run (App) callback, top down
3800   - void run_callback() {
3801   - pre_callback();
3802   - if(callback_)
3803   - callback_();
3804   - for(App *subc : get_subcommands()) {
3805   - subc->run_callback();
3806   - }
3807   - }
3808   -
3809   - /// Check to see if a subcommand is valid. Give up immediately if subcommand max has been reached.
3810   - bool _valid_subcommand(const std::string &current) const {
3811   - // Don't match if max has been reached - but still check parents
3812   - if(require_subcommand_max_ != 0 && parsed_subcommands_.size() >= require_subcommand_max_) {
3813   - return parent_ != nullptr && parent_->_valid_subcommand(current);
3814   - }
3815   -
3816   - for(const App_p &com : subcommands_)
3817   - if(com->check_name(current) && !*com)
3818   - return true;
3819   -
3820   - // Check parent if exists, else return false
3821   - return parent_ != nullptr && parent_->_valid_subcommand(current);
3822   - }
3823   -
3824   - /// Selects a Classifier enum based on the type of the current argument
3825   - detail::Classifier _recognize(const std::string &current) const {
3826   - std::string dummy1, dummy2;
3827   -
3828   - if(current == "--")
3829   - return detail::Classifier::POSITIONAL_MARK;
3830   - if(_valid_subcommand(current))
3831   - return detail::Classifier::SUBCOMMAND;
3832   - if(detail::split_long(current, dummy1, dummy2))
3833   - return detail::Classifier::LONG;
3834   - if(detail::split_short(current, dummy1, dummy2))
3835   - return detail::Classifier::SHORT;
3836   - if((allow_windows_style_options_) && (detail::split_windows(current, dummy1, dummy2)))
3837   - return detail::Classifier::WINDOWS;
3838   - return detail::Classifier::NONE;
3839   - }
3840   -
3841   - // The parse function is now broken into several parts, and part of process
3842   -
3843   - /// Read and process an ini file (main app only)
3844   - void _process_ini() {
3845   - // Process an INI file
3846   - if(config_ptr_ != nullptr) {
3847   - if(*config_ptr_) {
3848   - config_ptr_->run_callback();
3849   - config_required_ = true;
3850   - }
3851   - if(!config_name_.empty()) {
3852   - try {
3853   - std::vector<ConfigItem> values = config_formatter_->from_file(config_name_);
3854   - _parse_config(values);
3855   - } catch(const FileError &) {
3856   - if(config_required_)
3857   - throw;
3858   - }
3859   - }
3860   - }
3861   - }
3862   -
3863   - /// Get envname options if not yet passed. Runs on *all* subcommands.
3864   - void _process_env() {
3865   - for(const Option_p &opt : options_) {
3866   - if(opt->count() == 0 && !opt->envname_.empty()) {
3867   - char *buffer = nullptr;
3868   - std::string ename_string;
3869   -
3870   -#ifdef _MSC_VER
3871   - // Windows version
3872   - size_t sz = 0;
3873   - if(_dupenv_s(&buffer, &sz, opt->envname_.c_str()) == 0 && buffer != nullptr) {
3874   - ename_string = std::string(buffer);
3875   - free(buffer);
3876   - }
3877   -#else
3878   - // This also works on Windows, but gives a warning
3879   - buffer = std::getenv(opt->envname_.c_str());
3880   - if(buffer != nullptr)
3881   - ename_string = std::string(buffer);
3882   -#endif
3883   -
3884   - if(!ename_string.empty()) {
3885   - opt->add_result(ename_string);
3886   - }
3887   - }
3888   - }
3889   -
3890   - for(App_p &sub : subcommands_) {
3891   - sub->_process_env();
3892   - }
3893   - }
3894   -
3895   - /// Process callbacks. Runs on *all* subcommands.
3896   - void _process_callbacks() {
3897   - for(const Option_p &opt : options_) {
3898   - if(opt->count() > 0 && !opt->get_callback_run()) {
3899   - opt->run_callback();
3900   - }
3901   - }
3902   -
3903   - for(App_p &sub : subcommands_) {
3904   - sub->_process_callbacks();
3905   - }
3906   - }
3907   -
3908   - /// Run help flag processing if any are found.
3909   - ///
3910   - /// The flags allow recursive calls to remember if there was a help flag on a parent.
3911   - void _process_help_flags(bool trigger_help = false, bool trigger_all_help = false) const {
3912   - const Option *help_ptr = get_help_ptr();
3913   - const Option *help_all_ptr = get_help_all_ptr();
3914   -
3915   - if(help_ptr != nullptr && help_ptr->count() > 0)
3916   - trigger_help = true;
3917   - if(help_all_ptr != nullptr && help_all_ptr->count() > 0)
3918   - trigger_all_help = true;
3919   -
3920   - // If there were parsed subcommands, call those. First subcommand wins if there are multiple ones.
3921   - if(!parsed_subcommands_.empty()) {
3922   - for(const App *sub : parsed_subcommands_)
3923   - sub->_process_help_flags(trigger_help, trigger_all_help);
3924   -
3925   - // Only the final subcommand should call for help. All help wins over help.
3926   - } else if(trigger_all_help) {
3927   - throw CallForAllHelp();
3928   - } else if(trigger_help) {
3929   - throw CallForHelp();
3930   - }
3931   - }
3932   -
3933   - /// Verify required options and cross requirements. Subcommands too (only if selected).
3934   - void _process_requirements() {
3935   - for(const Option_p &opt : options_) {
3936   -
3937   - // Required or partially filled
3938   - if(opt->get_required() || opt->count() != 0) {
3939   - // Make sure enough -N arguments parsed (+N is already handled in parsing function)
3940   - if(opt->get_items_expected() < 0 && opt->count() < static_cast<size_t>(-opt->get_items_expected()))
3941   - throw ArgumentMismatch::AtLeast(opt->get_name(), -opt->get_items_expected());
3942   -
3943   - // Required but empty
3944   - if(opt->get_required() && opt->count() == 0)
3945   - throw RequiredError(opt->get_name());
3946   - }
3947   - // Requires
3948   - for(const Option *opt_req : opt->needs_)
3949   - if(opt->count() > 0 && opt_req->count() == 0)
3950   - throw RequiresError(opt->get_name(), opt_req->get_name());
3951   - // Excludes
3952   - for(const Option *opt_ex : opt->excludes_)
3953   - if(opt->count() > 0 && opt_ex->count() != 0)
3954   - throw ExcludesError(opt->get_name(), opt_ex->get_name());
3955   - }
3956   -
3957   - auto selected_subcommands = get_subcommands();
3958   - if(require_subcommand_min_ > selected_subcommands.size())
3959   - throw RequiredError::Subcommand(require_subcommand_min_);
3960   -
3961   - // Max error cannot occur, the extra subcommand will parse as an ExtrasError or a remaining item.
3962   -
3963   - for(App_p &sub : subcommands_) {
3964   - if(sub->count() > 0)
3965   - sub->_process_requirements();
3966   - }
3967   - }
3968   -
3969   - /// Process callbacks and such.
3970   - void _process() {
3971   - _process_ini();
3972   - _process_env();
3973   - _process_callbacks();
3974   - _process_help_flags();
3975   - _process_requirements();
3976   - }
3977   -
3978   - /// Throw an error if anything is left over and should not be.
3979   - /// Modifies the args to fill in the missing items before throwing.
3980   - void _process_extras(std::vector<std::string> &args) {
3981   - if(!(allow_extras_ || prefix_command_)) {
3982   - size_t num_left_over = remaining_size();
3983   - if(num_left_over > 0) {
3984   - args = remaining(false);
3985   - throw ExtrasError(args);
3986   - }
3987   - }
3988   -
3989   - for(App_p &sub : subcommands_) {
3990   - if(sub->count() > 0)
3991   - sub->_process_extras(args);
3992   - }
3993   - }
3994   -
3995   - /// Internal parse function
3996   - void _parse(std::vector<std::string> &args) {
3997   - parsed_++;
3998   - bool positional_only = false;
3999   -
4000   - while(!args.empty()) {
4001   - _parse_single(args, positional_only);
4002   - }
4003   -
4004   - if(parent_ == nullptr) {
4005   - _process();
4006   -
4007   - // Throw error if any items are left over (depending on settings)
4008   - _process_extras(args);
4009   -
4010   - // Convert missing (pairs) to extras (string only)
4011   - args = remaining(false);
4012   - }
4013   - }
4014   -
4015   - /// Parse one config param, return false if not found in any subcommand, remove if it is
4016   - ///
4017   - /// If this has more than one dot.separated.name, go into the subcommand matching it
4018   - /// Returns true if it managed to find the option, if false you'll need to remove the arg manually.
4019   - void _parse_config(std::vector<ConfigItem> &args) {
4020   - for(ConfigItem item : args) {
4021   - if(!_parse_single_config(item) && !allow_config_extras_)
4022   - throw ConfigError::Extras(item.fullname());
4023   - }
4024   - }
4025   -
4026   - /// Fill in a single config option
4027   - bool _parse_single_config(const ConfigItem &item, size_t level = 0) {
4028   - if(level < item.parents.size()) {
4029   - App *subcom;
4030   - try {
4031   - subcom = get_subcommand(item.parents.at(level));
4032   - } catch(const OptionNotFound &) {
4033   - return false;
4034   - }
4035   - return subcom->_parse_single_config(item, level + 1);
4036   - }
4037   -
4038   - Option *op;
4039   - try {
4040   - op = get_option("--" + item.name);
4041   - } catch(const OptionNotFound &) {
4042   - // If the option was not present
4043   - if(get_allow_config_extras())
4044   - // Should we worry about classifying the extras properly?
4045   - missing_.emplace_back(detail::Classifier::NONE, item.fullname());
4046   - return false;
4047   - }
4048   -
4049   - if(!op->get_configurable())
4050   - throw ConfigError::NotConfigurable(item.fullname());
4051   -
4052   - if(op->empty()) {
4053   - // Flag parsing
4054   - if(op->get_type_size() == 0) {
4055   - op->set_results(config_formatter_->to_flag(item));
4056   - } else {
4057   - op->set_results(item.inputs);
4058   - op->run_callback();
4059   - }
4060   - }
4061   -
4062   - return true;
4063   - }
4064   -
4065   - /// Parse "one" argument (some may eat more than one), delegate to parent if fails, add to missing if missing
4066   - /// from master
4067   - void _parse_single(std::vector<std::string> &args, bool &positional_only) {
4068   -
4069   - detail::Classifier classifier = positional_only ? detail::Classifier::NONE : _recognize(args.back());
4070   - switch(classifier) {
4071   - case detail::Classifier::POSITIONAL_MARK:
4072   - missing_.emplace_back(classifier, args.back());
4073   - args.pop_back();
4074   - positional_only = true;
4075   - break;
4076   - case detail::Classifier::SUBCOMMAND:
4077   - _parse_subcommand(args);
4078   - break;
4079   - case detail::Classifier::LONG:
4080   - case detail::Classifier::SHORT:
4081   - case detail::Classifier::WINDOWS:
4082   - // If already parsed a subcommand, don't accept options_
4083   - _parse_arg(args, classifier);
4084   - break;
4085   - case detail::Classifier::NONE:
4086   - // Probably a positional or something for a parent (sub)command
4087   - _parse_positional(args);
4088   - }
4089   - }
4090   -
4091   - /// Count the required remaining positional arguments
4092   - size_t _count_remaining_positionals(bool required = false) const {
4093   - size_t retval = 0;
4094   - for(const Option_p &opt : options_)
4095   - if(opt->get_positional() && (!required || opt->get_required()) && opt->get_items_expected() > 0 &&
4096   - static_cast<int>(opt->count()) < opt->get_items_expected())
4097   - retval = static_cast<size_t>(opt->get_items_expected()) - opt->count();
4098   -
4099   - return retval;
4100   - }
4101   -
4102   - /// Parse a positional, go up the tree to check
4103   - void _parse_positional(std::vector<std::string> &args) {
4104   -
4105   - std::string positional = args.back();
4106   - for(const Option_p &opt : options_) {
4107   - // Eat options, one by one, until done
4108   - if(opt->get_positional() &&
4109   - (static_cast<int>(opt->count()) < opt->get_items_expected() || opt->get_items_expected() < 0)) {
4110   -
4111   - opt->add_result(positional);
4112   - parse_order_.push_back(opt.get());
4113   - args.pop_back();
4114   - return;
4115   - }
4116   - }
4117   -
4118   - if(parent_ != nullptr && fallthrough_)
4119   - return parent_->_parse_positional(args);
4120   - else {
4121   - args.pop_back();
4122   - missing_.emplace_back(detail::Classifier::NONE, positional);
4123   -
4124   - if(prefix_command_) {
4125   - while(!args.empty()) {
4126   - missing_.emplace_back(detail::Classifier::NONE, args.back());
4127   - args.pop_back();
4128   - }
4129   - }
4130   - }
4131   - }
4132   -
4133   - /// Parse a subcommand, modify args and continue
4134   - ///
4135   - /// Unlike the others, this one will always allow fallthrough
4136   - void _parse_subcommand(std::vector<std::string> &args) {
4137   - if(_count_remaining_positionals(/* required */ true) > 0)
4138   - return _parse_positional(args);
4139   - for(const App_p &com : subcommands_) {
4140   - if(com->check_name(args.back())) {
4141   - args.pop_back();
4142   - if(std::find(std::begin(parsed_subcommands_), std::end(parsed_subcommands_), com.get()) ==
4143   - std::end(parsed_subcommands_))
4144   - parsed_subcommands_.push_back(com.get());
4145   - com->_parse(args);
4146   - return;
4147   - }
4148   - }
4149   - if(parent_ != nullptr)
4150   - return parent_->_parse_subcommand(args);
4151   - else
4152   - throw HorribleError("Subcommand " + args.back() + " missing");
4153   - }
4154   -
4155   - /// Parse a short (false) or long (true) argument, must be at the top of the list
4156   - void _parse_arg(std::vector<std::string> &args, detail::Classifier current_type) {
4157   -
4158   - std::string current = args.back();
4159   -
4160   - std::string arg_name;
4161   - std::string value;
4162   - std::string rest;
4163   -
4164   - switch(current_type) {
4165   - case detail::Classifier::LONG:
4166   - if(!detail::split_long(current, arg_name, value))
4167   - throw HorribleError("Long parsed but missing (you should not see this):" + args.back());
4168   - break;
4169   - case detail::Classifier::SHORT:
4170   - if(!detail::split_short(current, arg_name, rest))
4171   - throw HorribleError("Short parsed but missing! You should not see this");
4172   - break;
4173   - case detail::Classifier::WINDOWS:
4174   - if(!detail::split_windows(current, arg_name, value))
4175   - throw HorribleError("windows option parsed but missing! You should not see this");
4176   - break;
4177   - default:
4178   - throw HorribleError("parsing got called with invalid option! You should not see this");
4179   - }
4180   -
4181   - auto op_ptr =
4182   - std::find_if(std::begin(options_), std::end(options_), [arg_name, current_type](const Option_p &opt) {
4183   - if(current_type == detail::Classifier::LONG)
4184   - return opt->check_lname(arg_name);
4185   - if(current_type == detail::Classifier::SHORT)
4186   - return opt->check_sname(arg_name);
4187   - // this will only get called for detail::Classifier::WINDOWS
4188   - return opt->check_lname(arg_name) || opt->check_sname(arg_name);
4189   - });
4190   -
4191   - // Option not found
4192   - if(op_ptr == std::end(options_)) {
4193   - // If a subcommand, try the master command
4194   - if(parent_ != nullptr && fallthrough_)
4195   - return parent_->_parse_arg(args, current_type);
4196   - // Otherwise, add to missing
4197   - else {
4198   - args.pop_back();
4199   - missing_.emplace_back(current_type, current);
4200   - return;
4201   - }
4202   - }
4203   -
4204   - args.pop_back();
4205   -
4206   - // Get a reference to the pointer to make syntax bearable
4207   - Option_p &op = *op_ptr;
4208   -
4209   - int num = op->get_items_expected();
4210   -
4211   - // Make sure we always eat the minimum for unlimited vectors
4212   - int collected = 0;
4213   -
4214   - // --this=value
4215   - if(!value.empty()) {
4216   - // If exact number expected
4217   - if(num > 0)
4218   - num--;
4219   - op->add_result(value);
4220   - parse_order_.push_back(op.get());
4221   - collected += 1;
4222   - } else if(num == 0) {
4223   - op->add_result("");
4224   - parse_order_.push_back(op.get());
4225   - // -Trest
4226   - } else if(!rest.empty()) {
4227   - if(num > 0)
4228   - num--;
4229   - op->add_result(rest);
4230   - parse_order_.push_back(op.get());
4231   - rest = "";
4232   - collected += 1;
4233   - }
4234   -
4235   - // Unlimited vector parser
4236   - if(num < 0) {
4237   - while(!args.empty() && _recognize(args.back()) == detail::Classifier::NONE) {
4238   - if(collected >= -num) {
4239   - // We could break here for allow extras, but we don't
4240   -
4241   - // If any positionals remain, don't keep eating
4242   - if(_count_remaining_positionals() > 0)
4243   - break;
4244   - }
4245   - op->add_result(args.back());
4246   - parse_order_.push_back(op.get());
4247   - args.pop_back();
4248   - collected++;
4249   - }
4250   -
4251   - // Allow -- to end an unlimited list and "eat" it
4252   - if(!args.empty() && _recognize(args.back()) == detail::Classifier::POSITIONAL_MARK)
4253   - args.pop_back();
4254   -
4255   - } else {
4256   - while(num > 0 && !args.empty()) {
4257   - num--;
4258   - std::string current_ = args.back();
4259   - args.pop_back();
4260   - op->add_result(current_);
4261   - parse_order_.push_back(op.get());
4262   - }
4263   -
4264   - if(num > 0) {
4265   - throw ArgumentMismatch::TypedAtLeast(op->get_name(), num, op->get_type_name());
4266   - }
4267   - }
4268   -
4269   - if(!rest.empty()) {
4270   - rest = "-" + rest;
4271   - args.push_back(rest);
4272   - }
4273   - }
4274   -};
4275   -
4276   -namespace FailureMessage {
4277   -
4278   -/// Printout a clean, simple message on error (the default in CLI11 1.5+)
4279   -inline std::string simple(const App *app, const Error &e) {
4280   - std::string header = std::string(e.what()) + "\n";
4281   - std::vector<std::string> names;
4282   -
4283   - // Collect names
4284   - if(app->get_help_ptr() != nullptr)
4285   - names.push_back(app->get_help_ptr()->get_name());
4286   -
4287   - if(app->get_help_all_ptr() != nullptr)
4288   - names.push_back(app->get_help_all_ptr()->get_name());
4289   -
4290   - // If any names found, suggest those
4291   - if(!names.empty())
4292   - header += "Run with " + detail::join(names, " or ") + " for more information.\n";
4293   -
4294   - return header;
4295   -}
4296   -
4297   -/// Printout the full help string on error (if this fn is set, the old default for CLI11)
4298   -inline std::string help(const App *app, const Error &e) {
4299   - std::string header = std::string("ERROR: ") + e.get_name() + ": " + e.what() + "\n";
4300   - header += app->help();
4301   - return header;
4302   -}
4303   -
4304   -} // namespace FailureMessage
4305   -
4306   -namespace detail {
4307   -/// This class is simply to allow tests access to App's protected functions
4308   -struct AppFriend {
4309   -
4310   - /// Wrap _parse_short, perfectly forward arguments and return
4311   - template <typename... Args>
4312   - static auto parse_arg(App *app, Args &&... args) ->
4313   - typename std::result_of<decltype (&App::_parse_arg)(App, Args...)>::type {
4314   - return app->_parse_arg(std::forward<Args>(args)...);
4315   - }
4316   -
4317   - /// Wrap _parse_subcommand, perfectly forward arguments and return
4318   - template <typename... Args>
4319   - static auto parse_subcommand(App *app, Args &&... args) ->
4320   - typename std::result_of<decltype (&App::_parse_subcommand)(App, Args...)>::type {
4321   - return app->_parse_subcommand(std::forward<Args>(args)...);
4322   - }
4323   -};
4324   -} // namespace detail
4325   -
4326   -} // namespace CLI
4327   -
4328   -// From CLI/Config.hpp:
4329   -
4330   -namespace CLI {
4331   -
4332   -inline std::string
4333   -ConfigINI::to_config(const App *app, bool default_also, bool write_description, std::string prefix) const {
4334   - std::stringstream out;
4335   - for(const Option *opt : app->get_options({})) {
4336   -
4337   - // Only process option with a long-name and configurable
4338   - if(!opt->get_lnames().empty() && opt->get_configurable()) {
4339   - std::string name = prefix + opt->get_lnames()[0];
4340   - std::string value;
4341   -
4342   - // Non-flags
4343   - if(opt->get_type_size() != 0) {
4344   -
4345   - // If the option was found on command line
4346   - if(opt->count() > 0)
4347   - value = detail::ini_join(opt->results());
4348   -
4349   - // If the option has a default and is requested by optional argument
4350   - else if(default_also && !opt->get_defaultval().empty())
4351   - value = opt->get_defaultval();
4352   - // Flag, one passed
4353   - } else if(opt->count() == 1) {
4354   - value = "true";
4355   -
4356   - // Flag, multiple passed
4357   - } else if(opt->count() > 1) {
4358   - value = std::to_string(opt->count());
4359   -
4360   - // Flag, not present
4361   - } else if(opt->count() == 0 && default_also) {
4362   - value = "false";
4363   - }
4364   -
4365   - if(!value.empty()) {
4366   - if(write_description && opt->has_description()) {
4367   - if(static_cast<int>(out.tellp()) != 0) {
4368   - out << std::endl;
4369   - }
4370   - out << "; " << detail::fix_newlines("; ", opt->get_description()) << std::endl;
4371   - }
4372   -
4373   - // Don't try to quote anything that is not size 1
4374   - if(opt->get_items_expected() != 1)
4375   - out << name << "=" << value << std::endl;
4376   - else
4377   - out << name << "=" << detail::add_quotes_if_needed(value) << std::endl;
4378   - }
4379   - }
4380   - }
4381   -
4382   - for(const App *subcom : app->get_subcommands({}))
4383   - out << to_config(subcom, default_also, write_description, prefix + subcom->get_name() + ".");
4384   -
4385   - return out.str();
4386   -}
4387   -
4388   -} // namespace CLI
4389   -
4390   -// From CLI/Formatter.hpp:
4391   -
4392   -namespace CLI {
4393   -
4394   -inline std::string
4395   -Formatter::make_group(std::string group, bool is_positional, std::vector<const Option *> opts) const {
4396   - std::stringstream out;
4397   -
4398   - out << "\n" << group << ":\n";
4399   - for(const Option *opt : opts) {
4400   - out << make_option(opt, is_positional);
4401   - }
4402   -
4403   - return out.str();
4404   -}
4405   -
4406   -inline std::string Formatter::make_positionals(const App *app) const {
4407   - std::vector<const Option *> opts =
4408   - app->get_options([](const Option *opt) { return !opt->get_group().empty() && opt->get_positional(); });
4409   -
4410   - if(opts.empty())
4411   - return std::string();
4412   - else
4413   - return make_group(get_label("Positionals"), true, opts);
4414   -}
4415   -
4416   -inline std::string Formatter::make_groups(const App *app, AppFormatMode mode) const {
4417   - std::stringstream out;
4418   - std::vector<std::string> groups = app->get_groups();
4419   -
4420   - // Options
4421   - for(const std::string &group : groups) {
4422   - std::vector<const Option *> opts = app->get_options([app, mode, &group](const Option *opt) {
4423   - return opt->get_group() == group // Must be in the right group
4424   - && opt->nonpositional() // Must not be a positional
4425   - && (mode != AppFormatMode::Sub // If mode is Sub, then
4426   - || (app->get_help_ptr() != opt // Ignore help pointer
4427   - && app->get_help_all_ptr() != opt)); // Ignore help all pointer
4428   - });
4429   - if(!group.empty() && !opts.empty()) {
4430   - out << make_group(group, false, opts);
4431   -
4432   - if(group != groups.back())
4433   - out << "\n";
4434   - }
4435   - }
4436   -
4437   - return out.str();
4438   -}
4439   -
4440   -inline std::string Formatter::make_description(const App *app) const {
4441   - std::string desc = app->get_description();
4442   -
4443   - if(!desc.empty())
4444   - return desc + "\n";
4445   - else
4446   - return "";
4447   -}
4448   -
4449   -inline std::string Formatter::make_usage(const App *app, std::string name) const {
4450   - std::stringstream out;
4451   -
4452   - out << get_label("Usage") << ":" << (name.empty() ? "" : " ") << name;
4453   -
4454   - std::vector<std::string> groups = app->get_groups();
4455   -
4456   - // Print an Options badge if any options exist
4457   - std::vector<const Option *> non_pos_options =
4458   - app->get_options([](const Option *opt) { return opt->nonpositional(); });
4459   - if(!non_pos_options.empty())
4460   - out << " [" << get_label("OPTIONS") << "]";
4461   -
4462   - // Positionals need to be listed here
4463   - std::vector<const Option *> positionals = app->get_options([](const Option *opt) { return opt->get_positional(); });
4464   -
4465   - // Print out positionals if any are left
4466   - if(!positionals.empty()) {
4467   - // Convert to help names
4468   - std::vector<std::string> positional_names(positionals.size());
4469   - std::transform(positionals.begin(), positionals.end(), positional_names.begin(), [this](const Option *opt) {
4470   - return make_option_usage(opt);
4471   - });
4472   -
4473   - out << " " << detail::join(positional_names, " ");
4474   - }
4475   -
4476   - // Add a marker if subcommands are expected or optional
4477   - if(!app->get_subcommands({}).empty()) {
4478   - out << " " << (app->get_require_subcommand_min() == 0 ? "[" : "")
4479   - << get_label(app->get_require_subcommand_max() < 2 || app->get_require_subcommand_min() > 1 ? "SUBCOMMAND"
4480   - : "SUBCOMMANDS")
4481   - << (app->get_require_subcommand_min() == 0 ? "]" : "");
4482   - }
4483   -
4484   - out << std::endl;
4485   -
4486   - return out.str();
4487   -}
4488   -
4489   -inline std::string Formatter::make_footer(const App *app) const {
4490   - std::string footer = app->get_footer();
4491   - if(!footer.empty())
4492   - return footer + "\n";
4493   - else
4494   - return "";
4495   -}
4496   -
4497   -inline std::string Formatter::make_help(const App *app, std::string name, AppFormatMode mode) const {
4498   -
4499   - // This immediately forwards to the make_expanded method. This is done this way so that subcommands can
4500   - // have overridden formatters
4501   - if(mode == AppFormatMode::Sub)
4502   - return make_expanded(app);
4503   -
4504   - std::stringstream out;
4505   -
4506   - out << make_description(app);
4507   - out << make_usage(app, name);
4508   - out << make_positionals(app);
4509   - out << make_groups(app, mode);
4510   - out << make_subcommands(app, mode);
4511   - out << make_footer(app);
4512   -
4513   - return out.str();
4514   -}
4515   -
4516   -inline std::string Formatter::make_subcommands(const App *app, AppFormatMode mode) const {
4517   - std::stringstream out;
4518   -
4519   - std::vector<const App *> subcommands = app->get_subcommands({});
4520   -
4521   - // Make a list in definition order of the groups seen
4522   - std::vector<std::string> subcmd_groups_seen;
4523   - for(const App *com : subcommands) {
4524   - std::string group_key = com->get_group();
4525   - if(!group_key.empty() &&
4526   - std::find_if(subcmd_groups_seen.begin(), subcmd_groups_seen.end(), [&group_key](std::string a) {
4527   - return detail::to_lower(a) == detail::to_lower(group_key);
4528   - }) == subcmd_groups_seen.end())
4529   - subcmd_groups_seen.push_back(group_key);
4530   - }
4531   -
4532   - // For each group, filter out and print subcommands
4533   - for(const std::string &group : subcmd_groups_seen) {
4534   - out << "\n" << group << ":\n";
4535   - std::vector<const App *> subcommands_group = app->get_subcommands(
4536   - [&group](const App *sub_app) { return detail::to_lower(sub_app->get_group()) == detail::to_lower(group); });
4537   - for(const App *new_com : subcommands_group) {
4538   - if(mode != AppFormatMode::All) {
4539   - out << make_subcommand(new_com);
4540   - } else {
4541   - out << new_com->help(new_com->get_name(), AppFormatMode::Sub);
4542   - out << "\n";
4543   - }
4544   - }
4545   - }
4546   -
4547   - return out.str();
4548   -}
4549   -
4550   -inline std::string Formatter::make_subcommand(const App *sub) const {
4551   - std::stringstream out;
4552   - detail::format_help(out, sub->get_name(), sub->get_description(), column_width_);
4553   - return out.str();
4554   -}
4555   -
4556   -inline std::string Formatter::make_expanded(const App *sub) const {
4557   - std::stringstream out;
4558   - out << sub->get_name() << "\n";
4559   -
4560   - out << make_description(sub);
4561   - out << make_positionals(sub);
4562   - out << make_groups(sub, AppFormatMode::Sub);
4563   - out << make_subcommands(sub, AppFormatMode::Sub);
4564   -
4565   - // Drop blank spaces
4566   - std::string tmp = detail::find_and_replace(out.str(), "\n\n", "\n");
4567   - tmp = tmp.substr(0, tmp.size() - 1); // Remove the final '\n'
4568   -
4569   - // Indent all but the first line (the name)
4570   - return detail::find_and_replace(tmp, "\n", "\n ") + "\n";
4571   -}
4572   -
4573   -inline std::string Formatter::make_option_name(const Option *opt, bool is_positional) const {
4574   - if(is_positional)
4575   - return opt->get_name(true, false);
4576   - else
4577   - return opt->get_name(false, true);
4578   -}
4579   -
4580   -inline std::string Formatter::make_option_opts(const Option *opt) const {
4581   - std::stringstream out;
4582   -
4583   - if(opt->get_type_size() != 0) {
4584   - if(!opt->get_type_name().empty())
4585   - out << " " << get_label(opt->get_type_name());
4586   - if(!opt->get_defaultval().empty())
4587   - out << "=" << opt->get_defaultval();
4588   - if(opt->get_expected() > 1)
4589   - out << " x " << opt->get_expected();
4590   - if(opt->get_expected() == -1)
4591   - out << " ...";
4592   - if(opt->get_required())
4593   - out << " " << get_label("REQUIRED");
4594   - }
4595   - if(!opt->get_envname().empty())
4596   - out << " (" << get_label("Env") << ":" << opt->get_envname() << ")";
4597   - if(!opt->get_needs().empty()) {
4598   - out << " " << get_label("Needs") << ":";
4599   - for(const Option *op : opt->get_needs())
4600   - out << " " << op->get_name();
4601   - }
4602   - if(!opt->get_excludes().empty()) {
4603   - out << " " << get_label("Excludes") << ":";
4604   - for(const Option *op : opt->get_excludes())
4605   - out << " " << op->get_name();
4606   - }
4607   - return out.str();
4608   -}
4609   -
4610   -inline std::string Formatter::make_option_desc(const Option *opt) const { return opt->get_description(); }
4611   -
4612   -inline std::string Formatter::make_option_usage(const Option *opt) const {
4613   - // Note that these are positionals usages
4614   - std::stringstream out;
4615   - out << make_option_name(opt, true);
4616   -
4617   - if(opt->get_expected() > 1)
4618   - out << "(" << std::to_string(opt->get_expected()) << "x)";
4619   - else if(opt->get_expected() < 0)
4620   - out << "...";
4621   -
4622   - return opt->get_required() ? out.str() : "[" + out.str() + "]";
4623   -}
4624   -
4625   -} // namespace CLI
book/code/CMakeLists.txt
... ... @@ -4,7 +4,7 @@ project(CLI11_Examples LANGUAGES CXX)
4 4  
5 5 # Using CMake 3.11's ability to set imported interface targets
6 6 add_library(CLI11::CLI11 IMPORTED INTERFACE)
7   -target_include_directories(CLI11::CLI11 INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
  7 +target_include_directories(CLI11::CLI11 INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/../../include")
8 8 target_compile_features(CLI11::CLI11 INTERFACE cxx_std_11)
9 9  
10 10 # Add CTest
... ...
book/code/flags.cpp
1   -#include "CLI11.hpp"
  1 +#include "CLI/CLI.hpp"
2 2 #include <iostream>
3 3  
4 4 int main(int argc, char **argv) {
... ...
book/code/geet.cpp
1   -#include "CLI11.hpp"
  1 +#include "CLI/CLI.hpp"
2 2  
3 3 #include <iostream>
4 4  
... ...
book/code/intro.cpp
1   -#include "CLI11.hpp"
  1 +#include "CLI/CLI.hpp"
2 2 #include <iostream>
3 3  
4 4 int main(int argc, char **argv) {
... ...
book/code/simplest.cpp
1   -#include "CLI11.hpp"
  1 +#include "CLI/CLI.hpp"
2 2  
3 3 int main(int argc, char **argv) {
4 4 CLI::App app;
... ...