mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-29 12:13:52 +00:00
Making mutable sets explicit (#200)
This commit is contained in:
parent
8d7aefe21f
commit
02c49388d7
@ -1,7 +1,7 @@
|
||||
## Version 1.7: Parse breakup (in progress)
|
||||
|
||||
The parsing procedure now maps much more sensibly to complex, nested subcommand structures. Each phase of the parsing happens on all subcommands before moving on with the next phase of the parse. This allows several features, like required environment variables, to work properly even through subcommand boundaries.
|
||||
Passing the same subcommand multiple times is better supported. Several new features were added as well, including Windows style option support, parsing strings directly, and ignoring underscores in names.
|
||||
Passing the same subcommand multiple times is better supported. Several new features were added as well, including Windows style option support, parsing strings directly, and ignoring underscores in names. Adding a set that you plan to change later must now be done with `add_mutable_set`.
|
||||
|
||||
* Support Windows style options with `->allow_windows_style_options`. [#187] On by default on Windows. [#190]
|
||||
* Added `parse(string)` to split up and parse a command-line style string directly. [#186]
|
||||
@ -9,6 +9,7 @@ Passing the same subcommand multiple times is better supported. Several new feat
|
||||
* The default INI Config will now add quotes to strings with spaces [#195]
|
||||
* The default message now will mention the help-all flag also if present [#197]
|
||||
* Added `->description` to set Option descriptions [#199]
|
||||
* Mutating sets (introduced in Version 1.6) now have a clear add method, `add_mutable_set*`, since the set reference should not expire [#200]
|
||||
* Subcommands now track how many times they were parsed in a parsing process. `count()` with no arguments will return the number of times a subcommand was encountered. [#179]
|
||||
* Parsing is now done in phases: `shortcurcuits`, `ini`, `env`, `callbacks`, and `requirements`; all subcommands complete a phase before moving on. [#179]
|
||||
* Calling parse multiple times is now officially supported without `clear` (automatic). [#179]
|
||||
@ -28,6 +29,7 @@ Passing the same subcommand multiple times is better supported. Several new feat
|
||||
[#197]: https://github.com/CLIUtils/CLI11/pull/197
|
||||
[#195]: https://github.com/CLIUtils/CLI11/issues/195
|
||||
[#199]: https://github.com/CLIUtils/CLI11/pull/199
|
||||
[#200]: https://github.com/CLIUtils/CLI11/pull/200
|
||||
|
||||
## Version 1.6.2: Help-all
|
||||
|
||||
|
@ -194,17 +194,19 @@ app.add_set(option_name,
|
||||
set_of_possible_options,
|
||||
help_string="",
|
||||
default=false)
|
||||
app.add_mutable_set(... // Set can change later, keeps reference
|
||||
|
||||
app.add_set_ignore_case(... // String only
|
||||
|
||||
app.add__mutable_set_ignore_case(... // String only
|
||||
app.add_set_ignore_underscore(... // String only
|
||||
|
||||
app.add__mutable_set_ignore_underscore(... // String only
|
||||
app.add_set_ignore_case_underscore(... // String only
|
||||
app.add_mutable_set_ignore_case_underscore(... // String only
|
||||
|
||||
App* subcom = app.add_subcommand(name, description);
|
||||
```
|
||||
|
||||
An option name must start with a alphabetic character or underscore. For long options, anything but an equals sign or a comma is valid after that. Names are given as a comma separated string, with the dash or dashes. An option or flag can have as many names as you want, and afterward, using `count`, you can use any of the names, with dashes as needed, to count the options. One of the names is allowed to be given without proceeding dash(es); if present the option is a positional option, and that name will be used on help line for its positional form. If you want the default value to print in the help description, pass in `true` for the final parameter for `add_option` or `add_set`. The set options allow your users to pick from a set of predefined options; you can add an existing set if you need to modify the set later, or you can use an initializer list.
|
||||
An option name must start with a alphabetic character or underscore. For long options, anything but an equals sign or a comma is valid after that. Names are given as a comma separated string, with the dash or dashes. An option or flag can have as many names as you want, and afterward, using `count`, you can use any of the names, with dashes as needed, to count the options. One of the names is allowed to be given without proceeding dash(es); if present the option is a positional option, and that name will be used on help line for its positional form. If you want the default value to print in the help description, pass in `true` for the final parameter for `add_option` or `add_set`. The set options allow your users to pick from a set of predefined options, and you can use an initializer list directly if you like. If you need to modify the set later, use the `mutable` forms.
|
||||
|
||||
On a C++14 compiler, you can pass a callback function directly to `.add_flag`, while in C++11 mode you'll need to use `.add_flag_function` if you want a callback function. The function will be given the number of times the flag was passed. You can throw a relevant `CLI::ParseError` to signal a failure.
|
||||
|
||||
|
@ -547,8 +547,8 @@ class App {
|
||||
/// Add set of options (No default, temp reference, such as an inline set)
|
||||
template <typename T>
|
||||
Option *add_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
|
||||
std::set<T> options, ///< The set of possibilities
|
||||
std::string description = "") {
|
||||
|
||||
std::string simple_name = CLI::detail::split(option_name, ',').at(0);
|
||||
@ -566,12 +566,12 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options (No default, non-temp reference, such as an existing set)
|
||||
/// Add set of options (No default, set can be changed afterwords - do not destroy the set)
|
||||
template <typename T>
|
||||
Option *add_set(std::string option_name,
|
||||
T &member, ///< The selected member of the set
|
||||
const std::set<T> &options, ///< The set of possibilities
|
||||
std::string description = "") {
|
||||
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
|
||||
std::string description = "") {
|
||||
|
||||
std::string simple_name = CLI::detail::split(option_name, ',').at(0);
|
||||
CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
|
||||
@ -588,11 +588,11 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options (with default, R value, such as an inline set)
|
||||
/// Add set of options (with default, static set, such as an inline set)
|
||||
template <typename T>
|
||||
Option *add_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
|
||||
std::set<T> options, ///< The set of possibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
|
||||
@ -616,13 +616,13 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options (with default, L value reference, such as an existing set)
|
||||
/// Add set of options (with default, set can be changed afterwards - do not destroy the set)
|
||||
template <typename T>
|
||||
Option *add_set(std::string option_name,
|
||||
T &member, ///< The selected member of the set
|
||||
const std::set<T> &options, ///< The set of possibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
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
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
|
||||
std::string simple_name = CLI::detail::split(option_name, ',').at(0);
|
||||
CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
|
||||
@ -643,10 +643,10 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore case (no default, R value)
|
||||
/// Add set of options, string only, ignore case (no default, static set)
|
||||
Option *add_set_ignore_case(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &&options, ///< The set of possibilities
|
||||
std::string &member, ///< The selected member of the set
|
||||
std::set<std::string> options, ///< The set of possibilities
|
||||
std::string description = "") {
|
||||
|
||||
std::string simple_name = CLI::detail::split(option_name, ',').at(0);
|
||||
@ -671,11 +671,12 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore case (no default, L value)
|
||||
Option *add_set_ignore_case(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &options, ///< The set of possibilities
|
||||
std::string description = "") {
|
||||
/// Add set of options, string only, ignore case (no default, set can be changed afterwards - do not destroy the
|
||||
/// set)
|
||||
Option *add_mutable_set_ignore_case(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &options, ///< The set of possibilities
|
||||
std::string description = "") {
|
||||
|
||||
std::string simple_name = CLI::detail::split(option_name, ',').at(0);
|
||||
CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
|
||||
@ -699,10 +700,10 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore case (default, R value)
|
||||
/// Add set of options, string only, ignore case (default, static set)
|
||||
Option *add_set_ignore_case(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &&options, ///< The set of possibilities
|
||||
std::string &member, ///< The selected member of the set
|
||||
std::set<std::string> options, ///< The set of possibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
|
||||
@ -730,12 +731,12 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore case (default, L value)
|
||||
Option *add_set_ignore_case(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &options, ///< The set of possibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
/// Add set of options, string only, ignore case (default, set can be changed afterwards - do not destroy the set)
|
||||
Option *add_mutable_set_ignore_case(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &options, ///< The set of possibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
|
||||
std::string simple_name = CLI::detail::split(option_name, ',').at(0);
|
||||
CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
|
||||
@ -761,10 +762,10 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore underscore (no default, R value)
|
||||
/// Add set of options, string only, ignore underscore (no default, static set)
|
||||
Option *add_set_ignore_underscore(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &&options, ///< The set of possibilities
|
||||
std::string &member, ///< The selected member of the set
|
||||
std::set<std::string> options, ///< The set of possibilities
|
||||
std::string description = "") {
|
||||
|
||||
std::string simple_name = CLI::detail::split(option_name, ',').at(0);
|
||||
@ -789,11 +790,12 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore underscore (no default, L value)
|
||||
Option *add_set_ignore_underscore(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &options, ///< The set of possibilities
|
||||
std::string description = "") {
|
||||
/// Add set of options, string only, ignore underscore (no default, set can be changed afterwards - do not destroy
|
||||
/// the set)
|
||||
Option *add_mutable_set_ignore_underscore(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &options, ///< The set of possibilities
|
||||
std::string description = "") {
|
||||
|
||||
std::string simple_name = CLI::detail::split(option_name, ',').at(0);
|
||||
CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
|
||||
@ -817,10 +819,10 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore underscore (default, R value)
|
||||
/// Add set of options, string only, ignore underscore (default, static set)
|
||||
Option *add_set_ignore_underscore(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &&options, ///< The set of possibilities
|
||||
std::string &member, ///< The selected member of the set
|
||||
std::set<std::string> options, ///< The set of possibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
|
||||
@ -848,12 +850,13 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore underscore (default, L value)
|
||||
Option *add_set_ignore_underscore(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &options, ///< The set of possibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
/// Add set of options, string only, ignore underscore (default, set can be changed afterwards - do not destroy the
|
||||
/// set)
|
||||
Option *add_mutable_set_ignore_underscore(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &options, ///< The set of possibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
|
||||
std::string simple_name = CLI::detail::split(option_name, ',').at(0);
|
||||
CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
|
||||
@ -879,10 +882,10 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore underscore and case(no default, R value)
|
||||
/// Add set of options, string only, ignore underscore and case (no default, static set)
|
||||
Option *add_set_ignore_case_underscore(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &&options, ///< The set of possibilities
|
||||
std::string &member, ///< The selected member of the set
|
||||
std::set<std::string> options, ///< The set of possibilities
|
||||
std::string description = "") {
|
||||
|
||||
std::string simple_name = CLI::detail::split(option_name, ',').at(0);
|
||||
@ -907,11 +910,12 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore underscore and case(no default, L value)
|
||||
Option *add_set_ignore_case_underscore(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &options, ///< The set of possibilities
|
||||
std::string description = "") {
|
||||
/// Add set of options, string only, ignore underscore and case (no default, set can be changed afterwards - do not
|
||||
/// destroy the set)
|
||||
Option *add_mutable_set_ignore_case_underscore(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &options, ///< The set of possibilities
|
||||
std::string description = "") {
|
||||
|
||||
std::string simple_name = CLI::detail::split(option_name, ',').at(0);
|
||||
CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
|
||||
@ -935,10 +939,10 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore underscore and case (default, R value)
|
||||
/// Add set of options, string only, ignore underscore and case (default, static set)
|
||||
Option *add_set_ignore_case_underscore(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &&options, ///< The set of possibilities
|
||||
std::string &member, ///< The selected member of the set
|
||||
std::set<std::string> options, ///< The set of possibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
|
||||
@ -966,12 +970,13 @@ class App {
|
||||
return opt;
|
||||
}
|
||||
|
||||
/// Add set of options, string only, ignore underscore and case (default, L value)
|
||||
Option *add_set_ignore_case_underscore(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &options, ///< The set of possibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
/// Add set of options, string only, ignore underscore and case (default, set can be changed afterwards - do not
|
||||
/// destroy the set)
|
||||
Option *add_mutable_set_ignore_case_underscore(std::string option_name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
const std::set<std::string> &options, ///< The set of possibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
|
||||
std::string simple_name = CLI::detail::split(option_name, ',').at(0);
|
||||
CLI::callback_t fun = [&member, &options, simple_name](CLI::results_t res) {
|
||||
|
@ -1168,12 +1168,12 @@ TEST_F(TApp, FailSet) {
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
}
|
||||
|
||||
TEST_F(TApp, FailLValueSet) {
|
||||
TEST_F(TApp, FailMutableSet) {
|
||||
|
||||
int choice;
|
||||
std::set<int> vals{1, 2, 3};
|
||||
app.add_set("-q,--quick", choice, vals);
|
||||
app.add_set("-s,--slow", choice, vals, "", true);
|
||||
app.add_mutable_set("-q,--quick", choice, vals);
|
||||
app.add_mutable_set("-s,--slow", choice, vals, "", true);
|
||||
|
||||
args = {"--quick=hello"};
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
@ -1206,12 +1206,11 @@ TEST_F(TApp, InSetIgnoreCase) {
|
||||
EXPECT_THROW(run(), CLI::ArgumentMismatch);
|
||||
}
|
||||
|
||||
/*
|
||||
TEST_F(TApp, InSetIgnoreCaseLValue) {
|
||||
TEST_F(TApp, InSetIgnoreCaseMutableValue) {
|
||||
|
||||
std::set<std::string> options{"one", "Two", "THREE"};
|
||||
std::string choice;
|
||||
app.add_set_ignore_case("-q,--quick", choice, options);
|
||||
app.add_mutable_set_ignore_case("-q,--quick", choice, options);
|
||||
|
||||
args = {"--quick", "One"};
|
||||
run();
|
||||
@ -1227,14 +1226,7 @@ TEST_F(TApp, InSetIgnoreCaseLValue) {
|
||||
|
||||
options.clear();
|
||||
args = {"--quick", "ThrEE"};
|
||||
run();
|
||||
EXPECT_EQ("THREE", choice); // this will now fail since options was cleared
|
||||
|
||||
args = {"--quick", "four"};
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
|
||||
args = {"--quick=one", "--quick=two"};
|
||||
EXPECT_THROW(run(), CLI::ArgumentMismatch);
|
||||
}
|
||||
|
||||
TEST_F(TApp, InSetIgnoreCasePointer) {
|
||||
@ -1258,7 +1250,7 @@ TEST_F(TApp, InSetIgnoreCasePointer) {
|
||||
delete options;
|
||||
args = {"--quick", "ThrEE"};
|
||||
run();
|
||||
EXPECT_EQ("THREE", choice); // this could cause a seg fault
|
||||
EXPECT_EQ("THREE", choice); // this does not throw a segfault
|
||||
|
||||
args = {"--quick", "four"};
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
@ -1266,7 +1258,7 @@ TEST_F(TApp, InSetIgnoreCasePointer) {
|
||||
args = {"--quick=one", "--quick=two"};
|
||||
EXPECT_THROW(run(), CLI::ArgumentMismatch);
|
||||
}
|
||||
*/
|
||||
|
||||
TEST_F(TApp, InSetIgnoreUnderscore) {
|
||||
|
||||
std::string choice;
|
||||
@ -1765,8 +1757,8 @@ TEST_F(TApp, AddRemoveSetItems) {
|
||||
std::set<std::string> items{"TYPE1", "TYPE2", "TYPE3", "TYPE4", "TYPE5"};
|
||||
|
||||
std::string type1, type2;
|
||||
app.add_set("--type1", type1, items);
|
||||
app.add_set("--type2", type2, items, "", true);
|
||||
app.add_mutable_set("--type1", type1, items);
|
||||
app.add_mutable_set("--type2", type2, items, "", true);
|
||||
|
||||
args = {"--type1", "TYPE1", "--type2", "TYPE2"};
|
||||
|
||||
@ -1796,8 +1788,8 @@ TEST_F(TApp, AddRemoveSetItemsNoCase) {
|
||||
std::set<std::string> items{"TYPE1", "TYPE2", "TYPE3", "TYPE4", "TYPE5"};
|
||||
|
||||
std::string type1, type2;
|
||||
app.add_set_ignore_case("--type1", type1, items);
|
||||
app.add_set_ignore_case("--type2", type2, items, "", true);
|
||||
app.add_mutable_set_ignore_case("--type1", type1, items);
|
||||
app.add_mutable_set_ignore_case("--type2", type2, items, "", true);
|
||||
|
||||
args = {"--type1", "TYPe1", "--type2", "TyPE2"};
|
||||
|
||||
|
@ -795,7 +795,7 @@ TEST(THelp, ChangingSet) {
|
||||
|
||||
std::set<int> vals{1, 2, 3};
|
||||
int val;
|
||||
app.add_set("--val", val, vals);
|
||||
app.add_mutable_set("--val", val, vals);
|
||||
|
||||
std::string help = app.help();
|
||||
|
||||
@ -816,7 +816,7 @@ TEST(THelp, ChangingSetDefaulted) {
|
||||
|
||||
std::set<int> vals{1, 2, 3};
|
||||
int val = 2;
|
||||
app.add_set("--val", val, vals, "", true);
|
||||
app.add_mutable_set("--val", val, vals, "", true);
|
||||
|
||||
std::string help = app.help();
|
||||
|
||||
@ -836,7 +836,7 @@ TEST(THelp, ChangingCaselessSet) {
|
||||
|
||||
std::set<std::string> vals{"1", "2", "3"};
|
||||
std::string val;
|
||||
app.add_set_ignore_case("--val", val, vals);
|
||||
app.add_mutable_set_ignore_case("--val", val, vals);
|
||||
|
||||
std::string help = app.help();
|
||||
|
||||
@ -857,7 +857,7 @@ TEST(THelp, ChangingCaselessSetDefaulted) {
|
||||
|
||||
std::set<std::string> vals{"1", "2", "3"};
|
||||
std::string val = "2";
|
||||
app.add_set_ignore_case("--val", val, vals, "", true);
|
||||
app.add_mutable_set_ignore_case("--val", val, vals, "", true);
|
||||
|
||||
std::string help = app.help();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user