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,4 +6,5 @@ a.out*
6 /CMakeFiles/* 6 /CMakeFiles/*
7 /cmake_install.cmake 7 /cmake_install.cmake
8 /*.kdev4 8 /*.kdev4
  9 +/html/*
9 !/meson.build 10 !/meson.build
.travis.yml
@@ -38,19 +38,14 @@ matrix: @@ -38,19 +38,14 @@ matrix:
38 - export CXX=clang++-3.5 38 - export CXX=clang++-3.5
39 - npm install gitbook-cli -g 39 - npm install gitbook-cli -g
40 - gitbook fetch 3.2.3 40 - gitbook fetch 3.2.3
41 - - (cd book && gitbook install) 41 + - gitbook install book
42 script: 42 script:
43 - .ci/make_and_test.sh 11 43 - .ci/make_and_test.sh 11
44 after_success: 44 after_success:
45 - - export DOXYFILE=$TRAVIS_BUILD_DIR/docs/Doxyfile  
46 - export DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" 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 # GCC 7 and coverage (8 does not support lcov, wait till 9 and new lcov) 50 # GCC 7 and coverage (8 does not support lcov, wait till 9 and new lcov)
56 - compiler: gcc 51 - compiler: gcc
@@ -110,7 +105,15 @@ script: @@ -110,7 +105,15 @@ script:
110 105
111 106
112 deploy: 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 api_key: 117 api_key:
115 secure: L1svZ5J+RiR67dj1fNk/XiZRvYfGJC4c5/dKSvDH+yuKSzZ6ODaTiVmYF8NtMJ7/3AQenEa0OuRBVQ0YpngFz3ugIcRsGCDUHtCMK/Bti0+6ZFdICbqcv6W3BlRIM8s7EOBPhjfbCV+ae7xep9B24HmwBPKukMFjDIj4nwBsmwCHZK9iNFtfaW2J2cr2TJo7QPY01J0W1k/boaj91KzHf9UuhEH8KYqp7szv+6kV00W8bRBtugw419dIm25eXFXgXDT9s/OA7qXV7o5FXWWpkyJ5AINVbY9DerkYag5TStrdOyKk+S1FexRG6TMG4L4Jyu/QxQGhMdu0m1yRCLvIekGtWLDnjNrI2SZrd5HbKprQ0O8j1770Is4q5blVPqAZ6O9jVMJRtVEaYbsJwItz1BJWkPT4S9GFbDL1dq2Z5jR2f5gd/cz2yYH56b47iYHWtzSqEfVhsXiN+atD+tWyQFA4Q/av0bGHwJ6LX0A1q0OCHruUMoxcw1QKfYtV1bkf/folL4Z4Hx3CL+NB0Lkqs8LFsQHxODP4a26I5DS/kaDHofotho8wsWlKFDtonZa+CExORGFFMPnGRz2qX5tMgGoo84wcqrprfoQv2llqeUr3gISPl2qxrljAhj3/Dcl7iI7k0Er7Ji8ENpgjSec4aqnBx8Ke2yaDEmBvwbouFCM= 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 skip_cleanup: true 119 skip_cleanup: true
@@ -119,6 +122,7 @@ deploy: @@ -119,6 +122,7 @@ deploy:
119 repo: CLIUtils/CLI11 122 repo: CLIUtils/CLI11
120 tags: true 123 tags: true
121 condition: "$DEPLOY_MAT = yes" 124 condition: "$DEPLOY_MAT = yes"
  125 +
122 notifications: 126 notifications:
123 webhooks: 127 webhooks:
124 urls: 128 urls:
@@ -126,6 +130,7 @@ notifications: @@ -126,6 +130,7 @@ notifications:
126 on_success: change 130 on_success: change
127 on_failure: always 131 on_failure: always
128 on_start: never 132 on_start: never
  133 +
129 env: 134 env:
130 global: 135 global:
131 - secure: cY0OI609iTAxLRYuYQnNMi+H6n0dBwioTAoFXGGRTnngw2V9om3UmY5eUu4HQEQsQZovHdYpNhlSgRmdwQ4UqSp3FGyrwobf0kzacV4bVnMDeXDmHt8RzE5wP/LwDd8elNF6RRYjElY99f0k0FyXVd0fIvuVkGKQECNLOtEk0jQo+4YTh7dhuCxRhBYgTbNiRL6UJynfrcK0YN+DQ+8CJNupu2VxgaEpCSngTfvDHLcddcrXwpvn3MPc3FsDUbtN389ZCIe41qqIL0ATv46DQaTw4FOevyVfRyrBOznONoGCVeAYKL6VBdrk01Fh6aytF5zgI3hKaKobgEn+QFfzR6l68c6APvqA0Qv39iLjuh6KbdIV2YsqXfyt6FBgqP2xZuNEZW1jZ8LxUOLl2I40UEh87nFutvnSbfIzN+FcLrajm2H2jV2kZGNKAMx+4qxkZuXSre4JPkENfJm2WNFAKlqPt4ZSEQarkDYzZPcEr2I9fbGjQYVJICoN4LikCv9K5z7ujpTxCTNbVpQWZcEOT6QQBc6Vml/N/NKAIl9o2OeTLiXCmT31+KQMeO492KYNQ6VmkeqrVhGExOUcJdNyDJV9C+3mSekb3Sq78SneYRKDechkWbMl0ol07wGTdBwQQwgaorjRyn07x1rDxpPr3z19/+eubnpPUW4UQ5MYsjs= 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,7 +4,7 @@ project(CLI11_Examples LANGUAGES CXX)
4 4
5 # Using CMake 3.11's ability to set imported interface targets 5 # Using CMake 3.11's ability to set imported interface targets
6 add_library(CLI11::CLI11 IMPORTED INTERFACE) 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 target_compile_features(CLI11::CLI11 INTERFACE cxx_std_11) 8 target_compile_features(CLI11::CLI11 INTERFACE cxx_std_11)
9 9
10 # Add CTest 10 # Add CTest
book/code/flags.cpp
1 -#include "CLI11.hpp" 1 +#include "CLI/CLI.hpp"
2 #include <iostream> 2 #include <iostream>
3 3
4 int main(int argc, char **argv) { 4 int main(int argc, char **argv) {
book/code/geet.cpp
1 -#include "CLI11.hpp" 1 +#include "CLI/CLI.hpp"
2 2
3 #include <iostream> 3 #include <iostream>
4 4
book/code/intro.cpp
1 -#include "CLI11.hpp" 1 +#include "CLI/CLI.hpp"
2 #include <iostream> 2 #include <iostream>
3 3
4 int main(int argc, char **argv) { 4 int main(int argc, char **argv) {
book/code/simplest.cpp
1 -#include "CLI11.hpp" 1 +#include "CLI/CLI.hpp"
2 2
3 int main(int argc, char **argv) { 3 int main(int argc, char **argv) {
4 CLI::App app; 4 CLI::App app;