Skip to content

Commit

Permalink
refactor!: drop defaulted from add_option
Browse files Browse the repository at this point in the history
  • Loading branch information
henryiii committed Jun 15, 2021
1 parent ac74dac commit 3b0ec40
Show file tree
Hide file tree
Showing 13 changed files with 46 additions and 248 deletions.
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@
* Bugfix: avoid listing helpall as a required flag [#530][]
* Bugfix: avoid a clash with WINDOWS define [#563][]

* Removed deprecated set commands, use validators instead. [#565][]

* Build: support pkg-config [#523][]

#### Converting from CLI11 1.9:

* Removed deprecated set commands, use validators instead. [#565][]
* The final "defaulted" bool has been removed, use `->capture_default_str()`
instead. Use `app.option_defaults()->always_capture_default()` to set this for
all future options. [#597][]


[#435]: https://github.com/CLIUtils/CLI11/pull/435
[#443]: https://github.com/CLIUtils/CLI11/pull/443
Expand All @@ -35,6 +40,7 @@
[#563]: https://github.com/CLIUtils/CLI11/pull/563
[#565]: https://github.com/CLIUtils/CLI11/pull/565
[#574]: https://github.com/CLIUtils/CLI11/pull/574
[#597]: https://github.com/CLIUtils/CLI11/pull/597



Expand Down
4 changes: 2 additions & 2 deletions book/chapters/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ int int_option{0};
app.add_option("-i", int_option, "Optional description");
```
This will bind the option `-i` to the integer `int_option`. On the command line, a single value that can be converted to an integer will be expected. Non-integer results will fail. If that option is not given, CLI11 will not touch the initial value. This allows you to set up defaults by simply setting your value beforehand. If you want CLI11 to display your default value, you can add the optional final argument `true` when you add the option.
This will bind the option `-i` to the integer `int_option`. On the command line, a single value that can be converted to an integer will be expected. Non-integer results will fail. If that option is not given, CLI11 will not touch the initial value. This allows you to set up defaults by simply setting your value beforehand. If you want CLI11 to display your default value, you can add `->capture_default_str()` after the option.
```cpp
int int_option{0};
app.add_option("-i", int_option, "Optional description", true);
app.add_option("-i", int_option, "Optional description")->capture_default_str();
```

You can use any C++ int-like type, not just `int`. CLI11 understands the following categories of types:
Expand Down
4 changes: 3 additions & 1 deletion examples/nested.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ int main(int argc, char **argv) {

std::string mvcamera_config_file = "mvcamera_config.json";
CLI::App *mvcameraApp = cameraApp->add_subcommand("mvcamera", "MatrixVision Camera Configuration");
mvcameraApp->add_option("-c,--config", mvcamera_config_file, "Config filename", true)->check(CLI::ExistingFile);
mvcameraApp->add_option("-c,--config", mvcamera_config_file, "Config filename")
->capture_default_str()
->check(CLI::ExistingFile);

std::string mock_camera_path;
CLI::App *mockcameraApp = cameraApp->add_subcommand("mock", "Mock Camera Configuration");
Expand Down
2 changes: 1 addition & 1 deletion examples/ranges.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ int main(int argc, char **argv) {
int min{0}, max{0}, step{1};
ogroup->add_option("--min,-m", min, "The minimum")->required();
ogroup->add_option("--max,-M", max, "The maximum")->required();
ogroup->add_option("--step,-s", step, "The step", true);
ogroup->add_option("--step,-s", step, "The step")->capture_default_str();

app.require_option(1);

Expand Down
5 changes: 2 additions & 3 deletions include/CLI/App.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,14 +611,13 @@ class App {
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
std::string option_description = "",
bool defaulted = false) {
std::string option_description = "") {

auto fun = [&variable](const CLI::results_t &res) { // comment for spacing
return detail::lexical_conversion<AssignTo, ConvertTo>(res, variable);
};

Option *opt = add_option(option_name, fun, option_description, defaulted, [&variable]() {
Option *opt = add_option(option_name, fun, option_description, false, [&variable]() {
return CLI::detail::checked_to_string<AssignTo, ConvertTo>(variable);
});
opt->type_name(detail::type_name<ConvertTo>());
Expand Down
2 changes: 1 addition & 1 deletion tests/AppTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2219,7 +2219,7 @@ TEST_CASE_METHOD(TApp, "CustomUserSepParse3", "[app]") {
CHECK(std::vector<int>({1, 2}) == vals);
app.remove_option(opt);

app.add_option("--idx", vals, "", false)->delimiter(',');
app.add_option("--idx", vals)->delimiter(',');
run();
CHECK(std::vector<int>({1, 2}) == vals);
}
Expand Down
20 changes: 10 additions & 10 deletions tests/ConfigFileTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1685,7 +1685,7 @@ TEST_CASE_METHOD(TApp, "TomlOutputHiddenOptions", "[config]") {
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.add_option("--dval", val)->capture_default_str()->group("");

run();

Expand Down Expand Up @@ -1723,7 +1723,7 @@ TEST_CASE_METHOD(TApp, "TomlOutputOptionGroup", "[config]") {
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("");
og->add_option("--dval", val)->capture_default_str()->group("");

run();

Expand Down Expand Up @@ -1809,7 +1809,7 @@ TEST_CASE_METHOD(TApp, "TomlOutputSet", "[config]") {
TEST_CASE_METHOD(TApp, "TomlOutputDefault", "[config]") {

int v{7};
app.add_option("--simple", v, "", true);
app.add_option("--simple", v)->capture_default_str();

run();

Expand Down Expand Up @@ -1934,10 +1934,10 @@ TEST_CASE_METHOD(TApp, "TomlOutputQuoted", "[config]") {
TEST_CASE_METHOD(TApp, "DefaultsTomlOutputQuoted", "[config]") {

std::string val1{"I am a string"};
app.add_option("--val1", val1, "", true);
app.add_option("--val1", val1)->capture_default_str();

std::string val2{R"(I am a "confusing" string)"};
app.add_option("--val2", val2, "", true);
app.add_option("--val2", val2)->capture_default_str();

run();

Expand Down Expand Up @@ -2068,7 +2068,7 @@ TEST_CASE_METHOD(TApp, "IniOutputHiddenOptions", "[config]") {
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.add_option("--dval", val)->capture_default_str()->group("");
app.config_formatter(std::make_shared<CLI::ConfigINI>());
run();

Expand Down Expand Up @@ -2106,7 +2106,7 @@ TEST_CASE_METHOD(TApp, "IniOutputOptionGroup", "[config]") {
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("");
og->add_option("--dval", val)->capture_default_str()->group("");
app.config_formatter(std::make_shared<CLI::ConfigINI>());
run();

Expand Down Expand Up @@ -2177,7 +2177,7 @@ TEST_CASE_METHOD(TApp, "IniOutputSet", "[config]") {
TEST_CASE_METHOD(TApp, "IniOutputDefault", "[config]") {

int v{7};
app.add_option("--simple", v, "", true);
app.add_option("--simple", v)->capture_default_str();
app.config_formatter(std::make_shared<CLI::ConfigINI>());
run();

Expand Down Expand Up @@ -2302,10 +2302,10 @@ TEST_CASE_METHOD(TApp, "IniOutputQuoted", "[config]") {
TEST_CASE_METHOD(TApp, "DefaultsIniOutputQuoted", "[config]") {

std::string val1{"I am a string"};
app.add_option("--val1", val1, "", true);
app.add_option("--val1", val1)->capture_default_str();

std::string val2{R"(I am a "confusing" string)"};
app.add_option("--val2", val2, "", true);
app.add_option("--val2", val2)->capture_default_str();
app.config_formatter(std::make_shared<CLI::ConfigINI>());
run();

Expand Down
4 changes: 2 additions & 2 deletions tests/CreationTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -739,13 +739,13 @@ TEST_CASE_METHOD(TApp, "MakeUnstreamableOptions", "[creation]") {
app.add_option("--value", value);

// This used to fail to build, since it tries to stream from Unstreamable
app.add_option("--value2", value, "", false);
app.add_option("--value2", value);

std::vector<Unstreamable> values;
app.add_option("--values", values);

// This used to fail to build, since it tries to stream from Unstreamable
app.add_option("--values2", values, "", false);
app.add_option("--values2", values);

args = {"--value", "45"};
run();
Expand Down
211 changes: 0 additions & 211 deletions tests/DeprecatedTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,214 +12,3 @@ TEST_CASE("Deprecated: Empty", "[deprecated]") {
// No deprecated features at this time.
CHECK(true);
}

// Classic sets

TEST_CASE("THelp: Defaults", "[deprecated]") {
CLI::App app{"My prog"};

int one{1}, two{2};
app.add_option("--one", one, "Help for one", true);
app.add_option("--set", two, "Help for set", true)->check(CLI::IsMember({2, 3, 4}));

std::string help = app.help();

CHECK_THAT(help, Contains("--one"));
CHECK_THAT(help, Contains("--set"));
CHECK_THAT(help, Contains("1"));
CHECK_THAT(help, Contains("=2"));
CHECK_THAT(help, Contains("2,3,4"));
}

TEST_CASE("THelp: VectorOpts", "[deprecated]") {
CLI::App app{"My prog"};
std::vector<int> x = {1, 2};
app.add_option("-q,--quick", x, "", true);

std::string help = app.help();

CHECK_THAT(help, Contains("INT=[1,2] ..."));
}

TEST_CASE("THelp: SetLower", "[deprecated]") {
CLI::App app{"My prog"};

std::string def{"One"};
app.add_option("--set", def, "Help for set", true)->check(CLI::IsMember({"oNe", "twO", "THREE"}));

std::string help = app.help();

CHECK_THAT(help, Contains("--set"));
CHECK_THAT(help, Contains("=One"));
CHECK_THAT(help, Contains("oNe"));
CHECK_THAT(help, Contains("twO"));
CHECK_THAT(help, Contains("THREE"));
}

TEST_CASE("THelp: ChangingSetDefaulted", "[deprecated]") {
CLI::App app;

std::set<int> vals{1, 2, 3};
int val = 2;
app.add_option("--val", val, "", true)->check(CLI::IsMember(&vals));

std::string help = app.help();

CHECK_THAT(help, Contains("1"));
CHECK_THAT(help, !Contains("4"));

vals.insert(4);
vals.erase(1);

help = app.help();

CHECK_THAT(help, !Contains("1"));
CHECK_THAT(help, Contains("4"));
}

TEST_CASE("THelp: ChangingCaselessSetDefaulted", "[deprecated]") {
CLI::App app;

std::set<std::string> vals{"1", "2", "3"};
std::string val = "2";
app.add_option("--val", val, "", true)->check(CLI::IsMember(&vals, CLI::ignore_case));

std::string help = app.help();

CHECK_THAT(help, Contains("1"));
CHECK_THAT(help, !Contains("4"));

vals.insert("4");
vals.erase("1");

help = app.help();

CHECK_THAT(help, !Contains("1"));
CHECK_THAT(help, Contains("4"));
}

TEST_CASE_METHOD(TApp, "DefaultOpts", "[deprecated]") {

int i = 3;
std::string s = "HI";

app.add_option("-i,i", i, "", false);
app.add_option("-s,s", s, "", true);

args = {"-i2", "9"};

run();

CHECK(app.count("i") == 1u);
CHECK(app.count("-s") == 1u);
CHECK(i == 2);
CHECK(s == "9");
}

TEST_CASE_METHOD(TApp, "VectorDefaultedFixedString", "[deprecated]") {
std::vector<std::string> strvec{"one"};
std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};

CLI::Option *opt = app.add_option("-s,--string", strvec, "", true)->expected(3);
CHECK(opt->get_expected() == 3);

args = {"--string", "mystring", "mystring2", "mystring3"};
run();
CHECK(app.count("--string") == 3u);
CHECK(strvec == answer);
}

TEST_CASE_METHOD(TApp, "DefaultedResult", "[deprecated]") {
std::string sval = "NA";
int ival;
auto opts = app.add_option("--string", sval, "", true);
auto optv = app.add_option("--val", ival);
args = {};
run();
CHECK("NA" == sval);
std::string nString;
opts->results(nString);
CHECK("NA" == nString);
int newIval;
// CHECK_THROWS_AS (optv->results(newIval), CLI::ConversionError);
optv->default_str("442");
optv->results(newIval);
CHECK(442 == newIval);
}

TEST_CASE_METHOD(TApp, "OptionWithDefaults", "[deprecated]") {
int someint = 2;
app.add_option("-a", someint, "", true);

args = {"-a1", "-a2"};

CHECK_THROWS_AS(run(), CLI::ArgumentMismatch);
}

// #209
TEST_CASE_METHOD(TApp, "CustomUserSepParse", "[deprecated]") {

std::vector<int> vals = {1, 2, 3};
args = {"--idx", "1,2,3"};
auto opt = app.add_option("--idx", vals)->delimiter(',');
run();
CHECK(std::vector<int>({1, 2, 3}) == vals);
std::vector<int> vals2;
// check that the results vector gets the results in the same way
opt->results(vals2);
CHECK(vals == vals2);

app.remove_option(opt);

app.add_option("--idx", vals, "", true)->delimiter(',');
run();
CHECK(std::vector<int>({1, 2, 3}) == vals);
}

// #209
TEST_CASE_METHOD(TApp, "CustomUserSepParse2", "[deprecated]") {

std::vector<int> vals = {1, 2, 3};
args = {"--idx", "1,2,"};
auto opt = app.add_option("--idx", vals)->delimiter(',');
run();
CHECK(std::vector<int>({1, 2}) == vals);

app.remove_option(opt);

app.add_option("--idx", vals, "", true)->delimiter(',');
run();
CHECK(std::vector<int>({1, 2}) == vals);
}
//
// #209
TEST_CASE_METHOD(TApp, "CustomUserSepParse4", "[deprecated]") {

std::vector<int> vals;
args = {"--idx", "1, 2"};
auto opt = app.add_option("--idx", vals, "", true)->delimiter(',');
run();
CHECK(std::vector<int>({1, 2}) == vals);

app.remove_option(opt);

app.add_option("--idx", vals)->delimiter(',');
run();
CHECK(std::vector<int>({1, 2}) == vals);
}

// #218
TEST_CASE_METHOD(TApp, "CustomUserSepParse5", "[deprecated]") {

std::vector<std::string> bar;
args = {"this", "is", "a", "test"};
auto opt = app.add_option("bar", bar, "bar");
run();
CHECK(std::vector<std::string>({"this", "is", "a", "test"}) == bar);

app.remove_option(opt);
args = {"this", "is", "a", "test"};
app.add_option("bar", bar, "bar", true);
run();
CHECK(std::vector<std::string>({"this", "is", "a", "test"}) == bar);
}
Loading

0 comments on commit 3b0ec40

Please sign in to comment.