Commit 4917b8b7638011d70d8e830862d0376c35056bac

Authored by Henry Schreiner
Committed by GitHub
1 parent cf4933db

Moving tutorial docs (#304)

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