diff --git a/README.md b/README.md index 87f9d613..d2fd20ee 100644 --- a/README.md +++ b/README.md @@ -482,7 +482,8 @@ Before parsing, you can set the following options: - `->configurable(false)`: Disable this option from being in a configuration file. - `->capture_default_str()`: Store the current value attached and display it in - the help string. + the help string. This should work with almost any type that `add_option` can + accept. - `->default_function(std::string())`: Advanced: Change the function that `capture_default_str()` uses. - `->always_capture_default()`: Always run `capture_default_str()` when creating @@ -897,7 +898,11 @@ not used in performance critical code: variable. - `Value=opt->as()`: Returns the result or default value directly as the specified type if possible, can be vector to return all results, and a - non-vector to get the result according to the MultiOptionPolicy in place. + non-vector to get the result according to the MultiOptionPolicy in place. If + it is expected that the results will be needed as a vector, it is suggested + that `->expected(CLI::details::expected_max_vector_size)` or + `allow_extra_args()` be used on the option to inform CLI11 that vector args + are expected and allowed. ### Subcommands diff --git a/book/chapters/config.md b/book/chapters/config.md index d75d5fe8..d1559360 100644 --- a/book/chapters/config.md +++ b/book/chapters/config.md @@ -222,10 +222,25 @@ characters. Characters not in this form will be translated as given. If argument values with unprintable characters are used to generate a config file this binary form will be used in the output string. +### multiline vector + +Vector arguments can also be multiline + +```toml +#multiline vector format +vector = [ + 2, + 3, + 4, + 5, + 6 +] +``` + ### vector of vector inputs It is possible to specify vector of vector inputs in config file. This can be -done in a couple different ways +done in a few different ways ```toml # Examples of vector of vector inputs in config @@ -240,6 +255,7 @@ vector2 = [1,2,3,"%%",4,5,6] vector3 = [1,2,3] vector3 = [4,5,6] + ``` The `%%` is ignored in multiline format if the inject_separator modifier on the @@ -348,7 +364,7 @@ bool commentDefaultsBool = false; /// specify the config reader should collapse repeated field names to a single vector bool allowMultipleDuplicateFields{false}; /// Specify the configuration index to use for arrayed sections -uint16_t configIndex{0}; +uint16_t configIndex{-1}; /// Specify the configuration section that should be used std::string configSection; ``` diff --git a/book/chapters/internals.md b/book/chapters/internals.md index c2c98b75..cdfe8eaa 100644 --- a/book/chapters/internals.md +++ b/book/chapters/internals.md @@ -37,18 +37,59 @@ The parsing phase is the most interesting: didn't fit in the parse. 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. +completes all subcommands before moving to the next step. This ensures that +interactions between options and subcommand options is consistent. -1. `_process_ini`: This reads an INI file and fills/changes options as needed. -2. `_process_env`: Look for environment variables. -3. `_process_callbacks`: Run the callback functions - this fills out the - variables. -4. `_process_help_flags`: Run help flags if present (and quit). -5. `_process_requirements`: Make sure needs/excludes, required number of options - present. +```c++ +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); +} + +``` + +Option callbacks can be executed at many different stages depending on the +priority specified. The default is `Normal` so they will execute after +processing requirements. The default for help and version flags is to execute +`First`. Both can be changed to execute in different steps of the process. ## Exceptions The library immediately returns a C++ exception when it detects a problem, such -as an incorrect construction or a malformed command line. +as an incorrect construction or a malformed command line. Errors from config +processing are delayed until after other processing, to give priority to any +help or version flags, or other types of callback errors. diff --git a/book/chapters/options.md b/book/chapters/options.md index 67fb9e55..b953e9f3 100644 --- a/book/chapters/options.md +++ b/book/chapters/options.md @@ -372,7 +372,8 @@ constructed it sets a type_size min and max of 1. Meaning that the assignment uses a single string. The Expected size is also set to 1 by default, and `allow_extra_args` is set to false. meaning that each time this option is called 1 argument is expected. This would also be the case if val were a `double`, -`int` or any other single argument types. +`int` or any other single argument types. The modifier `allow_extra_args` should +be set to true if the option output will ever be needed as a vector. now for example @@ -463,6 +464,34 @@ specific cases: the argument is passed. The value is reset if the option is supplied multiple times. +- `->callback_priority(CallbackPriority priority)`: changes the order in which + the option callback is executed. Four principal callback call-points are + available. `CallbackPriority::First` executes at the very beginning of + processing, before configuration files are read and environment variables are + interpreted. `CallbackPriority::PreRequirementsCheck` executes after + configuration and environment processing but before requirements checking. + `CallbackPriority::Normal` executes after the requirements check but before + any previously potentially raised exceptions are re-thrown. + `CallbackPriority::Last` executes after exception handling is completed. For + each position, both ordinary option callbacks and help callbacks are invoked. + The relative order between them can be controlled using the corresponding + `PreHelp` variants. `CallbackPriority::FirstPreHelp` executes ordinary option + callbacks before help callbacks at the very beginning of processing. + `CallbackPriority::PreRequirementsCheckPreHelp` executes ordinary option + callbacks before help callbacks after configuration and environment processing + but before requirements checking. `CallbackPriority::NormalPreHelp` executes + ordinary option callbacks before help callbacks after the requirements check + but before exception re-throwing. `CallbackPriority::LastPreHelp` executes + ordinary option callbacks before help callbacks after exception handling has + completed. When using the standard priorities (`CallbackPriority::First`, + `CallbackPriority::PreRequirementsCheck`, `CallbackPriority::Normal`, + `CallbackPriority::Last`), help callbacks are executed before ordinary option + callbacks. By default, help callbacks use `CallbackPriority::First`, and + ordinary option callbacks use `CallbackPriority::Normal`. This mechanism + provides fine-grained control over when option values are set and when help or + requirement checks occur, enabling precise customization of the processing + sequence. + ## Unusual circumstances There are a few cases where some things break down in the type system managing diff --git a/book/chapters/validators.md b/book/chapters/validators.md index ccda46b2..c4e08b7e 100644 --- a/book/chapters/validators.md +++ b/book/chapters/validators.md @@ -120,6 +120,12 @@ compilation time is a concern they can be disabled. Some additional validators can be enabled by using CLI11_ENABLE_EXTRA_VALIDATORS to 1. These validators are disabled by default. +| Validator | Description | +| ------------------ | ----------------------------------------------------------- | +| `ReadPermissions` | Ensure a file or directory has permissions to read the file | +| `WritePermissions` | Ensure a file or directory has write permissions | +| `ExecPermissions` | Ensure a file has exec permissions | + ## Custom Validators CLI11 also supports the use of custom validators, this includes using the diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 23cde591..6e05183e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,7 +4,7 @@ if(CLI11_SANITIZERS AND ${CMAKE_VERSION} VERSION_GREATER "3.15") sanitizers GIT_REPOSITORY https://github.com/arsenm/sanitizers-cmake.git GIT_SHALLOW 1 - GIT_TAG 0573e2e) + GIT_TAG bcb1fc6) FetchContent_MakeAvailable(sanitizers)