mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-01-15 22:58:02 +00:00
Compare commits
2 Commits
ba68040e92
...
967bfe0e02
Author | SHA1 | Date | |
---|---|---|---|
|
967bfe0e02 | ||
|
d8a5bdc294 |
@ -75,7 +75,7 @@ SortIncludes: true
|
||||
# SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: Never
|
||||
# SpaceInEmptyParentheses: false
|
||||
# SpacesBeforeTrailingComments: 1
|
||||
SpacesBeforeTrailingComments: 2
|
||||
# SpacesInAngles: false
|
||||
# SpacesInContainerLiterals: true
|
||||
# SpacesInCStyleCastParentheses: false
|
||||
|
@ -1,7 +1,7 @@
|
||||
set noparent
|
||||
linelength=120 # As in .clang-format
|
||||
|
||||
# Non-used filters
|
||||
# Unused filters
|
||||
filter=-build/include_order # Requires unusual include order that encourages creating not self-contained headers
|
||||
filter=-readability/nolint # Conflicts with clang-tidy
|
||||
filter=-runtime/references # Requires fundamental change of API, don't see need for this
|
||||
@ -9,6 +9,3 @@ filter=-whitespace/blank_line # Unnecessarily strict with blank lines that othe
|
||||
filter=-whitespace/indent # Requires strange 3-space indent of private/protected/public markers
|
||||
filter=-whitespace/parens,-whitespace/braces # Conflict with clang-format
|
||||
|
||||
# Filters to be included in future
|
||||
filter=-whitespace/comments
|
||||
|
||||
|
36
README.md
36
README.md
@ -679,8 +679,23 @@ app.set_config(option_name="",
|
||||
required=false)
|
||||
```
|
||||
|
||||
If this is called with no arguments, it will remove the configuration file option (like `set_help_flag`). Setting a configuration option is special. If it is present, it will be read along with the normal command line arguments. The file will be read if it exists, and does not throw an error unless `required` is `true`. Configuration files are in `ini` format by default, The reader can also accept many files in [TOML] format 🆕. (other formats can be added by an adept user, some variations are available through customization points in the default formatter). An example of a file:
|
||||
If this is called with no arguments, it will remove the configuration file option (like `set_help_flag`). Setting a configuration option is special. If it is present, it will be read along with the normal command line arguments. The file will be read if it exists, and does not throw an error unless `required` is `true`. Configuration files are in [TOML] format by default 🚧, though the default reader can also accept files in INI format as well 🆕. It should be noted that CLI11 does not contain a full TOML parser but can read strings from most TOML file and run them through the CLI11 parser. Other formats can be added by an adept user, some variations are available through customization points in the default formatter. An example of a TOML file 🆕:
|
||||
|
||||
```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
|
||||
```
|
||||
or equivalently in INI format
|
||||
```ini
|
||||
; Comments are supported, using a ;
|
||||
; The default section is [default], case insensitive
|
||||
@ -695,23 +710,8 @@ str_vector = "one" "two" "and three"
|
||||
in_subcommand = Wow
|
||||
sub.subcommand = true
|
||||
```
|
||||
or equivalently in TOML 🆕
|
||||
```toml
|
||||
# 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
|
||||
```
|
||||
|
||||
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`, `enable`; or `false`, `off`, `0`, `no`, `disable` (case insensitive). Sections (and `.` separated names) are treated as subcommands (note: this does not necessarily mean that subcommand was passed, it just sets the "defaults"). You cannot set positional-only arguments. 🆕 Subcommands can be triggered from config files if the `configurable` flag was set on the subcommand. Then use `[subcommand]` notation will trigger a subcommand and cause it to act as if it were on the command line.
|
||||
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`, `enable`; or `false`, `off`, `0`, `no`, `disable` (case insensitive). Sections (and `.` separated names) are treated as subcommands (note: this does not necessarily mean that subcommand was passed, it just sets the "defaults"). You cannot set positional-only arguments. 🆕 Subcommands can be triggered from configuration files if the `configurable` flag was set on the subcommand. Then the use of `[subcommand]` notation will trigger a subcommand and cause it to act as if it were on the command line.
|
||||
|
||||
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. See [Config files](https://cliutils.github.io/CLI11/book/chapters/config.html) for some additional details.
|
||||
@ -744,7 +744,7 @@ The App class was designed allow toolkits to subclass it, to provide preset defa
|
||||
but before run behavior, while
|
||||
still giving the user freedom to `callback` on the main app.
|
||||
|
||||
The most important parse function is `parse(std::vector<std::string>)`, which takes a reversed list of arguments (so that `pop_back` processes the args in the correct order). `get_help_ptr` and `get_config_ptr` give you access to the help/config option pointers. The standard `parse` manually sets the name from the first argument, so it should not be in this vector. You can also use `parse(string, bool)` to split up and parse a string; the optional bool should be set to true if you are
|
||||
The most important parse function is `parse(std::vector<std::string>)`, which takes a reversed list of arguments (so that `pop_back` processes the args in the correct order). `get_help_ptr` and `get_config_ptr` give you access to the help/config option pointers. The standard `parse` manually sets the name from the first argument, so it should not be in this vector. You can also use `parse(string, bool)` to split up and parse a string; the optional boolean should be set to true if you are
|
||||
including the program name in the string, and false otherwise.
|
||||
|
||||
Also, in a related note, the `App` you get a pointer to is stored in the parent `App` in a `shared_ptr`s (similar to `Option`s) and are deleted when the main `App` goes out of scope unless the object has another owner.
|
||||
|
@ -41,7 +41,26 @@ If it is needed to get the configuration file name used this can be obtained via
|
||||
|
||||
## Configure file format
|
||||
|
||||
Here is an example configuration file, in INI format:
|
||||
Here is an example configuration file, in [TOML](https://github.com/toml-lang/toml) format:
|
||||
|
||||
```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
|
||||
[subcommand.sub]
|
||||
subcommand = true # could also be give as sub.subcommand=true
|
||||
```
|
||||
|
||||
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`, `y`, `t`, `+`, `yes`, `enable`; or `false`, `off`, `0`, `no`, `n`, `f`, `-`, `disable`, (case insensitive). Sections (and `.` separated names) are treated as subcommands (note: this does not necessarily mean that subcommand was passed, it just sets the "defaults". If a subcommand is set to `configurable` then passing the subcommand using `[sub]` in a configuration file will trigger the subcommand.)
|
||||
|
||||
CLI11 also supports configuration file in INI format.
|
||||
|
||||
```ini
|
||||
; Comments are supported, using a ;
|
||||
@ -57,25 +76,6 @@ in_subcommand = Wow
|
||||
sub.subcommand = true
|
||||
```
|
||||
|
||||
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`, `y`, `t`, `+`, `yes`, `enable`; or `false`, `off`, `0`, `no`, `n`, `f`, `-`, `disable`, (case insensitive). Sections (and `.` separated names) are treated as subcommands (note: this does not necessarily mean that subcommand was passed, it just sets the "defaults". If a subcommand is set to `configurable` then passing the subcommand using `[sub]` in a configuration file will trigger the subcommand.)
|
||||
|
||||
CLI11 also supports configuration file in [TOML](https://github.com/toml-lang/toml) format.
|
||||
|
||||
```toml
|
||||
# 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
|
||||
[subcommand.sub]
|
||||
subcommand = true # could also be give as sub.subcommand=true
|
||||
```
|
||||
|
||||
The main differences are in vector notation and comment character. Note: CLI11 is not a full TOML parser as it just reads values as strings. It is possible (but not recommended) to mix notation.
|
||||
|
||||
## Writing out a configure file
|
||||
@ -83,16 +83,16 @@ The main differences are in vector notation and comment character. Note: CLI11
|
||||
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.
|
||||
|
||||
### Customization of configure file output
|
||||
The default config parser/generator has some customization points that allow variations on the INI format. The default formatter has a base configuration that matches the INI format. It defines 5 characters that define how different aspects of the configuration are handled
|
||||
The default config parser/generator has some customization points that allow variations on the TOML format. The default formatter has a base configuration that matches the TOML format. It defines 5 characters that define how different aspects of the configuration are handled
|
||||
```cpp
|
||||
/// the character used for comments
|
||||
char commentChar = ';';
|
||||
char commentChar = '#';
|
||||
/// the character used to start an array '\0' is a default to not use
|
||||
char arrayStart = '\0';
|
||||
char arrayStart = '[';
|
||||
/// the character used to end an array '\0' is a default to not use
|
||||
char arrayEnd = '\0';
|
||||
char arrayEnd = ']';
|
||||
/// the character used to separate elements in an array
|
||||
char arraySeparator = ' ';
|
||||
char arraySeparator = ',';
|
||||
/// the character used separate the name from the value
|
||||
char valueDelimiter = '=';
|
||||
```
|
||||
@ -111,11 +111,11 @@ auto config_base=app.get_config_formatter_base();
|
||||
config_base->valueSeparator(':');
|
||||
```
|
||||
|
||||
The default configuration file will read TOML files, but will write out files in the INI format. To specify outputting TOML formatted files use
|
||||
The default configuration file will read INI files, but will write out files in the TOML format. To specify outputting INI formatted files use
|
||||
```cpp
|
||||
app.config_formatter(std::make_shared<CLI::ConfigTOML>());
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
```
|
||||
which makes use of a predefined modification of the ConfigBase class which INI also uses.
|
||||
which makes use of a predefined modification of the ConfigBase class which TOML also uses.
|
||||
|
||||
## Custom formats
|
||||
|
||||
|
@ -20,7 +20,7 @@ int main(int argc, char **argv) {
|
||||
int count{0};
|
||||
CLI::Option *copt = app.add_flag("-c,--count", count, "Counter")->required()->group("Important");
|
||||
|
||||
double value{0.0}; // = 3.14;
|
||||
double value{0.0}; // = 3.14;
|
||||
app.add_option("-d,--double", value, "Some Value")->group("Other");
|
||||
|
||||
try {
|
||||
|
@ -14,7 +14,7 @@ int main(int argc, char **argv) {
|
||||
app.add_flag("--version", "Get version");
|
||||
|
||||
CLI::App *cameraApp = app.add_subcommand("camera", "Configure the app camera");
|
||||
cameraApp->require_subcommand(0, 1); // 0 (default) or 1 camera
|
||||
cameraApp->require_subcommand(0, 1); // 0 (default) or 1 camera
|
||||
|
||||
std::string mvcamera_config_file = "mvcamera_config.json";
|
||||
CLI::App *mvcameraApp = cameraApp->add_subcommand("mvcamera", "MatrixVision Camera Configuration");
|
||||
|
@ -21,7 +21,7 @@ int main(int argc, char **argv) {
|
||||
int v{0};
|
||||
CLI::Option *flag = app.add_flag("--flag", v, "Some flag that can be passed multiple times");
|
||||
|
||||
double value{0.0}; // = 3.14;
|
||||
double value{0.0}; // = 3.14;
|
||||
app.add_option("-d,--double", value, "Some Value");
|
||||
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
@ -23,7 +23,7 @@ int main(int argc, char **argv) {
|
||||
CLI::Option *copt = impOpt->add_flag("-c,--count", count, "Counter")->required();
|
||||
|
||||
CLI::App_p otherOpt = std::make_shared<CLI::App>("Other");
|
||||
double value{0.0}; // = 3.14;
|
||||
double value{0.0}; // = 3.14;
|
||||
otherOpt->add_option("-d,--double", value, "Some Value");
|
||||
|
||||
// add the subapps to the main one
|
||||
|
@ -15,7 +15,7 @@ int main(int argc, char **argv) {
|
||||
app.add_flag("--random", "Some random flag");
|
||||
CLI::App *start = app.add_subcommand("start", "A great subcommand");
|
||||
CLI::App *stop = app.add_subcommand("stop", "Do you really want to stop?");
|
||||
app.require_subcommand(); // 1 or more
|
||||
app.require_subcommand(); // 1 or more
|
||||
|
||||
std::string file;
|
||||
start->add_option("-f,--file", file, "File name");
|
||||
|
@ -43,12 +43,12 @@ namespace CLI {
|
||||
namespace detail {
|
||||
enum class Classifier { NONE, POSITIONAL_MARK, SHORT, LONG, WINDOWS, SUBCOMMAND, SUBCOMMAND_TERMINATOR };
|
||||
struct AppFriend;
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
namespace FailureMessage {
|
||||
std::string simple(const App *app, const Error &e);
|
||||
std::string help(const App *app, const Error &e);
|
||||
} // namespace FailureMessage
|
||||
} // namespace FailureMessage
|
||||
|
||||
/// enumeration of modes of how to deal with extras in config files
|
||||
|
||||
@ -247,7 +247,7 @@ class App {
|
||||
Option *config_ptr_{nullptr};
|
||||
|
||||
/// This is the formatter for help printing. Default provided. INHERITABLE (same pointer)
|
||||
std::shared_ptr<Config> config_formatter_{new ConfigINI()};
|
||||
std::shared_ptr<Config> config_formatter_{new ConfigTOML()};
|
||||
|
||||
///@}
|
||||
|
||||
@ -464,7 +464,7 @@ class App {
|
||||
auto *p = (parent_ != nullptr) ? _get_fallthrough_parent() : this;
|
||||
auto &match = _compare_subcommand_names(*this, *p);
|
||||
if(!match.empty()) {
|
||||
ignore_case_ = false; // we are throwing so need to be exception invariant
|
||||
ignore_case_ = false; // we are throwing so need to be exception invariant
|
||||
throw OptionAlreadyAdded("ignore case would cause subcommand name conflicts: " + match);
|
||||
}
|
||||
}
|
||||
@ -586,7 +586,7 @@ class App {
|
||||
}
|
||||
}
|
||||
// this line should not be reached the above loop should trigger the throw
|
||||
throw(OptionAlreadyAdded("added option matched existing option name")); // LCOV_EXCL_LINE
|
||||
throw(OptionAlreadyAdded("added option matched existing option name")); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
/// Add option for assigning to a variable
|
||||
@ -594,11 +594,11 @@ class App {
|
||||
typename ConvertTo = AssignTo,
|
||||
enable_if_t<!std::is_const<ConvertTo>::value, detail::enabler> = detail::dummy>
|
||||
Option *add_option(std::string option_name,
|
||||
AssignTo &variable, ///< The variable to set
|
||||
AssignTo &variable, ///< The variable to set
|
||||
std::string option_description = "",
|
||||
bool defaulted = false) {
|
||||
|
||||
auto fun = [&variable](const CLI::results_t &res) { // comment for spacing
|
||||
auto fun = [&variable](const CLI::results_t &res) { // comment for spacing
|
||||
return detail::lexical_conversion<AssignTo, ConvertTo>(res, variable);
|
||||
};
|
||||
|
||||
@ -619,7 +619,7 @@ class App {
|
||||
/// Add option for a callback of a specific type
|
||||
template <typename T>
|
||||
Option *add_option_function(std::string option_name,
|
||||
const std::function<void(const T &)> &func, ///< the callback to execute
|
||||
const std::function<void(const T &)> &func, ///< the callback to execute
|
||||
std::string option_description = "") {
|
||||
|
||||
auto fun = [func](const CLI::results_t &res) {
|
||||
@ -731,7 +731,7 @@ class App {
|
||||
template <typename T,
|
||||
enable_if_t<std::is_integral<T>::value && !is_bool<T>::value, detail::enabler> = detail::dummy>
|
||||
Option *add_flag(std::string flag_name,
|
||||
T &flag_count, ///< A variable holding the count
|
||||
T &flag_count, ///< A variable holding the count
|
||||
std::string flag_description = "") {
|
||||
flag_count = 0;
|
||||
CLI::callback_t fun = [&flag_count](const CLI::results_t &res) {
|
||||
@ -754,7 +754,7 @@ class App {
|
||||
!std::is_constructible<std::function<void(int)>, T>::value,
|
||||
detail::enabler> = detail::dummy>
|
||||
Option *add_flag(std::string flag_name,
|
||||
T &flag_result, ///< A variable holding true if passed
|
||||
T &flag_result, ///< A variable holding true if passed
|
||||
std::string flag_description = "") {
|
||||
|
||||
CLI::callback_t fun = [&flag_result](const CLI::results_t &res) {
|
||||
@ -768,7 +768,7 @@ class App {
|
||||
typename T,
|
||||
enable_if_t<!std::is_assignable<std::function<void(std::int64_t)>, T>::value, detail::enabler> = detail::dummy>
|
||||
Option *add_flag(std::string flag_name,
|
||||
std::vector<T> &flag_results, ///< A vector of values with the flag results
|
||||
std::vector<T> &flag_results, ///< A vector of values with the flag results
|
||||
std::string flag_description = "") {
|
||||
CLI::callback_t fun = [&flag_results](const CLI::results_t &res) {
|
||||
bool retval = true;
|
||||
@ -785,7 +785,7 @@ class App {
|
||||
|
||||
/// Add option for callback that is triggered with a true flag and takes no arguments
|
||||
Option *add_flag_callback(std::string flag_name,
|
||||
std::function<void(void)> function, ///< A function to call, void(void)
|
||||
std::function<void(void)> function, ///< A function to call, void(void)
|
||||
std::string flag_description = "") {
|
||||
|
||||
CLI::callback_t fun = [function](const CLI::results_t &res) {
|
||||
@ -801,7 +801,7 @@ class App {
|
||||
|
||||
/// Add option for callback with an integer value
|
||||
Option *add_flag_function(std::string flag_name,
|
||||
std::function<void(std::int64_t)> function, ///< A function to call, void(int)
|
||||
std::function<void(std::int64_t)> function, ///< A function to call, void(int)
|
||||
std::string flag_description = "") {
|
||||
|
||||
CLI::callback_t fun = [function](const CLI::results_t &res) {
|
||||
@ -817,7 +817,7 @@ class App {
|
||||
#ifdef CLI11_CPP14
|
||||
/// Add option for callback (C++14 or better only)
|
||||
Option *add_flag(std::string flag_name,
|
||||
std::function<void(std::int64_t)> function, ///< A function to call, void(std::int64_t)
|
||||
std::function<void(std::int64_t)> function, ///< A function to call, void(std::int64_t)
|
||||
std::string flag_description = "") {
|
||||
return add_flag_function(std::move(flag_name), std::move(function), std::move(flag_description));
|
||||
}
|
||||
@ -826,8 +826,8 @@ class App {
|
||||
/// Add set of options (No default, temp reference, such as an inline set) DEPRECATED
|
||||
template <typename T>
|
||||
Option *add_set(std::string option_name,
|
||||
T &member, ///< The selected member of the set
|
||||
std::set<T> options, ///< The set of possibilities
|
||||
T &member, ///< The selected member of the set
|
||||
std::set<T> options, ///< The set of possibilities
|
||||
std::string option_description = "") {
|
||||
|
||||
Option *opt = add_option(option_name, member, std::move(option_description));
|
||||
@ -838,8 +838,8 @@ class App {
|
||||
/// Add set of options (No default, set can be changed afterwards - do not destroy the set) DEPRECATED
|
||||
template <typename T>
|
||||
Option *add_mutable_set(std::string option_name,
|
||||
T &member, ///< The selected member of the set
|
||||
const std::set<T> &options, ///< The set of possibilities
|
||||
T &member, ///< The selected member of the set
|
||||
const std::set<T> &options, ///< The set of possibilities
|
||||
std::string option_description = "") {
|
||||
|
||||
Option *opt = add_option(option_name, member, std::move(option_description));
|
||||
@ -850,8 +850,8 @@ class App {
|
||||
/// Add set of options (with default, static set, such as an inline set) DEPRECATED
|
||||
template <typename T>
|
||||
Option *add_set(std::string option_name,
|
||||
T &member, ///< The selected member of the set
|
||||
std::set<T> options, ///< The set of possibilities
|
||||
T &member, ///< The selected member of the set
|
||||
std::set<T> options, ///< The set of possibilities
|
||||
std::string option_description,
|
||||
bool defaulted) {
|
||||
|
||||
@ -863,8 +863,8 @@ class App {
|
||||
/// Add set of options (with default, set can be changed afterwards - do not destroy the set) DEPRECATED
|
||||
template <typename T>
|
||||
Option *add_mutable_set(std::string option_name,
|
||||
T &member, ///< The selected member of the set
|
||||
const std::set<T> &options, ///< The set of possibilities
|
||||
T &member, ///< The selected member of the set
|
||||
const std::set<T> &options, ///< The set of possibilities
|
||||
std::string option_description,
|
||||
bool defaulted) {
|
||||
|
||||
@ -932,7 +932,7 @@ class App {
|
||||
// Remove existing config if present
|
||||
if(config_ptr_ != nullptr) {
|
||||
remove_option(config_ptr_);
|
||||
config_ptr_ = nullptr; // need to remove the config_ptr completely
|
||||
config_ptr_ = nullptr; // need to remove the config_ptr completely
|
||||
}
|
||||
|
||||
// Only add config if option passed
|
||||
@ -1107,7 +1107,7 @@ class App {
|
||||
for(auto &sub : subcommands_) {
|
||||
cnt += sub->count_all();
|
||||
}
|
||||
if(!get_name().empty()) { // for named subcommands add the number of times the subcommand was called
|
||||
if(!get_name().empty()) { // for named subcommands add the number of times the subcommand was called
|
||||
cnt += parsed_;
|
||||
}
|
||||
return cnt;
|
||||
@ -1881,7 +1881,7 @@ class App {
|
||||
app->name_.clear();
|
||||
}
|
||||
if(app->name_.empty()) {
|
||||
app->fallthrough_ = false; // make sure fallthrough_ is false to prevent infinite loop
|
||||
app->fallthrough_ = false; // make sure fallthrough_ is false to prevent infinite loop
|
||||
app->prefix_command_ = false;
|
||||
}
|
||||
// make sure the parent is set to be this object in preparation for parse
|
||||
@ -2657,14 +2657,14 @@ class App {
|
||||
int max_num = op->get_items_expected_max();
|
||||
|
||||
// Make sure we always eat the minimum for unlimited vectors
|
||||
int collected = 0; // total number of arguments collected
|
||||
int result_count = 0; // local variable for number of results in a single arg string
|
||||
int collected = 0; // total number of arguments collected
|
||||
int result_count = 0; // local variable for number of results in a single arg string
|
||||
// deal with purely flag like things
|
||||
if(max_num == 0) {
|
||||
auto res = op->get_flag_value(arg_name, value);
|
||||
op->add_result(res);
|
||||
parse_order_.push_back(op.get());
|
||||
} else if(!value.empty()) { // --this=value
|
||||
} else if(!value.empty()) { // --this=value
|
||||
op->add_result(value, result_count);
|
||||
parse_order_.push_back(op.get());
|
||||
collected += result_count;
|
||||
@ -2685,11 +2685,11 @@ class App {
|
||||
collected += result_count;
|
||||
}
|
||||
|
||||
if(min_num > collected) { // if we have run out of arguments and the minimum was not met
|
||||
if(min_num > collected) { // if we have run out of arguments and the minimum was not met
|
||||
throw ArgumentMismatch::TypedAtLeast(op->get_name(), min_num, op->get_type_name());
|
||||
}
|
||||
|
||||
if(max_num > collected || op->get_allow_extra_args()) { // we allow optional arguments
|
||||
if(max_num > collected || op->get_allow_extra_args()) { // we allow optional arguments
|
||||
auto remreqpos = _count_remaining_positionals(true);
|
||||
// we have met the minimum now optionally check up to the maximum
|
||||
while((collected < max_num || op->get_allow_extra_args()) && !args.empty() &&
|
||||
@ -2866,7 +2866,7 @@ class App {
|
||||
throw OptionNotFound("could not locate the given Option");
|
||||
}
|
||||
}
|
||||
}; // namespace CLI
|
||||
}; // namespace CLI
|
||||
|
||||
/// Extension of App to better manage groups of options
|
||||
class Option_group : public App {
|
||||
@ -3050,7 +3050,7 @@ inline std::string help(const App *app, const Error &e) {
|
||||
return header;
|
||||
}
|
||||
|
||||
} // namespace FailureMessage
|
||||
} // namespace FailureMessage
|
||||
|
||||
namespace detail {
|
||||
/// This class is simply to allow tests access to App's protected functions
|
||||
@ -3072,6 +3072,6 @@ struct AppFriend {
|
||||
/// Wrap the fallthrough parent function to make sure that is working correctly
|
||||
static App *get_fallthrough_parent(App *app) { return app->_get_fallthrough_parent(); }
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
} // namespace CLI
|
||||
} // namespace CLI
|
||||
|
@ -160,17 +160,18 @@ inline void checkParentSegments(std::vector<ConfigItem> &output, const std::stri
|
||||
output.back().parents = std::move(parents);
|
||||
output.back().name = "++";
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) const {
|
||||
std::string line;
|
||||
std::string section = "default";
|
||||
|
||||
std::vector<ConfigItem> output;
|
||||
bool defaultArray = (arrayStart == '\0' || arrayStart == ' ') && arrayStart == arrayEnd;
|
||||
char aStart = (defaultArray) ? '[' : arrayStart;
|
||||
char aEnd = (defaultArray) ? ']' : arrayEnd;
|
||||
char aSep = (defaultArray && arraySeparator == ' ') ? ',' : arraySeparator;
|
||||
bool isDefaultArray = (arrayStart == '[' && arrayEnd == ']' && arraySeparator == ',');
|
||||
bool isINIArray = (arrayStart == '\0' || arrayStart == ' ') && arrayStart == arrayEnd;
|
||||
char aStart = (isINIArray) ? '[' : arrayStart;
|
||||
char aEnd = (isINIArray) ? ']' : arrayEnd;
|
||||
char aSep = (isINIArray && arraySeparator == ' ') ? ',' : arraySeparator;
|
||||
|
||||
while(getline(input, line)) {
|
||||
std::vector<std::string> items_buffer;
|
||||
@ -212,9 +213,9 @@ inline std::vector<ConfigItem> ConfigBase::from_config(std::istream &input) cons
|
||||
std::string item = detail::trim_copy(line.substr(pos + 1));
|
||||
if(item.size() > 1 && item.front() == aStart && item.back() == aEnd) {
|
||||
items_buffer = detail::split_up(item.substr(1, item.length() - 2), aSep);
|
||||
} else if(defaultArray && item.find_first_of(aSep) != std::string::npos) {
|
||||
} else if((isDefaultArray || isINIArray) && item.find_first_of(aSep) != std::string::npos) {
|
||||
items_buffer = detail::split_up(item, aSep);
|
||||
} else if(defaultArray && item.find_first_of(' ') != std::string::npos) {
|
||||
} else if((isDefaultArray || isINIArray) && item.find_first_of(' ') != std::string::npos) {
|
||||
items_buffer = detail::split_up(item);
|
||||
} else {
|
||||
items_buffer = {item};
|
||||
@ -343,4 +344,4 @@ ConfigBase::to_config(const App *app, bool default_also, bool write_description,
|
||||
return out.str();
|
||||
}
|
||||
|
||||
} // namespace CLI
|
||||
} // namespace CLI
|
||||
|
@ -71,17 +71,17 @@ class Config {
|
||||
virtual ~Config() = default;
|
||||
};
|
||||
|
||||
/// This converter works with INI/TOML files; to write proper TOML files use ConfigTOML
|
||||
/// This converter works with INI/TOML files; to write INI files use ConfigINI
|
||||
class ConfigBase : public Config {
|
||||
protected:
|
||||
/// the character used for comments
|
||||
char commentChar = ';';
|
||||
char commentChar = '#';
|
||||
/// the character used to start an array '\0' is a default to not use
|
||||
char arrayStart = '\0';
|
||||
char arrayStart = '[';
|
||||
/// the character used to end an array '\0' is a default to not use
|
||||
char arrayEnd = '\0';
|
||||
char arrayEnd = ']';
|
||||
/// the character used to separate elements in an array
|
||||
char arraySeparator = ' ';
|
||||
char arraySeparator = ',';
|
||||
/// the character used separate the name from the value
|
||||
char valueDelimiter = '=';
|
||||
|
||||
@ -113,19 +113,19 @@ class ConfigBase : public Config {
|
||||
}
|
||||
};
|
||||
|
||||
/// the default Config is the INI file format
|
||||
using ConfigINI = ConfigBase;
|
||||
/// the default Config is the TOML file format
|
||||
using ConfigTOML = ConfigBase;
|
||||
|
||||
/// ConfigTOML generates a TOML compliant output
|
||||
class ConfigTOML : public ConfigINI {
|
||||
/// ConfigINI generates a "standard" INI compliant output
|
||||
class ConfigINI : public ConfigTOML {
|
||||
|
||||
public:
|
||||
ConfigTOML() {
|
||||
commentChar = '#';
|
||||
arrayStart = '[';
|
||||
arrayEnd = ']';
|
||||
arraySeparator = ',';
|
||||
ConfigINI() {
|
||||
commentChar = ';';
|
||||
arrayStart = '\0';
|
||||
arrayEnd = '\0';
|
||||
arraySeparator = ' ';
|
||||
valueDelimiter = '=';
|
||||
}
|
||||
};
|
||||
} // namespace CLI
|
||||
} // namespace CLI
|
||||
|
@ -337,4 +337,4 @@ class OptionNotFound : public Error {
|
||||
|
||||
/// @}
|
||||
|
||||
} // namespace CLI
|
||||
} // namespace CLI
|
||||
|
@ -44,11 +44,11 @@ inline std::string Formatter::make_groups(const App *app, AppFormatMode mode) co
|
||||
// Options
|
||||
for(const std::string &group : groups) {
|
||||
std::vector<const Option *> opts = app->get_options([app, mode, &group](const Option *opt) {
|
||||
return opt->get_group() == group // Must be in the right group
|
||||
&& opt->nonpositional() // Must not be a positional
|
||||
&& (mode != AppFormatMode::Sub // If mode is Sub, then
|
||||
|| (app->get_help_ptr() != opt // Ignore help pointer
|
||||
&& app->get_help_all_ptr() != opt)); // Ignore help all pointer
|
||||
return opt->get_group() == group // Must be in the right group
|
||||
&& opt->nonpositional() // Must not be a positional
|
||||
&& (mode != AppFormatMode::Sub // If mode is Sub, then
|
||||
|| (app->get_help_ptr() != opt // Ignore help pointer
|
||||
&& app->get_help_all_ptr() != opt)); // Ignore help all pointer
|
||||
});
|
||||
if(!group.empty() && !opts.empty()) {
|
||||
out << make_group(group, false, opts);
|
||||
@ -220,7 +220,7 @@ inline std::string Formatter::make_expanded(const App *sub) const {
|
||||
|
||||
// Drop blank spaces
|
||||
std::string tmp = detail::find_and_replace(out.str(), "\n\n", "\n");
|
||||
tmp = tmp.substr(0, tmp.size() - 1); // Remove the final '\n'
|
||||
tmp = tmp.substr(0, tmp.size() - 1); // Remove the final '\n'
|
||||
|
||||
// Indent all but the first line (the name)
|
||||
return detail::find_and_replace(tmp, "\n", "\n ") + "\n";
|
||||
@ -278,4 +278,4 @@ inline std::string Formatter::make_option_usage(const Option *opt) const {
|
||||
return opt->get_required() ? out.str() : "[" + out.str() + "]";
|
||||
}
|
||||
|
||||
} // namespace CLI
|
||||
} // namespace CLI
|
||||
|
@ -24,9 +24,9 @@ class App;
|
||||
/// the second argument.
|
||||
|
||||
enum class AppFormatMode {
|
||||
Normal, //< The normal, detailed help
|
||||
All, //< A fully expanded help
|
||||
Sub, //< Used when printed as part of expanded subcommand
|
||||
Normal, //< The normal, detailed help
|
||||
All, //< A fully expanded help
|
||||
Sub, //< Used when printed as part of expanded subcommand
|
||||
};
|
||||
|
||||
/// This is the minimum requirements to run a formatter.
|
||||
@ -55,7 +55,7 @@ class FormatterBase {
|
||||
FormatterBase(FormatterBase &&) = default;
|
||||
|
||||
/// Adding a destructor in this form to work around bug in GCC 4.7
|
||||
virtual ~FormatterBase() noexcept {} // NOLINT(modernize-use-equals-default)
|
||||
virtual ~FormatterBase() noexcept {} // NOLINT(modernize-use-equals-default)
|
||||
|
||||
/// This is the key method that puts together help
|
||||
virtual std::string make_help(const App *, std::string, AppFormatMode) const = 0;
|
||||
@ -100,7 +100,7 @@ class FormatterLambda final : public FormatterBase {
|
||||
explicit FormatterLambda(funct_t funct) : lambda_(std::move(funct)) {}
|
||||
|
||||
/// Adding a destructor (mostly to make GCC 4.7 happy)
|
||||
~FormatterLambda() noexcept override {} // NOLINT(modernize-use-equals-default)
|
||||
~FormatterLambda() noexcept override {} // NOLINT(modernize-use-equals-default)
|
||||
|
||||
/// This will simply call the lambda function
|
||||
std::string make_help(const App *app, std::string name, AppFormatMode mode) const override {
|
||||
@ -177,4 +177,4 @@ class Formatter : public FormatterBase {
|
||||
///@}
|
||||
};
|
||||
|
||||
} // namespace CLI
|
||||
} // namespace CLI
|
||||
|
@ -33,11 +33,11 @@ class App;
|
||||
using Option_p = std::unique_ptr<Option>;
|
||||
/// Enumeration of the multiOption Policy selection
|
||||
enum class MultiOptionPolicy : char {
|
||||
Throw, //!< Throw an error if any extra arguments were given
|
||||
TakeLast, //!< take only the last Expected number of arguments
|
||||
TakeFirst, //!< take only the first Expected number of arguments
|
||||
Join, //!< merge all the arguments together into a single string via the delimiter character default('\n')
|
||||
TakeAll //!< just get all the passed argument regardless
|
||||
Throw, //!< Throw an error if any extra arguments were given
|
||||
TakeLast, //!< take only the last Expected number of arguments
|
||||
TakeFirst, //!< take only the first Expected number of arguments
|
||||
Join, //!< merge all the arguments together into a single string via the delimiter character default('\n')
|
||||
TakeAll //!< just get all the passed argument regardless
|
||||
};
|
||||
|
||||
/// This is the CRTP base class for Option and OptionDefaults. It was designed this way
|
||||
@ -316,10 +316,10 @@ class Option : public OptionBase<Option> {
|
||||
results_t proc_results_{};
|
||||
/// enumeration for the option state machine
|
||||
enum class option_state {
|
||||
parsing = 0, //!< The option is currently collecting parsed results
|
||||
validated = 2, //!< the results have been validated
|
||||
reduced = 4, //!< a subset of results has been generated
|
||||
callback_run = 6, //!< the callback has been executed
|
||||
parsing = 0, //!< The option is currently collecting parsed results
|
||||
validated = 2, //!< the results have been validated
|
||||
reduced = 4, //!< a subset of results has been generated
|
||||
callback_run = 6, //!< the callback has been executed
|
||||
};
|
||||
/// Whether the callback has run (needed for INI parsing)
|
||||
option_state current_option_state_{option_state::parsing};
|
||||
@ -631,8 +631,8 @@ class Option : public OptionBase<Option> {
|
||||
Option *multi_option_policy(MultiOptionPolicy value = MultiOptionPolicy::Throw) {
|
||||
if(value != multi_option_policy_) {
|
||||
if(multi_option_policy_ == MultiOptionPolicy::Throw && expected_max_ == detail::expected_max_vector_size &&
|
||||
expected_min_ > 1) { // this bizarre condition is to maintain backwards compatibility
|
||||
// with the previous behavior of expected_ with vectors
|
||||
expected_min_ > 1) { // this bizarre condition is to maintain backwards compatibility
|
||||
// with the previous behavior of expected_ with vectors
|
||||
expected_max_ = expected_min_;
|
||||
}
|
||||
multi_option_policy_ = value;
|
||||
@ -727,11 +727,11 @@ class Option : public OptionBase<Option> {
|
||||
/// Will include / prefer the positional name if positional is true.
|
||||
/// If all_options is false, pick just the most descriptive name to show.
|
||||
/// Use `get_name(true)` to get the positional name (replaces `get_pname`)
|
||||
std::string get_name(bool positional = false, //<[input] Show the positional name
|
||||
bool all_options = false //<[input] Show every option
|
||||
std::string get_name(bool positional = false, ///< Show the positional name
|
||||
bool all_options = false ///< Show every option
|
||||
) const {
|
||||
if(get_group().empty())
|
||||
return {}; // Hidden
|
||||
return {}; // Hidden
|
||||
|
||||
if(all_options) {
|
||||
|
||||
@ -822,7 +822,7 @@ class Option : public OptionBase<Option> {
|
||||
return lname;
|
||||
|
||||
if(ignore_case_ ||
|
||||
ignore_underscore_) { // We need to do the inverse, in case we are ignore_case or ignore underscore
|
||||
ignore_underscore_) { // We need to do the inverse, in case we are ignore_case or ignore underscore
|
||||
for(const std::string &sname : other.snames_)
|
||||
if(check_sname(sname))
|
||||
return sname;
|
||||
@ -974,7 +974,7 @@ class Option : public OptionBase<Option> {
|
||||
results_t res;
|
||||
if(results_.empty()) {
|
||||
if(!default_str_.empty()) {
|
||||
//_add_results takes an rvalue only
|
||||
// _add_results takes an rvalue only
|
||||
_add_result(std::string(default_str_), res);
|
||||
_validate_results(res);
|
||||
results_t extra;
|
||||
@ -1090,7 +1090,7 @@ class Option : public OptionBase<Option> {
|
||||
try {
|
||||
add_result(val_str);
|
||||
if(run_callback_for_default_) {
|
||||
run_callback(); // run callback sets the state we need to reset it again
|
||||
run_callback(); // run callback sets the state we need to reset it again
|
||||
current_option_state_ = option_state::parsing;
|
||||
} else {
|
||||
_validate_results(results_);
|
||||
@ -1126,7 +1126,7 @@ class Option : public OptionBase<Option> {
|
||||
void _validate_results(results_t &res) const {
|
||||
// Run the Validators (can change the string)
|
||||
if(!validators_.empty()) {
|
||||
if(type_size_max_ > 1) { // in this context index refers to the index in the type
|
||||
if(type_size_max_ > 1) { // in this context index refers to the index in the type
|
||||
int index = 0;
|
||||
if(get_items_expected_max() < static_cast<int>(res.size()) &&
|
||||
multi_option_policy_ == CLI::MultiOptionPolicy::TakeLast) {
|
||||
@ -1136,7 +1136,7 @@ class Option : public OptionBase<Option> {
|
||||
|
||||
for(std::string &result : res) {
|
||||
if(result.empty() && type_size_max_ != type_size_min_ && index >= 0) {
|
||||
index = 0; // reset index for variable size chunks
|
||||
index = 0; // reset index for variable size chunks
|
||||
continue;
|
||||
}
|
||||
auto err_msg = _validate(result, (index >= 0) ? (index % type_size_max_) : index);
|
||||
@ -1242,7 +1242,7 @@ class Option : public OptionBase<Option> {
|
||||
int _add_result(std::string &&result, std::vector<std::string> &res) const {
|
||||
int result_count = 0;
|
||||
if(allow_extra_args_ && !result.empty() && result.front() == '[' &&
|
||||
result.back() == ']') { // this is now a vector string likely from the default or user entry
|
||||
result.back() == ']') { // this is now a vector string likely from the default or user entry
|
||||
result.pop_back();
|
||||
|
||||
for(auto &var : CLI::detail::split(result.substr(1), ',')) {
|
||||
@ -1270,6 +1270,6 @@ class Option : public OptionBase<Option> {
|
||||
}
|
||||
return result_count;
|
||||
}
|
||||
}; // namespace CLI
|
||||
}; // namespace CLI
|
||||
|
||||
} // namespace CLI
|
||||
} // namespace CLI
|
||||
|
@ -134,5 +134,5 @@ get_names(const std::vector<std::string> &input) {
|
||||
short_names, long_names, pos_name);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace CLI
|
||||
} // namespace detail
|
||||
} // namespace CLI
|
||||
|
@ -28,7 +28,7 @@ std::ostream &operator<<(std::ostream &in, const T &item) {
|
||||
return in << static_cast<typename std::underlying_type<T>::type>(item);
|
||||
}
|
||||
|
||||
} // namespace enums
|
||||
} // namespace enums
|
||||
|
||||
/// Export to CLI namespace
|
||||
using enums::operator<<;
|
||||
@ -298,7 +298,7 @@ inline std::vector<std::string> split_up(std::string str, char delimiter = '\0')
|
||||
if(delims.find_first_of(str[0]) != std::string::npos) {
|
||||
keyChar = str[0];
|
||||
auto end = str.find_first_of(keyChar, 1);
|
||||
while((end != std::string::npos) && (str[end - 1] == '\\')) { // deal with escaped quotes
|
||||
while((end != std::string::npos) && (str[end - 1] == '\\')) { // deal with escaped quotes
|
||||
end = str.find_first_of(keyChar, end + 1);
|
||||
embeddedQuote = true;
|
||||
}
|
||||
@ -356,7 +356,7 @@ inline std::size_t escape_detect(std::string &str, std::size_t offset) {
|
||||
auto astart = str.find_last_of("-/ \"\'`", offset - 1);
|
||||
if(astart != std::string::npos) {
|
||||
if(str[astart] == ((str[offset] == '=') ? '-' : '/'))
|
||||
str[offset] = ' '; // interpret this as a space so the split_up works properly
|
||||
str[offset] = ' '; // interpret this as a space so the split_up works properly
|
||||
}
|
||||
}
|
||||
return offset + 1;
|
||||
@ -374,6 +374,6 @@ inline std::string &add_quotes_if_needed(std::string &str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
} // namespace CLI
|
||||
} // namespace CLI
|
||||
|
@ -13,7 +13,7 @@
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <chrono> // NOLINT(build/c++11)
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
@ -128,7 +128,7 @@ class AutoTimer : public Timer {
|
||||
~AutoTimer() { std::cout << to_string() << std::endl; }
|
||||
};
|
||||
|
||||
} // namespace CLI
|
||||
} // namespace CLI
|
||||
|
||||
/// This prints out the time if shifted into a std::cout like stream.
|
||||
inline std::ostream &operator<<(std::ostream &in, const CLI::Timer &timer) { return in << timer.to_string(); }
|
||||
|
@ -27,7 +27,7 @@ enum class enabler {};
|
||||
|
||||
/// An instance to use in EnableIf
|
||||
constexpr enabler dummy = {};
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
/// A copy of enable_if_t from C++14, compatible with C++11.
|
||||
///
|
||||
@ -624,7 +624,7 @@ template <typename T,
|
||||
enable_if_t<classify_object<T>::value == object_category::unsigned_integral, detail::enabler> = detail::dummy>
|
||||
bool lexical_cast(const std::string &input, T &output) {
|
||||
if(!input.empty() && input.front() == '-')
|
||||
return false; // std::stoull happily converts negative values to junk without any errors.
|
||||
return false; // std::stoull happily converts negative values to junk without any errors.
|
||||
|
||||
try {
|
||||
std::size_t n = 0;
|
||||
@ -804,7 +804,7 @@ bool lexical_assign(const std::string &input, T &output) {
|
||||
XC val{};
|
||||
bool parse_result = input.empty() ? true : lexical_cast<XC>(input, val);
|
||||
if(parse_result) {
|
||||
output = T(val); // use () form of constructor to allow some implicit conversions
|
||||
output = T(val); // use () form of constructor to allow some implicit conversions
|
||||
}
|
||||
return parse_result;
|
||||
}
|
||||
@ -1007,5 +1007,5 @@ void sum_flag_vector(const std::vector<std::string> &flags, T &output) {
|
||||
output = static_cast<T>(count);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace CLI
|
||||
} // namespace detail
|
||||
} // namespace CLI
|
||||
|
@ -42,7 +42,7 @@
|
||||
#endif
|
||||
|
||||
#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0
|
||||
#include <filesystem> // NOLINT(build/include)
|
||||
#include <filesystem> // NOLINT(build/include)
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@ -270,7 +270,7 @@ class Validator {
|
||||
return std::string(1, '(') + f1 + ')' + merger + '(' + f2 + ')';
|
||||
};
|
||||
}
|
||||
}; // namespace CLI
|
||||
}; // namespace CLI
|
||||
|
||||
/// Class wrapping some of the accessors of Validator
|
||||
class CustomValidator : public Validator {
|
||||
@ -459,7 +459,7 @@ class Number : public Validator {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
|
||||
// Static is not needed here, because global const implies static.
|
||||
|
||||
@ -561,7 +561,7 @@ typename std::remove_reference<T>::type &smart_deref(T &value) {
|
||||
/// Generate a string representation of a set
|
||||
template <typename T> std::string generate_set(const T &set) {
|
||||
using element_t = typename detail::element_type<T>::type;
|
||||
using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
|
||||
using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
|
||||
std::string out(1, '{');
|
||||
out.append(detail::join(
|
||||
detail::smart_deref(set),
|
||||
@ -574,7 +574,7 @@ template <typename T> std::string generate_set(const T &set) {
|
||||
/// Generate a string representation of a map
|
||||
template <typename T> std::string generate_map(const T &map, bool key_only = false) {
|
||||
using element_t = typename detail::element_type<T>::type;
|
||||
using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
|
||||
using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
|
||||
std::string out(1, '{');
|
||||
out.append(detail::join(
|
||||
detail::smart_deref(map),
|
||||
@ -685,7 +685,7 @@ typename std::enable_if<std::is_floating_point<T>::value, bool>::type checked_mu
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
/// Verify items are in a set
|
||||
class IsMember : public Validator {
|
||||
public:
|
||||
@ -705,11 +705,11 @@ class IsMember : public Validator {
|
||||
|
||||
// Get the type of the contained item - requires a container have ::value_type
|
||||
// if the type does not have first_type and second_type, these are both value_type
|
||||
using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
|
||||
using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
|
||||
using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
|
||||
using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
|
||||
|
||||
using local_item_t = typename IsMemberType<item_t>::type; // This will convert bad types to good ones
|
||||
// (const char * to std::string)
|
||||
using local_item_t = typename IsMemberType<item_t>::type; // This will convert bad types to good ones
|
||||
// (const char * to std::string)
|
||||
|
||||
// Make a local copy of the filter function, using a std::function if not one already
|
||||
std::function<local_item_t(local_item_t)> filter_fn = filter_function;
|
||||
@ -722,7 +722,7 @@ class IsMember : public Validator {
|
||||
func_ = [set, filter_fn](std::string &input) {
|
||||
local_item_t b;
|
||||
if(!detail::lexical_cast(input, b)) {
|
||||
throw ValidationError(input); // name is added later
|
||||
throw ValidationError(input); // name is added later
|
||||
}
|
||||
if(filter_fn) {
|
||||
b = filter_fn(b);
|
||||
@ -778,10 +778,10 @@ class Transformer : public Validator {
|
||||
"mapping must produce value pairs");
|
||||
// Get the type of the contained item - requires a container have ::value_type
|
||||
// if the type does not have first_type and second_type, these are both value_type
|
||||
using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
|
||||
using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
|
||||
using local_item_t = typename IsMemberType<item_t>::type; // This will convert bad types to good ones
|
||||
// (const char * to std::string)
|
||||
using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
|
||||
using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
|
||||
using local_item_t = typename IsMemberType<item_t>::type; // Will convert bad types to good ones
|
||||
// (const char * to std::string)
|
||||
|
||||
// Make a local copy of the filter function, using a std::function if not one already
|
||||
std::function<local_item_t(local_item_t)> filter_fn = filter_function;
|
||||
@ -836,12 +836,11 @@ class CheckedTransformer : public Validator {
|
||||
"mapping must produce value pairs");
|
||||
// Get the type of the contained item - requires a container have ::value_type
|
||||
// if the type does not have first_type and second_type, these are both value_type
|
||||
using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
|
||||
using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
|
||||
using local_item_t = typename IsMemberType<item_t>::type; // This will convert bad types to good ones
|
||||
// (const char * to std::string)
|
||||
using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair //
|
||||
// the type of the object pair
|
||||
using element_t = typename detail::element_type<T>::type; // Removes (smart) pointers if needed
|
||||
using item_t = typename detail::pair_adaptor<element_t>::first_type; // Is value_type if not a map
|
||||
using local_item_t = typename IsMemberType<item_t>::type; // Will convert bad types to good ones
|
||||
// (const char * to std::string)
|
||||
using iteration_type_t = typename detail::pair_adaptor<element_t>::value_type; // the type of the object pair
|
||||
|
||||
// Make a local copy of the filter function, using a std::function if not one already
|
||||
std::function<local_item_t(local_item_t)> filter_fn = filter_function;
|
||||
@ -1125,7 +1124,7 @@ inline std::pair<std::string, std::string> split_program_name(std::string comman
|
||||
return vals;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace detail
|
||||
/// @}
|
||||
|
||||
} // namespace CLI
|
||||
} // namespace CLI
|
||||
|
@ -684,7 +684,7 @@ TEST_F(TApp, FlagLikeOption) {
|
||||
EXPECT_EQ(1u, app.count("--flag"));
|
||||
EXPECT_TRUE(val);
|
||||
val = false;
|
||||
opt->type_size(0, 0); // should be the same as above
|
||||
opt->type_size(0, 0); // should be the same as above
|
||||
EXPECT_EQ(opt->get_type_size_min(), 0);
|
||||
EXPECT_EQ(opt->get_type_size_max(), 0);
|
||||
run();
|
||||
@ -797,7 +797,7 @@ TEST_F(TApp, DefaultOpts) {
|
||||
std::string s = "HI";
|
||||
|
||||
app.add_option("-i,i", i);
|
||||
app.add_option("-s,s", s)->capture_default_str(); // Used to be different
|
||||
app.add_option("-s,s", s)->capture_default_str(); // Used to be different
|
||||
|
||||
args = {"-i2", "9"};
|
||||
|
||||
@ -1191,7 +1191,7 @@ TEST_F(TApp, RequiredPositionalVector) {
|
||||
// Tests positionals at end
|
||||
TEST_F(TApp, RequiredPositionalValidation) {
|
||||
std::vector<std::string> sources;
|
||||
int dest; // required
|
||||
int dest; // required
|
||||
std::string d2;
|
||||
app.add_option("src", sources);
|
||||
app.add_option("dest", dest)->required()->check(CLI::PositiveNumber);
|
||||
@ -1416,7 +1416,7 @@ TEST_F(TApp, NotRequiredExpectedDoubleShort) {
|
||||
|
||||
TEST_F(TApp, RequiredFlags) {
|
||||
app.add_flag("-a")->required();
|
||||
app.add_flag("-b")->mandatory(); // Alternate term
|
||||
app.add_flag("-b")->mandatory(); // Alternate term
|
||||
|
||||
EXPECT_THROW(run(), CLI::RequiredError);
|
||||
|
||||
@ -1686,7 +1686,7 @@ TEST_F(TApp, RemoveExcludesLinks) {
|
||||
|
||||
args = {"--two"};
|
||||
|
||||
run(); // Mostly hoping it does not crash
|
||||
run(); // Mostly hoping it does not crash
|
||||
}
|
||||
|
||||
TEST_F(TApp, FileNotExists) {
|
||||
@ -1700,7 +1700,7 @@ TEST_F(TApp, FileNotExists) {
|
||||
run();
|
||||
EXPECT_EQ(myfile, filename);
|
||||
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_THROW(run(), CLI::ValidationError);
|
||||
// deactivate the check, so it should run now
|
||||
@ -1720,7 +1720,7 @@ TEST_F(TApp, FileExists) {
|
||||
|
||||
EXPECT_THROW(run(), CLI::ValidationError);
|
||||
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
EXPECT_TRUE(ok);
|
||||
run();
|
||||
EXPECT_EQ(myfile, filename);
|
||||
@ -1739,7 +1739,7 @@ TEST_F(TApp, NotFileExists) {
|
||||
|
||||
EXPECT_NO_THROW(run());
|
||||
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_THROW(run(), CLI::ValidationError);
|
||||
|
||||
@ -1749,7 +1749,7 @@ TEST_F(TApp, NotFileExists) {
|
||||
|
||||
TEST_F(TApp, pair_check) {
|
||||
std::string myfile{"pair_check_file.txt"};
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
EXPECT_TRUE(ok);
|
||||
|
||||
EXPECT_TRUE(CLI::ExistingFile(myfile).empty());
|
||||
@ -1781,7 +1781,7 @@ TEST_F(TApp, pair_check) {
|
||||
|
||||
TEST_F(TApp, pair_check_take_first) {
|
||||
std::string myfile{"pair_check_file2.txt"};
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
EXPECT_TRUE(ok);
|
||||
|
||||
EXPECT_TRUE(CLI::ExistingFile(myfile).empty());
|
||||
@ -1924,7 +1924,7 @@ TEST_F(TApp, VectorExpectedRange) {
|
||||
|
||||
EXPECT_EQ(opt->get_expected_max(), 4);
|
||||
EXPECT_EQ(opt->get_expected_min(), 2);
|
||||
opt->expected(4, 2); // just test the handling of reversed arguments
|
||||
opt->expected(4, 2); // just test the handling of reversed arguments
|
||||
EXPECT_EQ(opt->get_expected_max(), 4);
|
||||
EXPECT_EQ(opt->get_expected_min(), 2);
|
||||
opt->expected(-5);
|
||||
@ -2459,7 +2459,7 @@ TEST_F(TApp, vectorPairTypeRange) {
|
||||
|
||||
auto opt = app.add_option("--dict", custom_opt);
|
||||
|
||||
opt->type_size(2, 1); // just test switched arguments
|
||||
opt->type_size(2, 1); // just test switched arguments
|
||||
EXPECT_EQ(opt->get_type_size_min(), 1);
|
||||
EXPECT_EQ(opt->get_type_size_max(), 2);
|
||||
|
||||
@ -2477,7 +2477,7 @@ TEST_F(TApp, vectorPairTypeRange) {
|
||||
EXPECT_EQ(custom_opt[2].first, -1);
|
||||
EXPECT_EQ(custom_opt[2].second, "str4");
|
||||
|
||||
opt->type_size(-2, -1); // test negative arguments
|
||||
opt->type_size(-2, -1); // test negative arguments
|
||||
EXPECT_EQ(opt->get_type_size_min(), 1);
|
||||
EXPECT_EQ(opt->get_type_size_max(), 2);
|
||||
// this type size spec should run exactly as before
|
||||
|
@ -690,12 +690,12 @@ TEST_F(TApp, IniVector) {
|
||||
}
|
||||
TEST_F(TApp, TOMLVector) {
|
||||
|
||||
TempFile tmpini{"TestIniTmp.ini"};
|
||||
TempFile tmptoml{"TestTomlTmp.toml"};
|
||||
|
||||
app.set_config("--config", tmpini);
|
||||
app.set_config("--config", tmptoml);
|
||||
|
||||
{
|
||||
std::ofstream out{tmpini};
|
||||
std::ofstream out{tmptoml};
|
||||
out << "#this is a comment line\n";
|
||||
out << "[default]\n";
|
||||
out << "two=[2,3]\n";
|
||||
@ -1045,17 +1045,17 @@ TEST_F(TApp, IniSubcommandMultipleSections) {
|
||||
EXPECT_EQ(parse_c[0], 68U);
|
||||
EXPECT_EQ(parse_c[1], 58U);
|
||||
EXPECT_EQ(subsubcom->count(), 1u);
|
||||
EXPECT_EQ(subcom2->count(), 0u); // not configurable but value is updated
|
||||
EXPECT_EQ(subcom2->count(), 0u); // not configurable but value is updated
|
||||
}
|
||||
|
||||
TEST_F(TApp, DuplicateSubcommandCallbacks) {
|
||||
|
||||
TempFile tmpini{"TestIniTmp.ini"};
|
||||
TempFile tmptoml{"TesttomlTmp.toml"};
|
||||
|
||||
app.set_config("--config", tmpini);
|
||||
app.set_config("--config", tmptoml);
|
||||
|
||||
{
|
||||
std::ofstream out{tmpini};
|
||||
std::ofstream out{tmptoml};
|
||||
out << "[[foo]]" << std::endl;
|
||||
out << "[[foo]]" << std::endl;
|
||||
out << "[[foo]]" << std::endl;
|
||||
@ -1195,6 +1195,7 @@ TEST_F(TApp, IniFlagDual) {
|
||||
TempFile tmpini{"TestIniTmp.ini"};
|
||||
|
||||
bool boo{false};
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
app.add_flag("--flag", boo);
|
||||
app.set_config("--config", tmpini);
|
||||
|
||||
@ -1362,7 +1363,7 @@ TEST_F(TApp, IniFalseFlagsDefDisableOverrideSuccess) {
|
||||
EXPECT_EQ(15, val);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSimple) {
|
||||
TEST_F(TApp, TomlOutputSimple) {
|
||||
|
||||
int v{0};
|
||||
app.add_option("--simple", v);
|
||||
@ -1375,7 +1376,7 @@ TEST_F(TApp, IniOutputSimple) {
|
||||
EXPECT_EQ("simple=3\n", str);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputNoConfigurable) {
|
||||
TEST_F(TApp, TomlOutputNoConfigurable) {
|
||||
|
||||
int v1{0}, v2{0};
|
||||
app.add_option("--simple", v1);
|
||||
@ -1389,7 +1390,7 @@ TEST_F(TApp, IniOutputNoConfigurable) {
|
||||
EXPECT_EQ("simple=3\n", str);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputShortSingleDescription) {
|
||||
TEST_F(TApp, TomlOutputShortSingleDescription) {
|
||||
std::string flag = "some_flag";
|
||||
const std::string description = "Some short description.";
|
||||
app.add_flag("--" + flag, description);
|
||||
@ -1397,10 +1398,10 @@ TEST_F(TApp, IniOutputShortSingleDescription) {
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str(true, true);
|
||||
EXPECT_THAT(str, HasSubstr("; " + description + "\n" + flag + "=false\n"));
|
||||
EXPECT_THAT(str, HasSubstr("# " + description + "\n" + flag + "=false\n"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputShortDoubleDescription) {
|
||||
TEST_F(TApp, TomlOutputShortDoubleDescription) {
|
||||
std::string flag1 = "flagnr1";
|
||||
std::string flag2 = "flagnr2";
|
||||
const std::string description1 = "First description.";
|
||||
@ -1412,10 +1413,10 @@ TEST_F(TApp, IniOutputShortDoubleDescription) {
|
||||
|
||||
std::string str = app.config_to_str(true, true);
|
||||
EXPECT_THAT(
|
||||
str, HasSubstr("; " + description1 + "\n" + flag1 + "=false\n\n; " + description2 + "\n" + flag2 + "=false\n"));
|
||||
str, HasSubstr("# " + description1 + "\n" + flag1 + "=false\n\n# " + description2 + "\n" + flag2 + "=false\n"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputGroups) {
|
||||
TEST_F(TApp, TomlOutputGroups) {
|
||||
std::string flag1 = "flagnr1";
|
||||
std::string flag2 = "flagnr2";
|
||||
const std::string description1 = "First description.";
|
||||
@ -1430,7 +1431,7 @@ TEST_F(TApp, IniOutputGroups) {
|
||||
EXPECT_THAT(str, HasSubstr("group2"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputHiddenOptions) {
|
||||
TEST_F(TApp, TomlOutputHiddenOptions) {
|
||||
std::string flag1 = "flagnr1";
|
||||
std::string flag2 = "flagnr2";
|
||||
double val{12.7};
|
||||
@ -1454,7 +1455,7 @@ TEST_F(TApp, IniOutputHiddenOptions) {
|
||||
EXPECT_EQ(loc, std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputMultiLineDescription) {
|
||||
TEST_F(TApp, TomlOutputMultiLineDescription) {
|
||||
std::string flag = "some_flag";
|
||||
const std::string description = "Some short description.\nThat has lines.";
|
||||
app.add_flag("--" + flag, description);
|
||||
@ -1462,12 +1463,12 @@ TEST_F(TApp, IniOutputMultiLineDescription) {
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str(true, true);
|
||||
EXPECT_THAT(str, HasSubstr("; Some short description.\n"));
|
||||
EXPECT_THAT(str, HasSubstr("; That has lines.\n"));
|
||||
EXPECT_THAT(str, HasSubstr("# Some short description.\n"));
|
||||
EXPECT_THAT(str, HasSubstr("# That has lines.\n"));
|
||||
EXPECT_THAT(str, HasSubstr(flag + "=false\n"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputOptionGroup) {
|
||||
TEST_F(TApp, TomlOutputOptionGroup) {
|
||||
std::string flag1 = "flagnr1";
|
||||
std::string flag2 = "flagnr2";
|
||||
double val{12.7};
|
||||
@ -1496,20 +1497,7 @@ TEST_F(TApp, IniOutputOptionGroup) {
|
||||
EXPECT_GT(locg3, locg1);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputVector) {
|
||||
|
||||
std::vector<int> v;
|
||||
app.add_option("--vector", v);
|
||||
|
||||
args = {"--vector", "1", "2", "3"};
|
||||
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_EQ("vector=1 2 3\n", str);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputVectorTOML) {
|
||||
TEST_F(TApp, TomlOutputVector) {
|
||||
|
||||
std::vector<int> v;
|
||||
app.add_option("--vector", v);
|
||||
@ -1522,7 +1510,7 @@ TEST_F(TApp, IniOutputVectorTOML) {
|
||||
EXPECT_EQ("vector=[1, 2, 3]\n", str);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputVectorCustom) {
|
||||
TEST_F(TApp, ConfigOutputVectorCustom) {
|
||||
|
||||
std::vector<int> v;
|
||||
app.add_option("--vector", v);
|
||||
@ -1537,7 +1525,7 @@ TEST_F(TApp, IniOutputVectorCustom) {
|
||||
EXPECT_EQ("vector:{1; 2; 3}\n", str);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputFlag) {
|
||||
TEST_F(TApp, TomlOutputFlag) {
|
||||
|
||||
int v{0}, q{0};
|
||||
app.add_option("--simple", v);
|
||||
@ -1553,13 +1541,13 @@ TEST_F(TApp, IniOutputFlag) {
|
||||
EXPECT_THAT(str, HasSubstr("simple=3"));
|
||||
EXPECT_THAT(str, Not(HasSubstr("nothing")));
|
||||
EXPECT_THAT(str, HasSubstr("onething=true"));
|
||||
EXPECT_THAT(str, HasSubstr("something=true true"));
|
||||
EXPECT_THAT(str, HasSubstr("something=[true, true]"));
|
||||
|
||||
str = app.config_to_str(true);
|
||||
EXPECT_THAT(str, HasSubstr("nothing"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSet) {
|
||||
TEST_F(TApp, TomlOutputSet) {
|
||||
|
||||
int v{0};
|
||||
app.add_option("--simple", v)->check(CLI::IsMember({1, 2, 3}));
|
||||
@ -1572,7 +1560,7 @@ TEST_F(TApp, IniOutputSet) {
|
||||
EXPECT_THAT(str, HasSubstr("simple=2"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputDefault) {
|
||||
TEST_F(TApp, TomlOutputDefault) {
|
||||
|
||||
int v{7};
|
||||
app.add_option("--simple", v, "", true);
|
||||
@ -1586,7 +1574,7 @@ TEST_F(TApp, IniOutputDefault) {
|
||||
EXPECT_THAT(str, HasSubstr("simple=7"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSubcom) {
|
||||
TEST_F(TApp, TomlOutputSubcom) {
|
||||
|
||||
app.add_flag("--simple");
|
||||
auto subcom = app.add_subcommand("other");
|
||||
@ -1600,7 +1588,7 @@ TEST_F(TApp, IniOutputSubcom) {
|
||||
EXPECT_THAT(str, HasSubstr("other.newer=true"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSubcomConfigurable) {
|
||||
TEST_F(TApp, TomlOutputSubcomConfigurable) {
|
||||
|
||||
app.add_flag("--simple");
|
||||
auto subcom = app.add_subcommand("other")->configurable();
|
||||
@ -1616,7 +1604,7 @@ TEST_F(TApp, IniOutputSubcomConfigurable) {
|
||||
EXPECT_EQ(str.find("other.newer=true"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSubsubcom) {
|
||||
TEST_F(TApp, TomlOutputSubsubcom) {
|
||||
|
||||
app.add_flag("--simple");
|
||||
auto subcom = app.add_subcommand("other");
|
||||
@ -1633,7 +1621,7 @@ TEST_F(TApp, IniOutputSubsubcom) {
|
||||
EXPECT_THAT(str, HasSubstr("other.sub2.newest=true"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSubsubcomConfigurable) {
|
||||
TEST_F(TApp, TomlOutputSubsubcomConfigurable) {
|
||||
|
||||
app.add_flag("--simple");
|
||||
auto subcom = app.add_subcommand("other")->configurable();
|
||||
@ -1654,7 +1642,7 @@ TEST_F(TApp, IniOutputSubsubcomConfigurable) {
|
||||
EXPECT_EQ(str.find("sub2.newest=true"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSubsubcomConfigurableDeep) {
|
||||
TEST_F(TApp, TomlOutputSubsubcomConfigurableDeep) {
|
||||
|
||||
app.add_flag("--simple");
|
||||
auto subcom = app.add_subcommand("other")->configurable();
|
||||
@ -1677,7 +1665,7 @@ TEST_F(TApp, IniOutputSubsubcomConfigurableDeep) {
|
||||
EXPECT_EQ(str.find(".absolute_newest=true"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniQuotedOutput) {
|
||||
TEST_F(TApp, TomlOutputQuoted) {
|
||||
|
||||
std::string val1;
|
||||
app.add_option("--val1", val1);
|
||||
@ -1697,7 +1685,7 @@ TEST_F(TApp, IniQuotedOutput) {
|
||||
EXPECT_THAT(str, HasSubstr("val2='I am a \"confusing\" string'"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, DefaultsIniQuotedOutput) {
|
||||
TEST_F(TApp, DefaultsTomlOutputQuoted) {
|
||||
|
||||
std::string val1{"I am a string"};
|
||||
app.add_option("--val1", val1, "", true);
|
||||
@ -1718,7 +1706,7 @@ TEST_F(TApp, StopReadingConfigOnClear) {
|
||||
TempFile tmpini{"TestIniTmp.ini"};
|
||||
|
||||
app.set_config("--config", tmpini);
|
||||
auto ptr = app.set_config(); // Should *not* read config file
|
||||
auto ptr = app.set_config(); // Should *not* read config file
|
||||
EXPECT_EQ(ptr, nullptr);
|
||||
|
||||
{
|
||||
@ -1755,3 +1743,327 @@ TEST_F(TApp, ConfigWriteReadWrite) {
|
||||
|
||||
EXPECT_EQ(config1, config2);
|
||||
}
|
||||
|
||||
///////INI output tests
|
||||
|
||||
TEST_F(TApp, IniOutputSimple) {
|
||||
|
||||
int v{0};
|
||||
app.add_option("--simple", v);
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
args = {"--simple=3"};
|
||||
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_EQ("simple=3\n", str);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputNoConfigurable) {
|
||||
|
||||
int v1{0}, v2{0};
|
||||
app.add_option("--simple", v1);
|
||||
app.add_option("--noconf", v2)->configurable(false);
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
args = {"--simple=3", "--noconf=2"};
|
||||
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_EQ("simple=3\n", str);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputShortSingleDescription) {
|
||||
std::string flag = "some_flag";
|
||||
const std::string description = "Some short description.";
|
||||
app.add_flag("--" + flag, description);
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str(true, true);
|
||||
EXPECT_THAT(str, HasSubstr("; " + description + "\n" + flag + "=false\n"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputShortDoubleDescription) {
|
||||
std::string flag1 = "flagnr1";
|
||||
std::string flag2 = "flagnr2";
|
||||
const std::string description1 = "First description.";
|
||||
const std::string description2 = "Second description.";
|
||||
app.add_flag("--" + flag1, description1);
|
||||
app.add_flag("--" + flag2, description2);
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str(true, true);
|
||||
EXPECT_THAT(
|
||||
str, HasSubstr("; " + description1 + "\n" + flag1 + "=false\n\n; " + description2 + "\n" + flag2 + "=false\n"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputGroups) {
|
||||
std::string flag1 = "flagnr1";
|
||||
std::string flag2 = "flagnr2";
|
||||
const std::string description1 = "First description.";
|
||||
const std::string description2 = "Second description.";
|
||||
app.add_flag("--" + flag1, description1)->group("group1");
|
||||
app.add_flag("--" + flag2, description2)->group("group2");
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str(true, true);
|
||||
EXPECT_THAT(str, HasSubstr("group1"));
|
||||
EXPECT_THAT(str, HasSubstr("group2"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputHiddenOptions) {
|
||||
std::string flag1 = "flagnr1";
|
||||
std::string flag2 = "flagnr2";
|
||||
double val{12.7};
|
||||
const std::string description1 = "First description.";
|
||||
const std::string description2 = "Second description.";
|
||||
app.add_flag("--" + flag1, description1)->group("group1");
|
||||
app.add_flag("--" + flag2, description2)->group("group2");
|
||||
app.add_option("--dval", val, "", true)->group("");
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str(true, true);
|
||||
EXPECT_THAT(str, HasSubstr("group1"));
|
||||
EXPECT_THAT(str, HasSubstr("group2"));
|
||||
EXPECT_THAT(str, HasSubstr("dval=12.7"));
|
||||
auto loc = str.find("dval=12.7");
|
||||
auto locg1 = str.find("group1");
|
||||
EXPECT_GT(locg1, loc);
|
||||
// make sure it doesn't come twice
|
||||
loc = str.find("dval=12.7", loc + 4);
|
||||
EXPECT_EQ(loc, std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputMultiLineDescription) {
|
||||
std::string flag = "some_flag";
|
||||
const std::string description = "Some short description.\nThat has lines.";
|
||||
app.add_flag("--" + flag, description);
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str(true, true);
|
||||
EXPECT_THAT(str, HasSubstr("; Some short description.\n"));
|
||||
EXPECT_THAT(str, HasSubstr("; That has lines.\n"));
|
||||
EXPECT_THAT(str, HasSubstr(flag + "=false\n"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputOptionGroup) {
|
||||
std::string flag1 = "flagnr1";
|
||||
std::string flag2 = "flagnr2";
|
||||
double val{12.7};
|
||||
const std::string description1 = "First description.";
|
||||
const std::string description2 = "Second description.";
|
||||
app.add_flag("--" + flag1, description1)->group("group1");
|
||||
app.add_flag("--" + flag2, description2)->group("group2");
|
||||
auto og = app.add_option_group("group3", "g3 desc");
|
||||
og->add_option("--dval", val, "", true)->group("");
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str(true, true);
|
||||
EXPECT_THAT(str, HasSubstr("group1"));
|
||||
EXPECT_THAT(str, HasSubstr("group2"));
|
||||
EXPECT_THAT(str, HasSubstr("dval=12.7"));
|
||||
EXPECT_THAT(str, HasSubstr("group3"));
|
||||
EXPECT_THAT(str, HasSubstr("g3 desc"));
|
||||
auto loc = str.find("dval=12.7");
|
||||
auto locg1 = str.find("group1");
|
||||
auto locg3 = str.find("group3");
|
||||
EXPECT_LT(locg1, loc);
|
||||
// make sure it doesn't come twice
|
||||
loc = str.find("dval=12.7", loc + 4);
|
||||
EXPECT_EQ(loc, std::string::npos);
|
||||
EXPECT_GT(locg3, locg1);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputVector) {
|
||||
|
||||
std::vector<int> v;
|
||||
app.add_option("--vector", v);
|
||||
|
||||
args = {"--vector", "1", "2", "3"};
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_EQ("vector=1 2 3\n", str);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputFlag) {
|
||||
|
||||
int v{0}, q{0};
|
||||
app.add_option("--simple", v);
|
||||
app.add_flag("--nothing");
|
||||
app.add_flag("--onething");
|
||||
app.add_flag("--something", q);
|
||||
|
||||
args = {"--simple=3", "--onething", "--something", "--something"};
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_THAT(str, HasSubstr("simple=3"));
|
||||
EXPECT_THAT(str, Not(HasSubstr("nothing")));
|
||||
EXPECT_THAT(str, HasSubstr("onething=true"));
|
||||
EXPECT_THAT(str, HasSubstr("something=true true"));
|
||||
|
||||
str = app.config_to_str(true);
|
||||
EXPECT_THAT(str, HasSubstr("nothing"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSet) {
|
||||
|
||||
int v{0};
|
||||
app.add_option("--simple", v)->check(CLI::IsMember({1, 2, 3}));
|
||||
|
||||
args = {"--simple=2"};
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_THAT(str, HasSubstr("simple=2"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputDefault) {
|
||||
|
||||
int v{7};
|
||||
app.add_option("--simple", v, "", true);
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_THAT(str, Not(HasSubstr("simple=7")));
|
||||
|
||||
str = app.config_to_str(true);
|
||||
EXPECT_THAT(str, HasSubstr("simple=7"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSubcom) {
|
||||
|
||||
app.add_flag("--simple");
|
||||
auto subcom = app.add_subcommand("other");
|
||||
subcom->add_flag("--newer");
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
args = {"--simple", "other", "--newer"};
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_THAT(str, HasSubstr("simple=true"));
|
||||
EXPECT_THAT(str, HasSubstr("other.newer=true"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSubcomConfigurable) {
|
||||
|
||||
app.add_flag("--simple");
|
||||
auto subcom = app.add_subcommand("other")->configurable();
|
||||
subcom->add_flag("--newer");
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
args = {"--simple", "other", "--newer"};
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_THAT(str, HasSubstr("simple=true"));
|
||||
EXPECT_THAT(str, HasSubstr("[other]"));
|
||||
EXPECT_THAT(str, HasSubstr("newer=true"));
|
||||
EXPECT_EQ(str.find("other.newer=true"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSubsubcom) {
|
||||
|
||||
app.add_flag("--simple");
|
||||
auto subcom = app.add_subcommand("other");
|
||||
subcom->add_flag("--newer");
|
||||
auto subsubcom = subcom->add_subcommand("sub2");
|
||||
subsubcom->add_flag("--newest");
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
args = {"--simple", "other", "--newer", "sub2", "--newest"};
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_THAT(str, HasSubstr("simple=true"));
|
||||
EXPECT_THAT(str, HasSubstr("other.newer=true"));
|
||||
EXPECT_THAT(str, HasSubstr("other.sub2.newest=true"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSubsubcomConfigurable) {
|
||||
|
||||
app.add_flag("--simple");
|
||||
auto subcom = app.add_subcommand("other")->configurable();
|
||||
subcom->add_flag("--newer");
|
||||
|
||||
auto subsubcom = subcom->add_subcommand("sub2");
|
||||
subsubcom->add_flag("--newest");
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
args = {"--simple", "other", "--newer", "sub2", "--newest"};
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_THAT(str, HasSubstr("simple=true"));
|
||||
EXPECT_THAT(str, HasSubstr("[other]"));
|
||||
EXPECT_THAT(str, HasSubstr("newer=true"));
|
||||
EXPECT_THAT(str, HasSubstr("[other.sub2]"));
|
||||
EXPECT_THAT(str, HasSubstr("newest=true"));
|
||||
EXPECT_EQ(str.find("sub2.newest=true"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputSubsubcomConfigurableDeep) {
|
||||
|
||||
app.add_flag("--simple");
|
||||
auto subcom = app.add_subcommand("other")->configurable();
|
||||
subcom->add_flag("--newer");
|
||||
|
||||
auto subsubcom = subcom->add_subcommand("sub2");
|
||||
subsubcom->add_flag("--newest");
|
||||
auto sssscom = subsubcom->add_subcommand("sub-level2");
|
||||
subsubcom->add_flag("--still_newer");
|
||||
auto s5com = sssscom->add_subcommand("sub-level3");
|
||||
s5com->add_flag("--absolute_newest");
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
args = {"--simple", "other", "sub2", "sub-level2", "sub-level3", "--absolute_newest"};
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_THAT(str, HasSubstr("simple=true"));
|
||||
EXPECT_THAT(str, HasSubstr("[other.sub2.sub-level2.sub-level3]"));
|
||||
EXPECT_THAT(str, HasSubstr("absolute_newest=true"));
|
||||
EXPECT_EQ(str.find(".absolute_newest=true"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(TApp, IniOutputQuoted) {
|
||||
|
||||
std::string val1;
|
||||
app.add_option("--val1", val1);
|
||||
|
||||
std::string val2;
|
||||
app.add_option("--val2", val2);
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
args = {"--val1", "I am a string", "--val2", R"(I am a "confusing" string)"};
|
||||
|
||||
run();
|
||||
|
||||
EXPECT_EQ("I am a string", val1);
|
||||
EXPECT_EQ("I am a \"confusing\" string", val2);
|
||||
|
||||
std::string str = app.config_to_str();
|
||||
EXPECT_THAT(str, HasSubstr("val1=\"I am a string\""));
|
||||
EXPECT_THAT(str, HasSubstr("val2='I am a \"confusing\" string'"));
|
||||
}
|
||||
|
||||
TEST_F(TApp, DefaultsIniOutputQuoted) {
|
||||
|
||||
std::string val1{"I am a string"};
|
||||
app.add_option("--val1", val1, "", true);
|
||||
|
||||
std::string val2{R"(I am a "confusing" string)"};
|
||||
app.add_option("--val2", val2, "", true);
|
||||
app.config_formatter(std::make_shared<CLI::ConfigINI>());
|
||||
run();
|
||||
|
||||
std::string str = app.config_to_str(true);
|
||||
EXPECT_THAT(str, HasSubstr("val1=\"I am a string\""));
|
||||
EXPECT_THAT(str, HasSubstr("val2='I am a \"confusing\" string'"));
|
||||
}
|
||||
|
@ -527,7 +527,7 @@ TEST_F(TApp, GetOptionList) {
|
||||
auto flag = app.add_flag("--one");
|
||||
auto opt = app.add_option("--two", two);
|
||||
|
||||
const CLI::App &const_app = app; // const alias to force use of const-methods
|
||||
const CLI::App &const_app = app; // const alias to force use of const-methods
|
||||
std::vector<const CLI::Option *> opt_list = const_app.get_options();
|
||||
|
||||
ASSERT_EQ(opt_list.size(), static_cast<std::size_t>(3));
|
||||
|
@ -715,7 +715,7 @@ TEST(Exit, ExitCodes) {
|
||||
EXPECT_EQ(0, app.exit(CLI::CallForHelp()));
|
||||
EXPECT_EQ(i, app.exit(CLI::ExtrasError({"Thing"})));
|
||||
EXPECT_EQ(42, app.exit(CLI::RuntimeError(42)));
|
||||
EXPECT_EQ(1, app.exit(CLI::RuntimeError())); // Not sure if a default here is a good thing
|
||||
EXPECT_EQ(1, app.exit(CLI::RuntimeError())); // Not sure if a default here is a good thing
|
||||
}
|
||||
|
||||
struct CapturedHelp : public ::testing::Test {
|
||||
@ -945,7 +945,7 @@ TEST(THelp, ValidatorsText) {
|
||||
std::string help = app.help();
|
||||
EXPECT_THAT(help, HasSubstr("TEXT:FILE"));
|
||||
EXPECT_THAT(help, HasSubstr("INT in [1 - 4]"));
|
||||
EXPECT_THAT(help, HasSubstr("UINT:INT in [0 - 12]")); // Loses UINT
|
||||
EXPECT_THAT(help, HasSubstr("UINT:INT in [0 - 12]")); // Loses UINT
|
||||
}
|
||||
|
||||
TEST(THelp, ValidatorsTextCustom) {
|
||||
|
@ -218,7 +218,7 @@ TEST(Trim, TrimCopy) {
|
||||
TEST(Validators, FileExists) {
|
||||
std::string myfile{"TestFileNotUsed.txt"};
|
||||
EXPECT_FALSE(CLI::ExistingFile(myfile).empty());
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_TRUE(CLI::ExistingFile(myfile).empty());
|
||||
|
||||
@ -229,7 +229,7 @@ TEST(Validators, FileExists) {
|
||||
TEST(Validators, FileNotExists) {
|
||||
std::string myfile{"TestFileNotUsed.txt"};
|
||||
EXPECT_TRUE(CLI::NonexistentPath(myfile).empty());
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_FALSE(CLI::NonexistentPath(myfile).empty());
|
||||
|
||||
@ -255,7 +255,7 @@ TEST(Validators, DirectoryNotExists) {
|
||||
TEST(Validators, DirectoryIsFile) {
|
||||
std::string myfile{"TestFileNotUsed.txt"};
|
||||
EXPECT_TRUE(CLI::NonexistentPath(myfile).empty());
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_FALSE(CLI::ExistingDirectory(myfile).empty());
|
||||
|
||||
@ -271,7 +271,7 @@ TEST(Validators, PathExistsDir) {
|
||||
TEST(Validators, PathExistsFile) {
|
||||
std::string myfile{"TestFileNotUsed.txt"};
|
||||
EXPECT_FALSE(CLI::ExistingPath(myfile).empty());
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_TRUE(CLI::ExistingPath(myfile).empty());
|
||||
|
||||
@ -383,7 +383,7 @@ TEST(Validators, CombinedOrRange) {
|
||||
TEST(Validators, CombinedPaths) {
|
||||
std::string myfile{"TestFileNotUsed.txt"};
|
||||
EXPECT_FALSE(CLI::ExistingFile(myfile).empty());
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
EXPECT_TRUE(ok);
|
||||
|
||||
std::string dir{"../tests"};
|
||||
@ -435,7 +435,7 @@ TEST(Validators, ProgramNameSplit) {
|
||||
EXPECT_EQ(res.second, "this is a bunch of extra stuff");
|
||||
|
||||
res = CLI::detail::split_program_name("./program_name this is a bunch of extra stuff ");
|
||||
EXPECT_EQ(res.first, "./program_name"); // test sectioning of first argument even if it can't detect the file
|
||||
EXPECT_EQ(res.first, "./program_name"); // test sectioning of first argument even if it can't detect the file
|
||||
EXPECT_EQ(res.second, "this is a bunch of extra stuff");
|
||||
|
||||
res = CLI::detail::split_program_name(std::string(" ./") + std::string(myfile) + " ");
|
||||
@ -663,7 +663,7 @@ TEST(AppHelper, TempfileCreated) {
|
||||
|
||||
EXPECT_FALSE(CLI::ExistingFile(myfile).empty());
|
||||
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
bool ok = static_cast<bool>(std::ofstream(myfile.c_str()).put('a')); // create file
|
||||
EXPECT_TRUE(ok);
|
||||
EXPECT_TRUE(CLI::ExistingFile(name).empty());
|
||||
EXPECT_THROW({ TempFile otherfile(name); }, std::runtime_error);
|
||||
@ -994,12 +994,12 @@ TEST(Types, LexicalCastParsable) {
|
||||
|
||||
std::complex<double> output;
|
||||
EXPECT_TRUE(CLI::detail::lexical_cast(input, output));
|
||||
EXPECT_DOUBLE_EQ(output.real(), 4.2); // Doing this in one go sometimes has trouble
|
||||
EXPECT_DOUBLE_EQ(output.imag(), 7.3); // on clang + c++4.8 due to missing const
|
||||
EXPECT_DOUBLE_EQ(output.real(), 4.2); // Doing this in one go sometimes has trouble
|
||||
EXPECT_DOUBLE_EQ(output.imag(), 7.3); // on clang + c++4.8 due to missing const
|
||||
|
||||
EXPECT_TRUE(CLI::detail::lexical_cast("2.456", output));
|
||||
EXPECT_DOUBLE_EQ(output.real(), 2.456); // Doing this in one go sometimes has trouble
|
||||
EXPECT_DOUBLE_EQ(output.imag(), 0.0); // on clang + c++4.8 due to missing const
|
||||
EXPECT_DOUBLE_EQ(output.real(), 2.456); // Doing this in one go sometimes has trouble
|
||||
EXPECT_DOUBLE_EQ(output.imag(), 0.0); // on clang + c++4.8 due to missing const
|
||||
|
||||
EXPECT_FALSE(CLI::detail::lexical_cast(fail_input, output));
|
||||
EXPECT_FALSE(CLI::detail::lexical_cast(extra_input, output));
|
||||
|
@ -222,8 +222,8 @@ template <> bool lexical_cast<spair>(const std::string &input, spair &output) {
|
||||
output = {input.substr(0, sep), input.substr(sep + 1)};
|
||||
return true;
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace CLI
|
||||
} // namespace detail
|
||||
} // namespace CLI
|
||||
|
||||
TEST_F(TApp, custom_string_converter) {
|
||||
spair val;
|
||||
@ -295,14 +295,14 @@ template <> bool lexical_cast<std::complex<double>>(const std::string &input, st
|
||||
}
|
||||
return worked;
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace CLI
|
||||
} // namespace detail
|
||||
} // namespace CLI
|
||||
|
||||
TEST_F(TApp, AddingComplexParserDetail) {
|
||||
|
||||
bool skip_tests = false;
|
||||
try { // check if the library actually supports regex, it is possible to link against a non working regex in the
|
||||
// standard library
|
||||
try { // check if the library actually supports regex, it is possible to link against a non working regex in the
|
||||
// standard library
|
||||
std::smatch m;
|
||||
std::string input = "1.5+2.5j";
|
||||
static const std::regex creg(
|
||||
|
@ -768,6 +768,6 @@ TEST_F(ManyGroupsPreTrigger, PreTriggerTestsSubcommand) {
|
||||
EXPECT_EQ(triggerMain, 4u);
|
||||
EXPECT_EQ(trigger1, 1u);
|
||||
EXPECT_EQ(trigger2, 3u);
|
||||
EXPECT_EQ(trigger3, 1u); // processes the first argument in group3 which includes the entire subcommand, which will
|
||||
// go until the sub1 command is given
|
||||
EXPECT_EQ(trigger3, 1u); // processes the first argument in group3 which includes the entire subcommand, which will
|
||||
// go until the sub1 command is given
|
||||
}
|
||||
|
@ -508,11 +508,11 @@ TEST_F(TApp, InSetIgnoreCase) {
|
||||
|
||||
args = {"--quick", "two"};
|
||||
run();
|
||||
EXPECT_EQ("Two", choice); // Keeps caps from set
|
||||
EXPECT_EQ("Two", choice); // Keeps caps from set
|
||||
|
||||
args = {"--quick", "ThrEE"};
|
||||
run();
|
||||
EXPECT_EQ("THREE", choice); // Keeps caps from set
|
||||
EXPECT_EQ("THREE", choice); // Keeps caps from set
|
||||
|
||||
args = {"--quick", "four"};
|
||||
EXPECT_THROW(run(), CLI::ValidationError);
|
||||
@ -533,11 +533,11 @@ TEST_F(TApp, InSetIgnoreCaseMutableValue) {
|
||||
|
||||
args = {"--quick", "two"};
|
||||
run();
|
||||
EXPECT_EQ("Two", choice); // Keeps caps from set
|
||||
EXPECT_EQ("Two", choice); // Keeps caps from set
|
||||
|
||||
args = {"--quick", "ThrEE"};
|
||||
run();
|
||||
EXPECT_EQ("THREE", choice); // Keeps caps from set
|
||||
EXPECT_EQ("THREE", choice); // Keeps caps from set
|
||||
|
||||
options.clear();
|
||||
args = {"--quick", "ThrEE"};
|
||||
@ -556,16 +556,16 @@ TEST_F(TApp, InSetIgnoreCasePointer) {
|
||||
|
||||
args = {"--quick", "two"};
|
||||
run();
|
||||
EXPECT_EQ("Two", choice); // Keeps caps from set
|
||||
EXPECT_EQ("Two", choice); // Keeps caps from set
|
||||
|
||||
args = {"--quick", "ThrEE"};
|
||||
run();
|
||||
EXPECT_EQ("THREE", choice); // Keeps caps from set
|
||||
EXPECT_EQ("THREE", choice); // Keeps caps from set
|
||||
|
||||
delete options;
|
||||
args = {"--quick", "ThrEE"};
|
||||
run();
|
||||
EXPECT_EQ("THREE", choice); // this does not throw a segfault
|
||||
EXPECT_EQ("THREE", choice); // this does not throw a segfault
|
||||
|
||||
args = {"--quick", "four"};
|
||||
EXPECT_THROW(run(), CLI::ValidationError);
|
||||
@ -600,11 +600,11 @@ TEST_F(TApp, InSetIgnoreUnderscore) {
|
||||
|
||||
args = {"--quick", "optiontwo"};
|
||||
run();
|
||||
EXPECT_EQ("option_two", choice); // Keeps underscore from set
|
||||
EXPECT_EQ("option_two", choice); // Keeps underscore from set
|
||||
|
||||
args = {"--quick", "_option_thr_ee"};
|
||||
run();
|
||||
EXPECT_EQ("optionthree", choice); // no underscore
|
||||
EXPECT_EQ("optionthree", choice); // no underscore
|
||||
|
||||
args = {"--quick", "Option4"};
|
||||
EXPECT_THROW(run(), CLI::ValidationError);
|
||||
@ -626,11 +626,11 @@ TEST_F(TApp, InSetIgnoreCaseUnderscore) {
|
||||
|
||||
args = {"--quick", "OptionTwo"};
|
||||
run();
|
||||
EXPECT_EQ("option_two", choice); // Keeps underscore and case from set
|
||||
EXPECT_EQ("option_two", choice); // Keeps underscore and case from set
|
||||
|
||||
args = {"--quick", "_OPTION_thr_ee"};
|
||||
run();
|
||||
EXPECT_EQ("OptionThree", choice); // no underscore
|
||||
EXPECT_EQ("OptionThree", choice); // no underscore
|
||||
|
||||
args = {"--quick", "Option4"};
|
||||
EXPECT_THROW(run(), CLI::ValidationError);
|
||||
|
@ -104,7 +104,7 @@ TEST_F(TApp, CrazyNameSubcommand) {
|
||||
EXPECT_EQ(sub1->count(), 1u);
|
||||
}
|
||||
|
||||
TEST_F(TApp, RequiredAndSubcommands) { // #23
|
||||
TEST_F(TApp, RequiredAndSubcommands) { // #23
|
||||
|
||||
std::string baz;
|
||||
app.add_option("baz", baz, "Baz Description", true)->required();
|
||||
@ -631,13 +631,13 @@ TEST_F(TApp, CallbackOrderingImmediateMain) {
|
||||
EXPECT_EQ(0, sub_val);
|
||||
// the main app callback should run before the subcommand callbacks
|
||||
app.immediate_callback();
|
||||
val = 0; // reset value
|
||||
val = 0; // reset value
|
||||
run();
|
||||
EXPECT_EQ(2, val);
|
||||
EXPECT_EQ(1, sub_val);
|
||||
// the subcommand callback now runs immediately after processing and before the main app callback again
|
||||
sub->immediate_callback();
|
||||
val = 0; // reset value
|
||||
val = 0; // reset value
|
||||
run();
|
||||
EXPECT_EQ(1, val);
|
||||
EXPECT_EQ(0, sub_val);
|
||||
@ -1213,7 +1213,7 @@ TEST_F(ManySubcommands, Unlimited) {
|
||||
run();
|
||||
EXPECT_EQ(app.remaining(true), vs_t());
|
||||
|
||||
app.require_subcommand(2, 0); // 2 or more
|
||||
app.require_subcommand(2, 0); // 2 or more
|
||||
|
||||
run();
|
||||
EXPECT_EQ(app.remaining(true), vs_t());
|
||||
|
@ -4,7 +4,7 @@
|
||||
struct TApp_TBO : public TApp, public ::testing::WithParamInterface<const char *> {};
|
||||
|
||||
TEST_P(TApp_TBO, TrueBoolOption) {
|
||||
bool value{false}; // Not used, but set just in case
|
||||
bool value{false}; // Not used, but set just in case
|
||||
app.add_option("-b,--bool", value);
|
||||
args = {"--bool", GetParam()};
|
||||
run();
|
||||
@ -19,7 +19,7 @@ INSTANTIATE_TEST_CASE_P(TrueBoolOptions, TApp_TBO, ::testing::Values("true", "on
|
||||
struct TApp_FBO : public TApp, public ::testing::WithParamInterface<const char *> {};
|
||||
|
||||
TEST_P(TApp_FBO, FalseBoolOptions) {
|
||||
bool value{true}; // Not used, but set just in case
|
||||
bool value{true}; // Not used, but set just in case
|
||||
app.add_option("-b,--bool", value);
|
||||
args = {"--bool", GetParam()};
|
||||
run();
|
||||
|
@ -33,7 +33,7 @@ class TempFile {
|
||||
}
|
||||
|
||||
~TempFile() {
|
||||
std::remove(_name.c_str()); // Doesn't matter if returns 0 or not
|
||||
std::remove(_name.c_str()); // Doesn't matter if returns 0 or not
|
||||
}
|
||||
|
||||
operator const std::string &() const { return _name; }
|
||||
|
Loading…
Reference in New Issue
Block a user