Commit 1bf66bc3e5394910c5716ea98c81b7e1f411eeb0

Authored by Henry Fredrick Schreiner
1 parent 2f08c4c7

Moved to storing unique_ptr of Options, better support for --help

CHANGELOG.md 0 → 100644
  1 +## Version 0.2
  2 +
  3 +* Moved to simpler syntax, where `Option` pointers are returned and operated on
  4 +* Removed `make_` style options
  5 +* Simplified Validators, now only requires `->check(function)`
  6 +* Removed Combiners
  7 +* Fixed pointers to Options, stored in `unique_ptr` now
  8 +* Added `Option_p` and `App_p`, mostly for internal use
  9 +* Startup sequence, including help flag, can be modified by subclasses
  10 +
  11 +## Version 0.1
  12 +
  13 +Initial version
  14 +
  15 +
... ...
CMakeLists.txt
... ... @@ -15,7 +15,7 @@ endif()
15 15  
16 16 # Be moderately paranoid with flags
17 17 # But only globally, don't inherit
18   -add_compile_options(-pedantic -Wall -Wextra)
  18 +add_compile_options(-pedantic -Wall -Wextra -O0)
19 19  
20 20 add_library(CLI INTERFACE)
21 21 target_include_directories(CLI INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
... ...
README.md
... ... @@ -15,7 +15,7 @@ The following attributes are what I believe are important in a CLI parser librar
15 15 * Standard idioms supported naturally, like grouping flags, the positional seperator, etc.
16 16 * Easy to execute, with help, parse errors, etc. providing correct exit and details.
17 17 * Easy to extend as part of a framework that provides "applications".
18   -* Simple support for subcommands.
  18 +* Human readable support for subcommands.
19 19  
20 20 The major CLI parsers out there include:
21 21  
... ... @@ -30,7 +30,7 @@ So, this library was designed to provide a great syntax, good compiler compatibi
30 30  
31 31 To use, there are two methods.
32 32 1. Copy `CLI11.hpp` from the [most recent release](https://github.com/henryiii/CLI11/releases) into your include directory, and you are set. This is combined from the source files for every release.
33   -2. To be added.
  33 +2. Checkout the repository and add as a subdirectory for CMake. You can use the CLI interface target. (CMake 3.4+ recommended)
34 34  
35 35 To build the tests, get the entire directory and use CMake:
36 36  
... ... @@ -54,7 +54,7 @@ app.add_option("-f,--file", file, "A help string");
54 54  
55 55 try {
56 56 app.run(argc, argv);
57   -} catch (const CLI::Error &e) {
  57 +} catch (const CLI::ParseError &e) {
58 58 return app.exit(e);
59 59 }
60 60 ```
... ... @@ -66,33 +66,44 @@ The supported values are:
66 66 ```
67 67 app.add_options(option_name,
68 68 variable_to_bind_to, // int, float, vector, or string-like
69   - help_string,
70   - flags, ...) // Listed below
  69 + help_string="",
  70 + default=false)
71 71  
72 72 app.add_flag(option_name,
73   - optional_intlike_to_bind_to,
74   - help_string)
  73 + int_or_bool = nothing,
  74 + help_string="")
75 75  
76 76 app.add_set(option_name,
77 77 variable_to_bind_to,
78 78 set_of_possible_options,
79   - flags, ...)
  79 + help_string="",
  80 + default=false)
