### CLI11 Callback Setup Example Source: https://github.com/cliutils/cli11/blob/main/README.md Demonstrates how to set up preparse, parse_complete, and final callbacks for a main application and its subcommands in CLI11. Callbacks are executed at different stages of argument processing. ```cpp app.parse_complete_callback(ac1); app.final_callback(ac2); auto sub1=app.add_subcommand("sub1")->parse_complete_callback(c1)->preparse_callback(pc1); auto sub2=app.add_subcommand("sub2")->final_callback(c2)->preparse_callback(pc2); app.preparse_callback( pa); ``` -------------------------------- ### Install CLI11 using vcpkg Source: https://github.com/cliutils/cli11/blob/main/book/chapters/installation.md Clone the vcpkg repository, bootstrap it, integrate it with your system, and then install CLI11. ```bash git clone https://github.com/Microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg integrate install ./vcpkg install cli11 ``` -------------------------------- ### Build and Test CLI11 with Docker Source: https://github.com/cliutils/cli11/blob/main/book/chapters/installation.md This example demonstrates how to clone, build, and test CLI11 within a Docker container. Ensure you have Docker installed and internet access for cloning and dependency downloads. ```term gitbook:~ $ docker run -it alpine root:/ # apk add --no-cache g++ cmake make git fetch ... root:/ # git clone https://github.com/CLIUtils/CLI11.git Cloning into 'CLI11' ... root:/ # cd CLI11 root:CLI11 # mkdir build root:CLI11 # cd build root:build # cmake .. -- The CXX compiler identification is GNU 6.3.0 ... root:build # make Scanning dependencies ... root:build # make test [warning]Running tests... Test project /CLI11/build Start 1: HelpersTest 1/10 Test #1: HelpersTest ...................... Passed 0.01 sec Start 2: IniTest 2/10 Test #2: IniTest .......................... Passed 0.01 sec Start 3: SimpleTest 3/10 Test #3: SimpleTest ....................... Passed 0.01 sec Start 4: AppTest 4/10 Test #4: AppTest .......................... Passed 0.02 sec Start 5: CreationTest 5/10 Test #5: CreationTest ..................... Passed 0.01 sec Start 6: SubcommandTest 6/10 Test #6: SubcommandTest ................... Passed 0.01 sec Start 7: HelpTest 7/10 Test #7: HelpTest ......................... Passed 0.01 sec Start 8: NewParseTest 8/10 Test #8: NewParseTest ..................... Passed 0.01 sec Start 9: TimerTest 9/10 Test #9: TimerTest ........................ Passed 0.24 sec Start 10: link_test_2 10/10 Test #10: link_test_2 ...................... Passed 0.00 sec 100% tests passed, 0 tests failed out of 10 Total Test time (real) = 0.34 sec ``` -------------------------------- ### Install CLI11 using apt on Ubuntu Source: https://github.com/cliutils/cli11/blob/main/book/chapters/installation.md Install the CLI11 development package on Ubuntu using apt. ```bash sudo apt install libcli11-dev ``` -------------------------------- ### Install CLI11 Targets and Headers Source: https://github.com/cliutils/cli11/blob/main/src/CMakeLists.txt Handles the installation of the CLI11 library, its export targets, and header files. It conditionally installs implementation headers based on build configurations and installation flags. ```cmake if(CLI11_INSTALL OR CLI11_FULL_INSTALL) # Make an export target install(TARGETS CLI11 EXPORT CLI11Targets) if((NOT CLI11_SINGLE_FILE) OR CLI11_FULL_INSTALL) install(FILES ${CLI11_headers} ${CLI11_library_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/CLI") if(NOT (CLI11_DISABLE_IMPL_HEADERS_INSTALL AND CLI11_PRECOMPILED)) install(FILES ${CLI11_impl_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/CLI/impl") endif() endif() endif() ``` -------------------------------- ### JSON Example with CLI11 Source: https://github.com/cliutils/cli11/blob/main/examples/CMakeLists.txt Builds an example executable that uses nlohmann/json for configuration. It demonstrates fetching the JSON library, adding the executable, and setting up tests for JSON input and output. ```cmake if(CLI11_BUILD_EXAMPLES_JSON AND CMAKE_VERSION VERSION_GREATER "3.14.7") message(STATUS "Using nlohmann/json") FetchContent_Declare( json URL https://github.com/nlohmann/json/releases/download/v3.7.3/include.zip URL_HASH "SHA256=87b5884741427220d3a33df1363ae0e8b898099fbc59f1c451113f6732891014") FetchContent_MakeAvailable(json) add_cli_exe(json json.cpp) target_include_directories(json PUBLIC SYSTEM "${json_SOURCE_DIR}/single_include") add_test(NAME json_config_out COMMAND json --item 2) set_property(TEST json_config_out PROPERTY PASS_REGULAR_EXPRESSION [=[\{.*"item": "2".*"simple": false.*\}]=]) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/input.json" [=[{"item":3,"simple":false}]=]) add_test(NAME json_config_in COMMAND json --config "${CMAKE_CURRENT_BINARY_DIR}/input.json") set_property(TEST json_config_in PROPERTY PASS_REGULAR_EXPRESSION [=[\{.*"item": "3".*"simple": false.*\}]=]) endif() ``` -------------------------------- ### Simple CLI Example Source: https://github.com/cliutils/cli11/blob/main/examples/CMakeLists.txt Adds a basic 'simple' executable and configures tests for its default behavior, argument parsing, and version display. ```cmake add_cli_exe(simple simple.cpp) add_test(NAME simple_basic COMMAND simple) add_test(NAME simple_all COMMAND simple -f filename.txt -c 12 --flag --flag -d 1.2) set_property( TEST simple_all PROPERTY PASS_REGULAR_EXPRESSION [=[Working on file: filename.txt, direct count: 1, opt count: 1.*Working on count: 12, direct count: 1, opt count: 1.*Received flag: 2 (2) times.*Some value: 1.2]=] ) add_test(NAME simple_version COMMAND simple --version) set_property(TEST simple_version PROPERTY PASS_REGULAR_EXPRESSION "${CLI11_VERSION}") ``` -------------------------------- ### TOML Configuration File Example Source: https://github.com/cliutils/cli11/blob/main/README.md Example of a TOML file format for CLI11 configuration. Supports comments, sections mapping to subcommands, and various data types. ```toml # Comments are supported, using a # # The default section is [default], case-insensitive value = 1 value2 = 123_456 # a string with separators str = "A string" str2 = "A string\nwith new lines" str3 = 'A literal "string"' vector = [1,2,3] str_vector = ["one","two","and three"] # Sections map to subcommands [subcommand] in_subcommand = Wow sub.subcommand = true "sub"."subcommand2" = "string_value" ``` -------------------------------- ### INI Configuration File Example Source: https://github.com/cliutils/cli11/blob/main/README.md Example of an INI file format for CLI11 configuration. Supports comments, sections, and basic data types. ```ini ; Comments are supported, using a ; ; The default section is [default], case-insensitive value = 1 str = "A string" vector = 1 2 3 str_vector = "one" "two" "and three" ; Sections map to subcommands [subcommand] in_subcommand = Wow sub.subcommand = true ``` -------------------------------- ### Install CLI11 using dnf on Fedora/Almalinux Source: https://github.com/cliutils/cli11/blob/main/book/chapters/installation.md Install the CLI11 development package on Fedora or Almalinux using dnf. ```bash sudo dnf install cli11-devel ``` -------------------------------- ### Example Flag Usage and Output Source: https://github.com/cliutils/cli11/blob/main/book/chapters/flags.md Demonstrates compiling and running a program that uses various flags, showing the command-line arguments and the resulting output. ```term gitbook:examples $ g++ -std=c++11 flags.cpp gitbook:examples $ ./a.out -h Flag example program Usage: ./a.out [OPTIONS] Options: -h,--help Print this help message and exit -b,--bool This is a bool flag -i,--int This is an int flag -p,--plain This is a plain flag gitbook:examples $ ./a.out -bii --plain -i The flags program Bool flag passed Flag int: 3 Flag plain: 1 ``` -------------------------------- ### CLI11 Option Formatting Example Source: https://github.com/cliutils/cli11/blob/main/book/chapters/formatting.md Shows the typical structure of a formatted option in the help message, detailing which methods generate each part. ```text make_option_opts(o) ┌───┴────┐ -n,--name (REQUIRED) This is a description └────┬────┘ └──────────┬──────────┘ make_option_name(o,p) make_option_desc(o) ``` -------------------------------- ### Install CLI11 using Conan Source: https://github.com/cliutils/cli11/blob/main/book/chapters/installation.md Install CLI11 using Conan, a C/C++ package manager. This command fetches pre-built binaries or builds from source if missing. ```bash conan install --requires="cli11/[*]" --build=missing ``` -------------------------------- ### Initialize App and Require Subcommand (C++) Source: https://github.com/cliutils/cli11/blob/main/book/chapters/an-advanced-example.md Sets up the main application and enforces that at least one subcommand must be provided. This is the initial setup for the 'geet' application. ```cpp #include int main(int argc, char **argv) { CLI::App app{"geet - a git clone"}; // Add a subcommand, which is required auto add = app.add_subcommand("add", "Add files to the index"); auto commit = app.add_subcommand("commit", "Record changes to the repository"); // Have to parse, or the subcommands won't be processed try { app.parse(argc, argv); } catch (const CLI::ParseError &e) { return app.exit(e); } return 0; } ``` -------------------------------- ### INI Configuration File Example Source: https://github.com/cliutils/cli11/blob/main/book/chapters/config.md Demonstrates basic INI configuration with comments, default section, key-value pairs, and subcommand mapping. Supports standard INI syntax. ```ini ; Comments are supported, using a ; ; The default section is [default], case-insensitive value = 1 str = "A string" vector = 1 2 3 ; Section map to subcommands [subcommand] in_subcommand = Wow sub.subcommand = true ``` -------------------------------- ### CLI11 Command Line Example Source: https://github.com/cliutils/cli11/blob/main/README.md Illustrates a sample command line input for a CLI11 application with subcommands and options, demonstrating how arguments are parsed and callbacks are triggered. ```bash program --opt1 opt1_val sub1 --sub1opt --sub1optb val sub2 --sub2opt sub1 --sub1opt2 sub2 --sub2opt2 val ``` -------------------------------- ### Compile CLI11 Example Source: https://github.com/cliutils/cli11/blob/main/book/README.md Command to compile a C++ file using CLI11 with GCC, specifying C++11 standard. ```bash c++ -std=c++11 intro.cpp ``` -------------------------------- ### Basic CLI App Setup and Option Parsing Source: https://github.com/cliutils/cli11/blob/main/README.md Set up a CLI application with a description, ensure UTF-8 compatibility, add a file option, and parse command-line arguments. This is the standard way to initialize and run a CLI11 application. ```cpp int main(int argc, char** argv) { CLI::App app{"App description"}; argv = app.ensure_utf8(argv); std::string filename = "default"; app.add_option("-f,--file", filename, "A help string"); CLI11_PARSE(app, argc, argv); return 0; } ``` -------------------------------- ### Trivial JSON Configuration Example Source: https://github.com/cliutils/cli11/blob/main/book/chapters/config.md A basic JSON structure that can be parsed with minor configuration tweaks. This format is suitable for simple configurations. ```JSON { "test": 56, "testb": "test", "flag": true } ``` -------------------------------- ### Add Example Fuzzing Executable Source: https://github.com/cliutils/cli11/blob/main/fuzz/CMakeLists.txt Conditionally adds an executable for fuzzing examples if CLI11_BUILD_EXAMPLES is enabled. This executable is placed in the 'Examples' folder. ```cmake if(CLI11_BUILD_EXAMPLES) add_executable(cli11Fuzz fuzzCommand.cpp fuzzApp.cpp fuzzApp.hpp) target_link_libraries(cli11Fuzz PUBLIC CLI11) set_property(TARGET cli11Fuzz PROPERTY FOLDER "Examples") endif() ``` -------------------------------- ### Setup Vector Option Source: https://github.com/cliutils/cli11/blob/main/book/chapters/options.md Define a vector option to accept multiple values. By default, it accepts values until the next valid option name. ```cpp std::vector int_vec; app.add_option("--vec", int_vec, "My vector option"); ``` -------------------------------- ### Setup Vector of Vectors Option Source: https://github.com/cliutils/cli11/blob/main/book/chapters/options.md Define a vector of vectors to handle nested lists of values. Use `%%` to separate inner vectors on the command line. ```cpp std::vector> int_vec; app.add_option("--vec", int_vec, "My vector of vectors option"); ``` -------------------------------- ### Partitioned Subcommands CLI Example Source: https://github.com/cliutils/cli11/blob/main/examples/CMakeLists.txt Adds a 'subcom_partitioned' executable and configures tests to check its behavior with required arguments and optional arguments, including timer functionality. ```cmake add_cli_exe(subcom_partitioned subcom_partitioned.cpp) add_test(NAME subcom_partitioned_none COMMAND subcom_partitioned) set_property( TEST subcom_partitioned_none PROPERTY PASS_REGULAR_EXPRESSION [=[--file is required.*Run with --help for more information..*This is a timer:]=]) add_test(NAME subcom_partitioned_all COMMAND subcom_partitioned --file this --count --count -d 1.2) set_property( TEST subcom_partitioned_all PROPERTY PASS_REGULAR_EXPRESSION [=[Working on file: this, direct count: 1, opt count: 1.*Working on count: 2, direct count: 2, opt count: 2.*Some value: 1.2.*This is a timer:]=] ) ``` -------------------------------- ### Subcommands CLI Example Source: https://github.com/cliutils/cli11/blob/main/examples/CMakeLists.txt Adds a 'subcommands' executable and configures tests to verify its behavior with and without subcommands, including argument parsing within subcommands. ```cmake add_cli_exe(subcommands subcommands.cpp) add_test(NAME subcommands_none COMMAND subcommands) set_property(TEST subcommands_none PROPERTY PASS_REGULAR_EXPRESSION "A subcommand is required") add_test( NAME subcommands_all COMMAND subcommands --random start --file name stop --count) set_property( TEST subcommands_all PROPERTY PASS_REGULAR_EXPRESSION [=[Working on --file from start: name.*Working on --count from stop: 1, direct count: 1.*Count of --random flag: 1.*Subcommand: start.*Subcommand: stop]=] ) ``` -------------------------------- ### Get Config Formatter and Write Subcommand Config Source: https://github.com/cliutils/cli11/blob/main/book/chapters/config.md Obtain the configuration formatter and use it to write configuration for a specific subcommand, including defaults and descriptions, with a custom prefix. ```cpp auto fmtr=app.get_config_formatter(); //std::string to_config(const App *app, bool default_also, bool write_description, std::string prefix) fmtr->to_config(&app,true,true,"sub."); //prefix can be used to set a prefix before each argument, like "sub." ``` -------------------------------- ### Example of Fallthrough in CLI11 Source: https://github.com/cliutils/cli11/blob/main/book/chapters/subcommands.md Demonstrates how an option not matched by a subcommand can fall through to the parent command. This is enabled using `->fallthrough()` on a subcommand. ```term ./my_program my_model_1 --model_flag --shared_flag ``` -------------------------------- ### Get Config Formatter with ConfigOutputMode Source: https://github.com/cliutils/cli11/blob/main/book/chapters/config.md Use the configuration formatter with a specific `CLI::ConfigOutputMode` to control which configuration values are included, along with descriptions and a prefix. ```cpp auto fmtr=app.get_config_formatter(); //std::string to_config(const App *app, CLI::ConfigOutputMode mode, bool write_description, std::string prefix) fmtr->to_config(&app,CLI::ConfigOutputMode::ActiveSubcommandDefaults,true,"sub."); ``` -------------------------------- ### Define 'add' Subcommand with Options (C++) Source: https://github.com/cliutils/cli11/blob/main/book/chapters/an-advanced-example.md Defines the 'add' subcommand for the 'geet' application, including options for specifying files. This snippet extends the initial app setup. ```cpp #include int main(int argc, char **argv) { CLI::App app{"geet - a git clone"}; auto add = app.add_subcommand("add", "Add files to the index"); // Add options to the add subcommand add->add_option("files", "Files to add"); auto commit = app.add_subcommand("commit", "Record changes to the repository"); try { app.parse(argc, argv); } catch (const CLI::ParseError &e) { return app.exit(e); } return 0; } ``` -------------------------------- ### Setup Map with Nested Pair Option Source: https://github.com/cliutils/cli11/blob/main/book/chapters/options.md Define a map where values are pairs. Each invocation requires multiple arguments corresponding to the nested types. ```cpp std::map> map; app.add_option("--dict", map, "map of pairs"); ``` -------------------------------- ### Code Coverage Setup Source: https://github.com/cliutils/cli11/blob/main/tests/CMakeLists.txt Includes the CodeCoverage module and sets up the 'ctest' target for LCOV code coverage collection if the build type is 'Coverage'. ```cmake if(CMAKE_BUILD_TYPE STREQUAL Coverage) include(CodeCoverage) setup_target_for_coverage_lcov( NAME CLI11_coverage EXECUTABLE ctest DEPENDENCIES ${CLI11_TESTS} ${CLI11_MULTIONLY_TESTS}) endif() ``` -------------------------------- ### Setup Map with Pair of Vectors Option Source: https://github.com/cliutils/cli11/blob/main/book/chapters/options.md Define a map where values are pairs of vectors. Each invocation requires specific arguments, and vectors can absorb an unlimited number of strings. ```cpp std::map>> map; app.add_option("--dict", map, "map of pairs"); ``` -------------------------------- ### Set Option Defaults and Inheritance Source: https://github.com/cliutils/cli11/blob/main/book/chapters/options.md Configure default settings for options and subcommands using `option_defaults()`. These defaults are inherited at the point of creation. Example shows ignoring case and setting a group. ```cpp app.option_defaults()->ignore_case()->group("Required"); app.add_flag("--CaSeLeSs"); app.get_group() // is "Required" ``` -------------------------------- ### Create Shim for Single-File Tests with CMake Source: https://github.com/cliutils/cli11/blob/main/tests/CMakeLists.txt Conditionally writes a shim header file for single-file tests and installs it if the CLI11_SINGLE_FILE and CLI11_INSTALL_PACKAGE_TESTS options are enabled. ```cmake if(CLI11_SINGLE_FILE AND CLI11_INSTALL_PACKAGE_TESTS) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_single/CLI/CLI.hpp" "#include ") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/test_single/CLI/CLI.hpp" DESTINATION include/CLI) endif() ``` -------------------------------- ### Retrieve Validator by Index Source: https://github.com/cliutils/cli11/blob/main/README.md Get a pointer to a validator using its application index. Returns `nullptr` if the index is invalid. ```cpp auto *validator = opt->get_validator(index); ``` -------------------------------- ### Setup Pair of Vectors Option Source: https://github.com/cliutils/cli11/blob/main/book/chapters/options.md Define a pair of vectors to store two distinct lists of values. The separator `%%` is crucial for distinguishing values between the pair elements. ```cpp std::pair,std::vector> two_vecs; app.add_option("--vec", two_vecs, "pair of vectors"); ``` -------------------------------- ### Subcommand Mapping in INI Source: https://github.com/cliutils/cli11/blob/main/book/chapters/config.md Map configuration sections to subcommands using dot notation. This example shows how 'subcommand' maps to 'in_subcommand' and 'sub.subcommand' maps to 'subcommand'. ```ini [subcommand] in_subcommand = Wow [subcommand.sub] subcommand = true ``` -------------------------------- ### Retrieve Validator by Name Source: https://github.com/cliutils/cli11/blob/main/README.md Get a pointer to a named validator associated with an option. Throws `CLI::OptionNotFound` if the name is invalid. ```cpp auto *validator = opt->get_validator(name); ``` -------------------------------- ### Get All Remaining Arguments Source: https://github.com/cliutils/cli11/blob/main/book/chapters/subcommands.md Retrieve all remaining command-line arguments, including those from subcommands, in their original order. Pass `true` to include arguments from nested subcommands. ```cpp app.remaining(true); ``` -------------------------------- ### Get Used Configuration File Name Source: https://github.com/cliutils/cli11/blob/main/book/chapters/config.md Retrieves the name of the configuration file that was actually used by the application. This assumes a configuration option like '--config' has been set. ```cpp app.get_config_ptr()->as() ``` ```cpp app["--config"]->as() ``` -------------------------------- ### Find and Check CLI11 Package with PkgConfig Source: https://github.com/cliutils/cli11/blob/main/tests/package_config_tests/CMakeLists.txt This snippet finds the CLI11 package using PkgConfig and checks for its availability. It ensures that CLI11 is installed and configured correctly for use in the project. ```cmake find_package(PkgConfig) if(CLI11_DIR) set(CMAKE_PREFIX_PATH ${CLI11_DIR} ${CLI11_DIR}/lib) endif() message(STATUS "${CLI11_DIR}-- ${CMAKE_PREFIX_PATH}") pkg_check_modules(CLI11 REQUIRED IMPORTED_TARGET CLI11) ``` -------------------------------- ### Modify Value Separator for Configuration Source: https://github.com/cliutils/cli11/blob/main/book/chapters/config.md Example of how to change the character used to separate names from values in the configuration file. This is useful for formats that do not use the standard '='. ```cpp auto config_base=app.get_config_formatter_base(); config_base->valueSeparator(':'); ``` -------------------------------- ### Subclass CLI::Formatter to Customize Help Output Source: https://github.com/cliutils/cli11/blob/main/book/chapters/formatting.md Subclass `CLI::Formatter` and override methods like `make_option_opts` to customize specific parts of the help message. This example removes the option flags from the output. ```cpp class MyFormatter : public CLI::Formatter { public: std::string make_option_opts(const CLI::Option *) const override {return "";} }; app.formatter(std::make_shared()); ``` -------------------------------- ### Chain Validator Operations Source: https://github.com/cliutils/cli11/blob/main/README.md Validator operations like `description`, `active`, and `name` can be chained. This example sets a description, deactivates the validator, and assigns a name. ```cpp opt->check(CLI::Range(10,20).description("range is limited to sensible values").active(false).name("range")); ``` -------------------------------- ### Custom Option Parser Lambda Source: https://github.com/cliutils/cli11/blob/main/README.md Adds a custom option that uses a lambda function to process its arguments. This example prints how many times the option was provided. ```cpp app.add_option("--fancy-count", [](std::vector val){ std::cout << "This option was given " << val.size() << " times." << std::endl; return true; }); ``` -------------------------------- ### Customize Option with Expected Values Source: https://github.com/cliutils/cli11/blob/main/book/chapters/options.md Use `expected(N)` or `expected(Nmin, Nmax)` to define the number of values an option can accept. This example creates a hybrid flag that uses a default value or an explicitly provided one. ```cpp std::string val; auto opt=app.add_flag("--opt{vvv}",val,"description"); opt->expected(0,1); ``` -------------------------------- ### Define Flag with Explicit Default Value Source: https://github.com/cliutils/cli11/blob/main/README.md This syntax explicitly sets the default value for a flag. It is equivalent to the previous example but more verbose. This also works for short form options. ```cpp "--flag,--no-flag{false}" ``` -------------------------------- ### Combine CLI11 Validators with OR Source: https://github.com/cliutils/cli11/blob/main/README.md Shows how to combine multiple validators using the OR operator (|) to create a check that accepts values satisfying either condition. For example, ensuring a value is within one of two ranges. ```cpp ->check(CLI::Range(0,10)|CLI::Range(20,30)); ``` -------------------------------- ### Compile and Test Simplest CLI11 Program Source: https://github.com/cliutils/cli11/blob/main/book/chapters/basics.md Demonstrates how to compile a C++ file using g++ and then run the executable with the help flag to see the generated usage information. ```bash g++ -std=c++11 simplest.cpp ./a.out -h ``` -------------------------------- ### Print Configuration to String (All Defaults) Source: https://github.com/cliutils/cli11/blob/main/book/chapters/config.md Write the active configuration values, including defaulted arguments for the app and all subcommands, to a string. Descriptions are also included. ```cpp CLI::App app; app.add_option(...); // several other options CLI11_PARSE(app, argc, argv); //the config printout should be after the parse to capture the given arguments std::cout<delimiter(',')` to define a custom character for separating single arguments into vector arguments. For example, `--opt=1,2,3` with a comma delimiter will result in three vector elements. ```cpp ->delimiter(char) ``` -------------------------------- ### Build CLI11 with Meson Source: https://github.com/cliutils/cli11/blob/main/tests/mesonTest/README.md Use these commands to configure and build the project using Meson and Ninja. ```bash meson build ``` ```bash ninja -C build ``` -------------------------------- ### Allow Multiple Configuration Files Source: https://github.com/cliutils/cli11/blob/main/book/chapters/config.md Configure the application to accept multiple configuration files by specifying a positive integer for the expected number of `--config` arguments. ```cpp app.set_config("--config")->expected(1, X); ``` -------------------------------- ### Build and Test CLI11 with CMake Source: https://github.com/cliutils/cli11/blob/main/AGENTS.md Use CMake's default workflow for configuring, building, and testing the library. Alternatively, manually configure, build, and run tests. ```bash cmake --workflow default ``` ```bash cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug cmake --build build -j4 cmake --build build --target test # or: cd build && ctest --output-on-failure ``` -------------------------------- ### Package Search Location Source: https://github.com/cliutils/cli11/blob/main/tests/CMakeLists.txt Initializes a variable for specifying custom search locations for packages. This is typically used to guide CMake's find_package commands. ```cmake set(CLI11_PACKAGE_SEARCH_LOC "") ``` -------------------------------- ### Configure CLI11 with CMake Presets Source: https://github.com/cliutils/cli11/blob/main/AGENTS.md Utilize CMake presets for streamlined configuration and building, such as the 'tidy' preset for linting. ```bash cmake --preset tidy cmake --build --preset tidy ``` -------------------------------- ### Add Subcommands and Option Groups Source: https://github.com/cliutils/cli11/blob/main/README.md Illustrates how to define subcommands and group related options together for better organization within the CLI. ```cpp // Add subcommands App* subcom = app.add_subcommand(name, description); ``` ```cpp Option_group *app.add_option_group(name,description); ``` -------------------------------- ### Basic CLI11 Program with Optional Parameter Source: https://github.com/cliutils/cli11/blob/main/book/README.md This is a simple program demonstrating an optional parameter with a default value. It shows how CLI11 handles basic argument parsing and help messages. ```cpp #include #include int main(int argc, char **argv) { CLI::App app("App description"); int parameter = 0; app.add_option("-p,--parameter", parameter, "Parameter"); CLI11_PARSE(app, argc, argv); std::cout << "Parameter value: " << parameter << std::endl; return 0; } ``` -------------------------------- ### Custom Configuration Format Implementation Source: https://github.com/cliutils/cli11/blob/main/book/chapters/config.md To implement a custom configuration format, inherit from `CLI::Config` and implement the `to_config` and `from_config` methods. The `CLI::ConfigItem` structure is used for parsing. ```cpp std::string to_config(const CLI::App *app, bool default_also, bool, std::string) const; std::vector from_config(std::istream &input) const; ``` -------------------------------- ### Set Multi-Option Policy for Config Files Source: https://github.com/cliutils/cli11/blob/main/book/chapters/config.md Configures how multiple configuration files are processed. The default is 'Reverse' (last file takes precedence), but 'TakeAll' reads them in the order given. ```cpp app.set_config("--config") ->multi_option_policy(CLI::MultiOptionPolicy::TakeAll); ``` -------------------------------- ### Use a Formatting Callback in CLI11 Source: https://github.com/cliutils/cli11/blob/main/book/chapters/formatting.md Provides a simple callback function to replace the default help message generation. The callback receives the App, usage name, and format mode, and returns the formatted string. ```cpp app.formatter_fn( [](const CLI::App *, std::string, CLI::AppFormatMode) { return std::string("This is really simple"); }); ``` -------------------------------- ### Set Option Description in CLI11 Source: https://github.com/cliutils/cli11/blob/main/README.md Use the `->description()` method to set or change the help text for an option. This is useful for providing clear explanations to users. ```cpp ->description(str) ``` -------------------------------- ### Include Single File Edition of CLI11 Source: https://github.com/cliutils/cli11/blob/main/book/chapters/installation.md Use this for the simplest integration. Download CLI11.hpp and place it in your project's source directory or include path. ```cpp #include ``` -------------------------------- ### CLI11 Add Required Option with Existing File Check Source: https://github.com/cliutils/cli11/blob/main/book/README.md Example of adding a required option that checks for the existence of a file. The option is bound to a std::string variable. ```cpp std::string file; app.add_option("-f,--file", file, "Require an existing file") ->required() ->check(CLI::ExistingFile); ``` -------------------------------- ### Find and Configure Catch2 Testing Framework Source: https://github.com/cliutils/cli11/blob/main/tests/CMakeLists.txt Finds the Catch2 testing framework. If found, it configures the 'catch_main' library appropriately for Catch2 v2 or v3. If not found, it downloads the catch.hpp header. ```cmake find_package(Catch2 CONFIG QUIET) if(Catch2_FOUND) if(NOT TARGET Catch2::Catch2) message(FATAL_ERROR "Found Catch2 at ${Catch2_DIR} but targets are missing.") endif() message(STATUS "Found Catch2 ${Catch2_VERSION}") if(Catch2_VERSION VERSION_LESS 3) add_library(catch_main main.cpp catch.hpp) target_include_directories(catch_main PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") target_link_libraries(catch_main PUBLIC Catch2::Catch2) else() add_library(catch_main ALIAS Catch2::Catch2WithMain) target_compile_definitions(Catch2::Catch2WithMain INTERFACE -DCLI11_CATCH3) endif() else() set(catch2_url https://github.com/philsquared/Catch/releases/download/v2.13.10/catch.hpp) set(catch2_header "${CMAKE_CURRENT_BINARY_DIR}/catch2/catch.hpp") set(catch2_hash "3725c0f0a75f376a5005dde31ead0feb8f7da7507644c201b814443de8355170") if(EXISTS "${catch2_header}") file(SHA256 "${catch2_header}" catch2_cached_hash) endif() if(EXISTS "${catch2_header}" AND catch2_cached_hash STREQUAL catch2_hash) message(STATUS "Using cached Catch2 header") else() message(STATUS "Catch2 not found; downloading Catch2") # FetchContent would be better, but requires newer CMake. file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/catch2") file( DOWNLOAD ${catch2_url} "${catch2_header}" STATUS status EXPECTED_HASH SHA256=${catch2_hash}) list(GET status 0 error) if(error) message(FATAL_ERROR "Could not download ${catch2_url}, and Catch2 not found on your system.") endif() endif() add_library(catch_main main.cpp catch.hpp) target_include_directories(catch_main PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") endif() ``` -------------------------------- ### Basic CLI11 Application Structure Source: https://github.com/cliutils/cli11/blob/main/book/chapters/installation.md Include necessary CLI11 headers and parse command-line arguments in your C++ application. ```cpp #include "CLI/App.hpp" #include "CLI/Formatter.hpp" #include "CLI/Config.hpp" int main(int argc, char** argv) { CLI::App app{"MyApp"}; // Here your flags / options CLI11_PARSE(app, argc, argv); } ``` -------------------------------- ### Include Full Edition of CLI11 Source: https://github.com/cliutils/cli11/blob/main/book/chapters/installation.md Use this for the full CLI11 features, including the Timer utility. The include statement changes slightly. ```cpp #include ``` -------------------------------- ### Simplest CLI11 Program Source: https://github.com/cliutils/cli11/blob/main/book/chapters/basics.md This is the most basic structure for a CLI11 application. It includes the necessary header and sets up the application object for parsing command-line arguments. ```cpp #include int main(int argc, char** argv) { CLI::App app{"Description for your app."}; CLI11_PARSE(app, argc, argv); } ``` -------------------------------- ### Add Library and Link with CLI11 Source: https://github.com/cliutils/cli11/blob/main/tests/CMakeLists.txt Creates a library 'link_test_1' from 'link_test_1.cpp' and links it with CLI11. It also sets the target folder to 'Tests'. ```cmake add_library(link_test_1 link_test_1.cpp) target_link_libraries(link_test_1 PUBLIC CLI11) set_target_properties(link_test_1 PROPERTIES FOLDER "Tests") ``` -------------------------------- ### Allowing Multiple Configuration Files in CLI11 Source: https://github.com/cliutils/cli11/blob/main/README.md Configure CLI11 to accept multiple configuration files by specifying an expected number of arguments for the --config option. ```cpp app.set_config("--config")->expected(1, X); ``` -------------------------------- ### Disable Description and Footer Formatting Source: https://github.com/cliutils/cli11/blob/main/book/chapters/formatting.md Turn off automatic formatting for description and footer paragraphs. This is useful when you need to manually control alignment and width, for example, with pre-formatted text or ASCII art. ```cpp app.get_formatter()->enable_description_formatting(false); app.get_formatter()->enable_footer_formatting(false); ``` -------------------------------- ### Add a Subcommand Source: https://github.com/cliutils/cli11/blob/main/book/chapters/subcommands.md Use this to add a new subcommand to your application. The subcommand name and a description are required. A pointer to the subcommand is returned for further configuration. ```cpp CLI::App* sub = app.add_subcommand("sub", "This is a subcommand"); ``` -------------------------------- ### Transform Validator Example Source: https://github.com/cliutils/cli11/blob/main/book/chapters/validators.md Demonstrates a mutating validator function that modifies the input string and returns an error message or an empty string on success. Throws CLI::ValidationError for specific error conditions. ```cpp auto transform_validator = CLI::Validator( [](std::string &input) { if (input == "error") { return "error is not a valid value"; } else if (input == "unexpected") { throw CLI::ValidationError{"Unexpected error"}; } input = "new string"; return ""; }, "VALIDATOR DESCRIPTION", "Validator name"); cli_global.add_option("option")->transform(transform_validator); ``` -------------------------------- ### Anatomy of a CLI11 Help Message Source: https://github.com/cliutils/cli11/blob/main/book/chapters/formatting.md Illustrates the methods called by CLI11 to construct the help message. Each line or section corresponds to a specific `make_` method. ```text ... ``` -------------------------------- ### CLI11 Parsing Procedure Source: https://github.com/cliutils/cli11/blob/main/book/chapters/internals.md Illustrates the main parsing routine within CLI11's App class. It outlines the sequence of operations, including callback processing, help flag handling, configuration file and environment variable processing, and requirement checks, with specific attention to error handling and priority. ```cpp CLI11_INLINE void App::_process() { // help takes precedence over other potential errors and config and environment shouldn't be processed if help // throws _process_callbacks(CallbackPriority::FirstPreHelp); _process_help_flags(CallbackPriority::First); _process_callbacks(CallbackPriority::First); std::exception_ptr config_exception; try { // the config file might generate a FileError but that should not be processed until later in the process // to allow for help, version and other errors to generate first. _process_config_file(); // process env shouldn't throw but no reason to process it if config generated an error _process_env(); } catch(const CLI::FileError &) { config_exception = std::current_exception(); } // callbacks and requirements processing can generate exceptions which should take priority // over the config file error if one exists. _process_callbacks(CallbackPriority::PreRequirementsCheckPreHelp); _process_help_flags(CallbackPriority::PreRequirementsCheck); _process_callbacks(CallbackPriority::PreRequirementsCheck); _process_requirements(); _process_callbacks(CallbackPriority::NormalPreHelp); _process_help_flags(CallbackPriority::Normal); _process_callbacks(CallbackPriority::Normal); if(config_exception) { std::rethrow_exception(config_exception); } _process_callbacks(CallbackPriority::LastPreHelp); _process_help_flags(CallbackPriority::Last); _process_callbacks(CallbackPriority::Last); } ``` -------------------------------- ### Add Default Path for Config Files Source: https://github.com/cliutils/cli11/blob/main/book/chapters/config.md Allows specified configuration files to be found either at the given path or within a default search path. Multiple default paths can be chained. ```cpp app.set_config("--config")->transform(CLI::FileOnDefaultPath("/default_path/")); ``` ```cpp app.set_config("--config") ->transform(CLI::FileOnDefaultPath("/default_path2/",false)); ``` ```cpp app.set_config("--config") ->transform(CLI::FileOnDefaultPath("/default_path2/") | CLI::FileOnDefaultPath("/default_path/")); ``` -------------------------------- ### Enable Allow Extras Source: https://github.com/cliutils/cli11/blob/main/book/chapters/subcommands.md Configure the application to not throw an error for unmatched command-line arguments. These extra arguments will be stored and accessible via the `.remaining()` method. ```cpp app.allow_extras(); ``` -------------------------------- ### Set System Include Directories Source: https://github.com/cliutils/cli11/blob/main/src/CMakeLists.txt Configures include directories for the CLI11 target. It conditionally marks headers as system headers if CLI11 is included from another project to prevent compiler warnings. It also specifies build and install interface directories. ```cmake if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(SYSTEM_INCL "") else() # If this project is included from somewhere else, we mark our headers as system headers to avoid # the compiler emitting any warnings about them set(SYSTEM_INCL "SYSTEM") endif() # Duplicated because CMake adds the current source dir if you don't. target_include_directories( CLI11 ${SYSTEM_INCL} ${PUBLIC_OR_INTERFACE} $ $) ``` -------------------------------- ### Add Flag with Default Values in CLI11 Source: https://github.com/cliutils/cli11/blob/main/book/chapters/flags.md Specify default values for flags using a special syntax in the option name string. For example, `--flag,!--no-flag` sets `result` to true if `--flag` is present and false if `--no-flag` is present. This syntax also works for short options and can specify numerical or string defaults. ```cpp app.add_flag("--flag,!--no-flag",result,"help for flag"); ``` ```cpp app.add_flag("-1{1},-2{2},-3{3}",result,"numerical flag") ``` -------------------------------- ### Add Executable and Link with CLI11 and Other Libraries Source: https://github.com/cliutils/cli11/blob/main/tests/CMakeLists.txt Creates an executable 'link_test_2' from 'link_test_2.cpp' and links it with CLI11 and the 'link_test_1' library. It also adds a catch test. ```cmake add_executable(link_test_2 link_test_2.cpp) target_link_libraries(link_test_2 PUBLIC CLI11 link_test_1) add_catch_test(link_test_2) ``` -------------------------------- ### Run Local Pre-commit Hooks Source: https://github.com/cliutils/cli11/blob/main/AGENTS.md Execute local pre-commit hooks for code style and linting checks across various file types. ```bash prek -a ``` -------------------------------- ### Set Configuration File Source: https://github.com/cliutils/cli11/blob/main/README.md Configures the application to read options from an INI file. Allows specifying the option name for the config file, a default file name, help string, and whether it's required. ```cpp app.set_config(option_name="", default_file_name="", help_string="Read an ini file", required=false) ``` -------------------------------- ### Use CLI::IsMember with Initializer List Source: https://github.com/cliutils/cli11/blob/main/README.md Select from exact match to choices using an initializer list. ```cpp CLI::IsMember({"choice1", "choice2"}) ``` -------------------------------- ### Create Group for Help Display Source: https://github.com/cliutils/cli11/blob/main/README.md Creates an option group that is treated as if it were not in a group for help display purposes. Options within this group are handled similarly to parent options. ```cpp auto added_group=app.add_option_group("+sub"); ``` -------------------------------- ### Add Options with Various Types Source: https://github.com/cliutils/cli11/blob/main/README.md Demonstrates adding options that bind to different variable types like bool, int, float, vectors, enums, and more. Supports types with string conversion or specific constructors. ```cpp // Add options app.add_option(option_name, help_str="") ``` ```cpp app.add_option(option_name, variable_to_bind_to, // bool, char(see note), int, float, vector, enum, std::atomic, or string-like, or anything with a defined conversion from a string or that takes an int, double, or string in a constructor. Also allowed are tuples, std::array or std::pair. Also supported are complex numbers, wrapper types, and containers besides vectors of any other supported type. help_string="") ``` ```cpp app.add_option_function(option_name, function , // type can be any type supported by add_option help_string="") ``` ```cpp // char as an option type is supported before 2.0 but in 2.0 it defaulted to allowing single non numerical characters in addition to the numeric values. ``` ```cpp // There is a template overload which takes two template parameters the first is the type of object to assign the value to, the second is the conversion type. The conversion type should have a known way to convert from a string, such as any of the types that work in the non-template version. If XC is a std::pair and T is some non pair type. Then a two argument constructor for T is called to assign the value. For tuples or other multi element types, XC must be a single type or a tuple like object of the same size as the assignment type app.add_option(option_name, T &output, // output must be assignable or constructible from a value of type XC help_string="") ``` -------------------------------- ### Add Option with Lambda Callback Source: https://github.com/cliutils/cli11/blob/main/book/chapters/internals.md Demonstrates how to add an option to a CLI11 application using a lambda function to bind a value to a variable. This approach avoids the need for explicit classes or inheritance. ```cpp Option* add_option(string name, T &item) { this->function = [&item](string value){ return lexical_cast(value, item); } } ``` -------------------------------- ### Build and Test Help Message Generation CLI Source: https://github.com/cliutils/cli11/blob/main/examples/CMakeLists.txt Adds a CLI executable 'help_usage' and configures a test to check its help message output. The test passes if the output contains a digit between 1 and 9. ```cmake add_cli_exe(help_usage help_usage.cpp) add_test(NAME help_use COMMAND help_usage --help) set_property(TEST help_use PROPERTY PASS_REGULAR_EXPRESSION "[1..9]") ``` -------------------------------- ### Configure CLI11 with Filesystem for GCC 8 Source: https://github.com/cliutils/cli11/blob/main/book/chapters/installation.md Define CLI11_HAS_FILESYSTEM=1 and link against libstdc++fs when using GCC 8 with C++17 to enable filesystem support. ```bash # Define CLI11_HAS_FILESYSTEM=1 and link with -lstdc++fs ``` -------------------------------- ### Define Book Sources in CMake Source: https://github.com/cliutils/cli11/blob/main/book/CMakeLists.txt Specifies the source files for the book, including README and SUMMARY, using CMake's set command. ```cmake set(book_sources README.md SUMMARY.md) ```