From e29cb3f1b47a973094813ef82c6e2dab84984336 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Wed, 9 Feb 2022 10:12:55 -0800 Subject: [PATCH] feat: support empty vector in TOML (#660) * add tests which suppose to pass * Update ConfigFileTest.cpp * Update ConfigFileTest.cpp * style: pre-commit.ci fixes * add the possibility for an empty vector result if allowed. * style: pre-commit.ci fixes * add empty vector command line tests * update book and readme * add no default test Co-authored-by: puchneiner <90352207+puchneiner@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- README.md | 2 ++ book/chapters/options.md | 32 ++++++++++++++++++++++++++++++++ include/CLI/App.hpp | 3 ++- include/CLI/ConfigFwd.hpp | 3 +++ include/CLI/Option.hpp | 12 +++++++++++- include/CLI/TypeTools.hpp | 15 ++++++++++++++- tests/AppTest.cpp | 29 +++++++++++++++++++++++++++++ tests/ConfigFileTest.cpp | 29 +++++++++++++++++++++++++++-- 8 files changed, 120 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index eb8d4b57..6b45a550 100644 --- a/README.md +++ b/README.md @@ -798,6 +798,8 @@ app.set_config("--config")->expected(1, X); Where X is some positive number and will allow up to `X` configuration files to be specified by separate `--config` arguments. Value strings with quote characters in it will be printed with a single quote. All other arguments will use double quote. Empty strings will use a double quoted argument. Numerical or boolean values are not quoted. +For options or flags which allow 0 arguments to be passed using an empty string in the config file, `{}`, or `[]` will convert the result to the default value specified via `default_str` or `default_val` on the option 🚧. If no user specified default is given the result is an empty string or the converted value of an empty string. + NOTE: Transforms and checks can be used with the option pointer returned from set_config like any other option to validate the input if needed. It can also be used with the built in transform `CLI::FileOnDefaultPath` to look in a default path as well as the current one. For example ```cpp diff --git a/book/chapters/options.md b/book/chapters/options.md index f41ac780..a71ad428 100644 --- a/book/chapters/options.md +++ b/book/chapters/options.md @@ -72,6 +72,38 @@ Vectors will be replaced by the parsed content if the option is given on the com A definition of a container for purposes of CLI11 is a type with a `end()`, `insert(...)`, `clear()` and `value_type` definitions. This includes `vector`, `set`, `deque`, `list`, `forward_iist`, `map`, `unordered_map` and a few others from the standard library, and many other containers from the boost library. +### Empty containers + +By default a container will never return an empty container. If it is desired to allow an empty container to be returned, then the option must be modified with a 0 as the minimum expected value + +```cpp +std::vector int_vec; +app.add_option("--vec", int_vec, "Empty vector allowed")->expected(0,-1); +``` + +An empty vector can than be specified on the command line as `--vec {}` + +To allow an empty vector from config file, the default must be set in addition to the above modification. + +```cpp +std::vector int_vec; +app.add_option("--vec", int_vec, "Empty vector allowed")->expected(0,-1)->default_str("{}"); +``` + +Then in the file + +```toml +vec={} +``` + +or + +```toml +vec=[] +``` + +will generate an empty vector in `int_vec`. + ### Containers of containers Containers of containers are also supported. diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index 520bfb55..67ed685b 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -2451,8 +2451,9 @@ class App { } if(op->empty()) { - // Flag parsing + if(op->get_expected_min() == 0) { + // Flag parsing auto res = config_formatter_->to_flag(item); res = op->get_flag_value(item.name, res); diff --git a/include/CLI/ConfigFwd.hpp b/include/CLI/ConfigFwd.hpp index ef2ac345..94aa260c 100644 --- a/include/CLI/ConfigFwd.hpp +++ b/include/CLI/ConfigFwd.hpp @@ -58,6 +58,9 @@ class Config { if(item.inputs.size() == 1) { return item.inputs.at(0); } + if(item.inputs.empty()) { + return "{}"; + } throw ConversionError::TooManyInputsFlag(item.fullname()); } diff --git a/include/CLI/Option.hpp b/include/CLI/Option.hpp index 25a67605..c78fc057 100644 --- a/include/CLI/Option.hpp +++ b/include/CLI/Option.hpp @@ -1162,7 +1162,7 @@ class Option : public OptionBase