80 81  
81 82 App* subcom = app.add_subcommand(name, discription);
82 83  
83 84 ```
84 85  
  86 +An option name must start with a alphabetic character or underscore. For long options, anything but an equals sign or a comma is valid after that. Names are given as a comma separated string, with the dash or dashes. An option or flag can have as many names as you want, and afterward, using `count`, you can use any of the names, with dashes as needed, to count the options. One of the names is allowed to be given without proceeding dash(es); if present the option is a positional option, and that name will be used on help line for its positional form.
85 87  
86   -There are several flags:
  88 +> ### Example
  89 +>
  90 +> * `"one,-o,--one"`: Valid as long as not a flag, would create an option that can be specified positionally, or with `-o` or `--option`
  91 +> * `"this"` Can only be passed positionally
  92 +> * `"-a,-b,-c"` No limit to the number of non-positional option names
  93 +
  94 +
  95 +The add commands return a pointer to an internally stored `Option`. If you set the final argument to true, the default value is captured and printed on the command line with the help flag. This option can be used direcly to check for the count (`->count()`) after parsing to avoid a string based lookup. Before parsing, you can set the following options:
87 96  
88   -* `CLI::Default`: Print the default value in help
89   -* `CLI::Required`: The program will quit if this option is not present
90   -* `CLI::Opts(N)`: Take `N` values instead of as many as possible, only for vector args
91   -* `CLI::ExistingFile`: Requires that the file exists if given
92   -* `CLI::ExistingDirectory`: Requires that the directory exists
93   -* `CLI::NonexistentPath`: Requires that the path does not exist
  97 +* `->required()`: The program will quit if this option is not present
  98 +* `->expected(N)`: Take `N` values instead of as many as possible, only for vector args
  99 +* `->check(CLI::ExistingFile)`: Requires that the file exists if given
  100 +* `->check(CLI::ExistingDirectory)`: Requires that the directory exists
  101 +* `->check(CLI::NonexistentPath)`: Requires that the path does not exist
94 102  
95   -Options can be given as:
  103 +These options return the `Option` pointer, so you can chain them together, and even skip storing the pointer entirely. Check takes any function that has the signature `bool(std::string)`.
  104 +
  105 +
  106 +On the command line, options can be given as:
96 107  
97 108 * `-a` (flag)
98 109 * `-abc` (flags can be combined)
... ... @@ -103,8 +114,6 @@ Options can be given as:
103 114 * `--file filename` (space)
104 115 * `--file=filename` (equals)
105 116  
106   -An option must start with a alphabetic character or underscore. For long options, anything but an equals sign or a comma is valid after that. Names are given as a comma separated string, with the dash or dashes. An option or flag can have as many names as you want, and afterward, using `count`, you can use any of the names, with dashes as needed, to count the options. One of the names is allowed to be given without proceeding dash(es); if present the option is a positional option, and that name will be used on help line for its positional form.
107   -
108 117 Extra positional arguments will cause the program to exit, so at least one positional option with a vector is recommended if you want to allow extraneous arguments
109 118 If `--` is present in the command line,
110 119 everything after that is positional only.
... ... @@ -121,40 +130,14 @@ even exit the program through the callback. The main `App` has a callback slot,
121 130  
122 131 > ## Subclassing
123 132 >
124   -> The App class was designed allow toolkits to subclass it, to provide default options and setup/teardown code. Subcommands remain `App`'s, since those are not expected to need setup and teardown. The default `App` only adds a help flag, `-h,--help`.
  133 +> The App class was designed allow toolkits to subclass it, to provide default options and setup/teardown code. Subcommands remain `App`'s, since those are not expected to need setup and teardown. The default `App` only adds a help flag, `-h,--help` through the `virtual void setup()` method. If you only want to change this flag, override this method. Since subcommands are always the built in `App` object, they must have a normal help flag.
125 134 >
126   -> Also, in a related note, the `App`s you get a pointer to are stored in the parent `App` and cannot be deleted.
127   -
128   -## Make syntax
129   -
130   -A second, provisional syntax looks like this:
131   -
132   -```cpp
133   -CLI::App app{"App description"};
134   -
135   -auto filename = app.add_option("-f,--file", "default", "A help string");
136   -auto int_value = app.add_option<int>("-i,--int", "An int with no default");
137   -
138   -try {
139   - app.run(argc, argv);
140   -} catch (const CLI::Error &e) {
141   - return app.exit(e);
142   -}
143   -
144   -std::cout << "The file was: " << *filename << std::endl;
145   -std::cout << "This will throw an error if int not passed: " << *int_value << std::endl;
146   -```
147   -
148   -
149   -Internally, it uses the same mechanism to work, it just provides a single line definition, but requires a template argument for non-strings, and creates an object that must be dereferenced to be used. This object (`CLI::Value<type>`) supports conversion to bool, allowing you to easily check if an option was passed without resorting to count. Dereferencing will also throw an error if no value was passed and no default was given.
150   -
151   -The same functions as the first syntax are supported, only with `make` instead of `add`, and with the variable to bind to replaced by the default value (optional). If you want to use something other than a string option and do not want to give a default, you need to give a template parameter with the type.
  135 +> Also, in a related note, the `App`s you get a pointer to are stored in the parent `App` in `unique_ptr`s (like `Option`s) and are deleted when the main `App` goes out of scope.
152 136  
153   -`Value` wraps a `shared_ptr` to a `unique_ptr` to a value, so it lasts even if the `App` object is destructed.
154 137  
155 138 ## How it works
156 139  
157   -Every `make_` or `add_` option you've seen depends on one method that takes a lambda function. Each of these methods is just making a different lambda function with capture to populate the option. The function has full access to the vector of vector of strings, so it knows how many times an option was passed, and how many arguments each passing received (flags add empty strings to keep the counts correct). The lambda returns true if it could validate the option strings, and
  140 +Every `add_` option you've seen depends on one method that takes a lambda function. Each of these methods is just making a different lambda function with capture to populate the option. The function has full access to the vector of vector of strings, so it knows how many times an option was passed, and how many arguments each passing received (flags add empty strings to keep the counts correct). The lambda returns true if it could validate the option strings, and
158 141 false if it failed.
159 142  
160 143  
... ...
examples/try.cpp
... ... @@ -6,13 +6,13 @@ int main (int argc, char** argv) {
6 6 CLI::App app("K3Pi goofit fitter");
7 7  
8 8 std::string file;
9   - app.add_option("-f,--file,file", file, "File name");
  9 + CLI::Option* opt = app.add_option("-f,--file,file", file, "File name");
10 10  
11 11 int count;
12   - app.add_flag("-c,--count", count, "Counter");
  12 + CLI::Option* copt = app.add_flag("-c,--count", count, "Counter");
13 13  
14   - double value = 3.14;
15   - app.add_option("-d,--double", value, "Some Value", false);
  14 + double value;// = 3.14;
  15 + app.add_option("-d,--double", value, "Some Value");
16 16  
17 17 try {
18 18 app.run(argc, argv);
... ... @@ -20,8 +20,14 @@ int main (int argc, char** argv) {
20 20 return app.exit(e);
21 21 }
22 22  
23   - std::cout << "Working on file: " << file << ", direct count: " << app.count("--file") << std::endl;
24   - std::cout << "Working on count: " << count << ", direct count: " << app.count("--count") << std::endl;
  23 + std::cout << "Working on file: " << file
  24 + << ", direct count: " << app.count("--file")
  25 + << ", opt count: " << opt->count()
  26 + << std::endl;
  27 + std::cout << "Working on count: " << count
  28 + << ", direct count: " << app.count("--count")
  29 + << ", opt count: " << copt->count()
  30 + << std::endl;
25 31 std::cout << "Some value: " << value << std::endl;
26 32  
27 33 return 0;
... ...
examples/try1.cpp
... ... @@ -11,8 +11,7 @@ int main (int argc, char** argv) {
11 11 std::string file;
12 12 start->add_option("-f,--file", file, "File name");
13 13  
14   - int count;
15   - stop->add_flag("-c,--count", count, "Counter");
  14 + CLI::Option* s = stop->add_flag("-c,--count", "Counter");
16 15  
17 16 try {
18 17 app.run(argc, argv);
... ... @@ -21,7 +20,7 @@ int main (int argc, char** argv) {
21 20 }
22 21  
23 22 std::cout << "Working on file: " << file << ", direct count: " << start->count("--file") << std::endl;
24   - std::cout << "Working on count: " << count << ", direct count: " << stop->count("--count") << std::endl;
  23 + std::cout << "Working on count: " << s->count() << ", direct count: " << stop->count("--count") << std::endl;
25 24 if(app.get_subcommand() != nullptr)
26 25 std::cout << "Subcommand:" << app.get_subcommand()->get_name() << std::endl;
27 26  
... ...
include/CLI/App.hpp
... ... @@ -26,6 +26,11 @@ namespace CLI {
26 26  
27 27 enum class Classifer {NONE, POSITIONAL_MARK, SHORT, LONG, SUBCOMMAND};
28 28  
  29 +class App;
  30 +
  31 +typedef std::unique_ptr<Option> Option_p;
  32 +typedef std::unique_ptr<App> App_p;
  33 +
29 34 /// Creates a command line program, with very few defaults.
30 35 /** To use, create a new Program() instance with argc, argv, and a help description. The templated
31 36 * add_option methods make it easy to prepare options. Remember to call `.start` before starting your
... ... @@ -35,14 +40,14 @@ protected:
35 40  
36 41 std::string name;
37 42 std::string prog_description;
38   - std::vector<Option> options;
39   - Option* help_flag {nullptr};
  43 + std::vector<Option_p> options;
40 44 std::vector<std::string> missing_options;
41 45 std::deque<std::string> positionals;
42   - std::vector<std::unique_ptr<App>> subcommands;
  46 + std::vector<App_p> subcommands;
43 47 bool parsed{false};
44 48 App* subcommand{nullptr};
45 49 std::string progname{"program"};
  50 + Option* help_flag {nullptr};
46 51  
47 52 std::function<void()> app_callback;
48 53  
... ... @@ -67,10 +72,10 @@ public:
67 72 parsed = false;
68 73 subcommand = nullptr;
69 74  
70   - for(Option& opt : options) {
71   - opt.clear();
  75 + for(const Option_p &opt : options) {
  76 + opt->clear();
72 77 }
73   - for(std::unique_ptr<App> &app : subcommands) {
  78 + for(const App_p &app : subcommands) {
74 79 app->reset();
75 80 }
76 81 }
... ... @@ -100,8 +105,8 @@ public:
100 105 * After start is called, you can use count to see if the value was passed, and
101 106 * the value will be initialized properly.
102 107 *
103   - * Program::Required, Program::Default, and the validators are options, and can be `|`
104   - * together. The positional options take an optional number of arguments.
  108 + * ->required(), ->default, and the validators are options,
  109 + * The positional options take an optional number of arguments.
105 110 *
106 111 * For example,
107 112 *
... ... @@ -112,14 +117,17 @@ public:
112 117 std::string name,
113 118 callback_t callback,
114 119 std::string description="",
115   - bool defaulted=true
  120 + bool defaulted=false
116 121 ) {
117 122 Option myopt{name, description, callback, defaulted};
118   - if(std::find(std::begin(options), std::end(options), myopt) == std::end(options))
119   - options.push_back(myopt);
120   - else
  123 + if(std::find_if(std::begin(options), std::end(options),
  124 + [&myopt](const Option_p &v){return *v == myopt;}) == std::end(options)) {
  125 + options.emplace_back();
  126 + Option_p& option = options.back();
  127 + option.reset(new Option(name, description, callback, defaulted));
  128 + return option.get();
  129 + } else
121 130 throw OptionAlreadyAdded(myopt.get_name());
122   - return &options.back();
123 131  
124 132 }
125 133  
... ... @@ -129,7 +137,7 @@ public:
129 137 std::string name,
130 138 T &variable, ///< The variable to set
131 139 std::string description="",
132   - bool defaulted=true
  140 + bool defaulted=false
133 141 ) {
134 142  
135 143  
... ... @@ -159,7 +167,7 @@ public:
159 167 std::string name,
160 168 std::vector<T> &variable, ///< The variable vector to set
161 169 std::string description="",
162   - bool defaulted=true
  170 + bool defaulted=false
163 171 ) {
164 172  
165 173 CLI::callback_t fun = [&variable](CLI::results_t res){
... ... @@ -173,9 +181,6 @@ public:
173 181 return variable.size() > 0 && retval;
174 182 };
175 183  
176   - if(variable.size() == 0)
177   - defaulted = false;
178   -
179 184 Option* retval = add_option(name, fun, description, defaulted);
180 185 retval->allow_vector = true;
181 186 retval->_expected = -1;
... ... @@ -252,12 +257,12 @@ public:
252 257 Option* add_set(
253 258 std::string name,
254 259 T &member, ///< The selected member of the set
255   - std::set<T> options, ///< The set of posibilities
  260 + std::set<T> _options, ///< The set of posibilities
256 261 std::string description="",
257   - bool defaulted=true
  262 + bool defaulted=false
258 263 ) {
259 264  
260   - CLI::callback_t fun = [&member, options](CLI::results_t res){
  265 + CLI::callback_t fun = [&member, _options](CLI::results_t res){
261 266 if(res.size()!=1) {
262 267 return false;
263 268 }
... ... @@ -267,15 +272,17 @@ public:
267 272 bool retval = detail::lexical_cast(res[0][0], member);
268 273 if(!retval)
269 274 return false;
270   - return std::find(std::begin(options), std::end(options), member) != std::end(options);
  275 + return std::find(std::begin(_options), std::end(_options), member) != std::end(_options);
271 276 };
272 277  
273 278 Option* retval = add_option(name, fun, description, defaulted);
274 279 retval->typeval = detail::type_name<T>();
275   - retval->typeval += " in {" + detail::join(options) + "}";
276   - std::stringstream out;
277   - out << member;
278   - retval->defaultval = out.str();
  280 + retval->typeval += " in {" + detail::join(_options) + "}";
  281 + if(defaulted) {
  282 + std::stringstream out;
  283 + out << member;
  284 + retval->defaultval = out.str();
  285 + }
279 286 return retval;
280 287 }
281 288  
... ... @@ -328,17 +335,17 @@ public:
328 335  
329 336  
330 337  
331   - for(Option& opt : options) {
332   - while (opt.get_positional() && opt.count() < opt.get_expected() && positionals.size() > 0) {
333   - opt.get_new();
334   - opt.add_result(0, positionals.front());
  338 + for(const Option_p& opt : options) {
  339 + while (opt->get_positional() && opt->count() < opt->get_expected() && positionals.size() > 0) {
  340 + opt->get_new();
  341 + opt->add_result(0, positionals.front());
335 342 positionals.pop_front();
336 343 }
337   - if (opt.get_required() && opt.count() < opt.get_expected())
338   - throw RequiredError(opt.get_name());
339   - if (opt.count() > 0) {
340   - if(!opt.run_callback())
341   - throw ConversionError(opt.get_name());
  344 + if (opt->get_required() && opt->count() < opt->get_expected())
  345 + throw RequiredError(opt->get_name());
  346 + if (opt->count() > 0) {
  347 + if(!opt->run_callback())
  348 + throw ConversionError(opt->get_name());
342 349 }
343 350  
344 351 }
... ... @@ -350,7 +357,7 @@ public:
350 357 }
351 358  
352 359 void _parse_subcommand(std::vector<std::string> &args) {
353   - for(std::unique_ptr<App> &com : subcommands) {
  360 + for(const App_p &com : subcommands) {
354 361 if(com->name == args.back()){
355 362 args.pop_back();
356 363 subcommand = com.get();
... ... @@ -370,13 +377,16 @@ public:
370 377 throw HorribleError("Short");
371 378 args.pop_back();
372 379  
373   - auto op = std::find_if(std::begin(options), std::end(options), [name](const Option &v){return v.check_sname(name);});
  380 + auto op_ptr = std::find_if(std::begin(options), std::end(options), [name](const Option_p &opt){return opt->check_sname(name);});
374 381  
375   - if(op == std::end(options)) {
  382 + if(op_ptr == std::end(options)) {
376 383 missing_options.push_back("-" + name);
377 384 return;
378 385 }
379 386  
  387 + // Get a reference to the pointer to make syntax bearable
  388 + Option_p& op = *op_ptr;
  389 +
380 390 int vnum = op->get_new();
381 391 int num = op->get_expected();
382 392  
... ... @@ -414,7 +424,7 @@ public:
414 424  
415 425 if(current == "--")
416 426 return Classifer::POSITIONAL_MARK;
417   - for(const std::unique_ptr<App> &com : subcommands) {
  427 + for(const App_p &com : subcommands) {
418 428 if(com->name == current)
419 429 return Classifer::SUBCOMMAND;
420 430 }
... ... @@ -434,13 +444,15 @@ public:
434 444 throw HorribleError("Long");
435 445 args.pop_back();
436 446  
437   - auto op = std::find_if(std::begin(options), std::end(options), [name](const Option &v){return v.check_lname(name);});
  447 + auto op_ptr = std::find_if(std::begin(options), std::end(options), [name](const Option_p &v){return v->check_lname(name);});
438 448  
439   - if(op == std::end(options)) {
  449 + if(op_ptr == std::end(options)) {
440 450 missing_options.push_back("--" + name);
441 451 return;
442 452 }
443 453  
  454 + // Get a reference to the pointer to make syntax bearable
  455 + Option_p& op = *op_ptr;
444 456  
445 457 int vnum = op->get_new();
446 458 int num = op->get_expected();
... ... @@ -488,9 +500,9 @@ public:
488 500  
489 501 /// Counts the number of times the given option was passed.
490 502 int count(std::string name) const {
491   - for(const Option &opt : options) {
492   - if(opt.check_name(name)) {
493   - return opt.count();
  503 + for(const Option_p &opt : options) {
  504 + if(opt->check_name(name)) {
  505 + return opt->count();
494 506 }
495 507 }
496 508 throw OptionNotFound(name);
... ... @@ -512,8 +524,8 @@ public:
512 524  
513 525 // Check for options
514 526 bool npos = false;
515   - for(const Option &opt : options) {
516   - if(opt.nonpositional()) {
  527 + for(const Option_p &opt : options) {
  528 + if(opt->nonpositional()) {
517 529 npos = true;
518 530 break;
519 531 }
... ... @@ -524,10 +536,10 @@ public:
524 536  
525 537 // Positionals
526 538 bool pos=false;
527   - for(const Option &opt : options)
528   - if(opt.get_positional()) {
529   - out << " " << opt.help_positional();
530   - if(opt.has_description())
  539 + for(const Option_p &opt : options)
  540 + if(opt->get_positional()) {
  541 + out << " " << opt->help_positional();
  542 + if(opt->has_description())
531 543 pos=true;
532 544 }
533 545  
... ... @@ -536,9 +548,9 @@ public:
536 548 // Positional descriptions
537 549 if(pos) {
538 550 out << "Positionals:" << std::endl;
539   - for(const Option &opt : options)
540   - if(opt.get_positional() && opt.has_description())
541   - detail::format_help(out, opt.get_pname(), opt.get_description(), wid);
  551 + for(const Option_p &opt : options)
  552 + if(opt->get_positional() && opt->has_description())
  553 + detail::format_help(out, opt->get_pname(), opt->get_description(), wid);
542 554 out << std::endl;
543 555  
544 556 }
... ... @@ -547,9 +559,9 @@ public:
547 559 // Options
548 560 if(npos) {
549 561 out << "Options:" << std::endl;
550   - for(const Option &opt : options) {
551   - if(opt.nonpositional())
552   - detail::format_help(out, opt.help_name(), opt.get_description(), wid);
  562 + for(const Option_p &opt : options) {
  563 + if(opt->nonpositional())
  564 + detail::format_help(out, opt->help_name(), opt->get_description(), wid);
553 565  
554 566 }
555 567 out << std::endl;
... ... @@ -558,7 +570,7 @@ public:
558 570 // Subcommands
559 571 if(subcommands.size()> 0) {
560 572 out << "Subcommands:" << std::endl;
561   - for(const std::unique_ptr<App> &com : subcommands)
  573 + for(const App_p &com : subcommands)
562 574 detail::format_help(out, com->get_name(), com->prog_description, wid);
563 575 }
564 576 return out.str();
... ...
include/CLI/Error.hpp
... ... @@ -18,16 +18,6 @@ struct Error : public std::runtime_error {
18 18 Error(std::string parent, std::string name, int exit_code=255, bool print_help=true) : runtime_error(parent + ": " + name), exit_code(exit_code), print_help(print_help) {}
19 19 };
20 20  
21   -/// This is a successful completion on parsing, supposed to exit
22   -struct Success : public Error {
23   - Success() : Error("Success", "Successfully completed, should be caught and quit", 0, false) {}
24   -};
25   -
26   -/// -h or --help on command line
27   -struct CallForHelp : public Error {
28   - CallForHelp() : Error("CallForHelp", "This should be caught in your main function, see examples", 0) {}
29   -};
30   -
31 21 // Construction errors (not in parsing)
32 22  
33 23 struct ConstructionError : public Error {
... ... @@ -51,10 +41,24 @@ struct OptionAlreadyAdded : public ConstructionError {
51 41  
52 42 // Parsing errors
53 43  
  44 +/// Anything that can error in Parse
54 45 struct ParseError : public Error {
55 46 using Error::Error;
56 47 };
57 48  
  49 +// Not really "errors"
  50 +
  51 +/// This is a successful completion on parsing, supposed to exit
  52 +struct Success : public ParseError {
  53 + Success() : ParseError("Success", "Successfully completed, should be caught and quit", 0, false) {}
  54 +};
  55 +
  56 +/// -h or --help on command line
  57 +struct CallForHelp : public ParseError {
  58 + CallForHelp() : ParseError("CallForHelp", "This should be caught in your main function, see examples", 0) {}
  59 +};
  60 +
  61 +
58 62 /// Thrown when conversion call back fails, such as when an int fails to coerse to a string
59 63 struct ConversionError : public ParseError {
60 64 ConversionError(std::string name) : ParseError("ConversionError", name, 2) {}
... ... @@ -75,6 +79,8 @@ struct HorribleError : public ParseError {
75 79 HorribleError(std::string name) : ParseError("HorribleError", "(You should never see this error) " + name, 7) {}
76 80 };
77 81  
  82 +// After parsing
  83 +
78 84 /// Thrown when counting a non-existent option
79 85 struct OptionNotFound : public Error {
80 86 OptionNotFound(std::string name) : Error("OptionNotFound", name, 4) {}
... ...
include/CLI/Option.hpp
... ... @@ -43,7 +43,7 @@ protected:
43 43 std::vector<std::function<bool(std::string)>> _validators;
44 44  
45 45 // Results
46   - results_t results {};
  46 + results_t results;
47 47  
48 48  
49 49 public:
... ... @@ -206,8 +206,8 @@ public:
206 206 /// Count the total number of times an option was passed
207 207 int count() const {
208 208 int out = 0;
209   - for(const std::vector<std::string>& v : results)
210   - out += v.size();
  209 + for(const std::vector<std::string>& vec : results)
  210 + out += vec.size();
211 211 return out;
212 212 }
213 213  
... ...