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