Commit 3c73d91c0b04e2b59462f0a741be8c07024c1bc0

Authored by Bartek
Committed by jarro2783
1 parent e6858d34

add_options variant with initializer list (#189)

Allow adding options with a single initializer list.
include/cxxopts.hpp
... ... @@ -1220,6 +1220,28 @@ namespace cxxopts
1220 1220  
1221 1221 std::vector<KeyValue> m_sequential;
1222 1222 };
  1223 +
  1224 + struct Option
  1225 + {
  1226 + Option
  1227 + (
  1228 + const std::string& opts,
  1229 + const std::string& desc,
  1230 + const std::shared_ptr<const Value>& value = ::cxxopts::value<bool>(),
  1231 + const std::string& arg_help = ""
  1232 + )
  1233 + : opts_(opts)
  1234 + , desc_(desc)
  1235 + , value_(value)
  1236 + , arg_help_(arg_help)
  1237 + {
  1238 + }
  1239 +
  1240 + std::string opts_;
  1241 + std::string desc_;
  1242 + std::shared_ptr<const Value> value_;
  1243 + std::string arg_help_;
  1244 + };
1223 1245  
1224 1246 class Options
1225 1247 {
... ... @@ -1272,6 +1294,20 @@ namespace cxxopts
1272 1294  
1273 1295 OptionAdder
1274 1296 add_options(std::string group = "");
  1297 +
  1298 + void
  1299 + add_options
  1300 + (
  1301 + const std::string& group,
  1302 + std::initializer_list<Option> options
  1303 + );
  1304 +
  1305 + void
  1306 + add_option
  1307 + (
  1308 + const std::string& group,
  1309 + const Option& option
  1310 + );
1275 1311  
1276 1312 void
1277 1313 add_option
... ... @@ -1512,6 +1548,21 @@ ParseResult::ParseResult
1512 1548 }
1513 1549  
1514 1550 inline
  1551 +void
  1552 +Options::add_options
  1553 +(
  1554 + const std::string &group,
  1555 + std::initializer_list<Option> options
  1556 +)
  1557 +{
  1558 + OptionAdder option_adder(*this, group);
  1559 + for (const auto &option: options)
  1560 + {
  1561 + option_adder(option.opts_, option.desc_, option.value_, option.arg_help_);
  1562 + }
  1563 +}
  1564 +
  1565 +inline
1515 1566 OptionAdder
1516 1567 Options::add_options(std::string group)
1517 1568 {
... ... @@ -1890,6 +1941,17 @@ void
1890 1941 Options::add_option
1891 1942 (
1892 1943 const std::string& group,
  1944 + const Option& option
  1945 +)
  1946 +{
  1947 + add_options(group, {option});
  1948 +}
  1949 +
  1950 +inline
  1951 +void
  1952 +Options::add_option
  1953 +(
  1954 + const std::string& group,
1893 1955 const std::string& s,
1894 1956 const std::string& l,
1895 1957 std::string desc,
... ...
test/options.cpp
... ... @@ -93,7 +93,7 @@ TEST_CASE(&quot;Basic options&quot;, &quot;[options]&quot;)
93 93 CHECK(arguments[1].key() == "short");
94 94 CHECK(arguments[2].key() == "value");
95 95 CHECK(arguments[3].key() == "av");
96   -
  96 +
97 97 CHECK_THROWS_AS(result["nothing"].as<std::string>(), std::domain_error&);
98 98 }
99 99  
... ... @@ -684,3 +684,86 @@ TEST_CASE(&quot;Invalid option syntax&quot;, &quot;[options]&quot;) {
684 684 CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_syntax_exception&);
685 685 }
686 686 }
  687 +
  688 +TEST_CASE("Options empty", "[options]") {
  689 + cxxopts::Options options("Options list empty", " - test empty option list");
  690 + options.add_options();
  691 + options.add_options("");
  692 + options.add_options("", {});
  693 + options.add_options("test");
  694 +
  695 + Argv argv_({
  696 + "test",
  697 + "--unknown"
  698 + });
  699 + auto argc = argv_.argc();
  700 + char** argv = argv_.argv();
  701 +
  702 + CHECK(options.groups().empty());
  703 + CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception&);
  704 +}
  705 +
  706 +TEST_CASE("Initializer list with group", "[options]") {
  707 + cxxopts::Options options("Initializer list group", " - test initializer list with group");
  708 +
  709 + options.add_options("", {
  710 + {"a, address", "server address", cxxopts::value<std::string>()->default_value("127.0.0.1")},
  711 + {"p, port", "server port", cxxopts::value<std::string>()->default_value("7110"), "PORT"},
  712 + });
  713 +
  714 + cxxopts::Option help{"h,help", "Help"};
  715 +
  716 + options.add_options("TEST_GROUP", {
  717 + {"t, test", "test option"},
  718 + help
  719 + });
  720 +
  721 + Argv argv({
  722 + "test",
  723 + "--address",
  724 + "10.0.0.1",
  725 + "-p",
  726 + "8000",
  727 + "-t",
  728 + });
  729 + char** actual_argv = argv.argv();
  730 + auto argc = argv.argc();
  731 + auto result = options.parse(argc, actual_argv);
  732 +
  733 + CHECK(options.groups().size() == 2);
  734 + CHECK(result.count("address") == 1);
  735 + CHECK(result.count("port") == 1);
  736 + CHECK(result.count("test") == 1);
  737 + CHECK(result.count("help") == 0);
  738 + CHECK(result["address"].as<std::string>() == "10.0.0.1");
  739 + CHECK(result["port"].as<std::string>() == "8000");
  740 + CHECK(result["test"].as<bool>() == true);
  741 +}
  742 +
  743 +TEST_CASE("Option add with add_option(string, Option)", "[options]") {
  744 + cxxopts::Options options("Option add with add_option", " - test Option add with add_option(string, Option)");
  745 +
  746 + cxxopts::Option option_1("t,test", "test option", cxxopts::value<int>()->default_value("7"), "TEST");
  747 +
  748 + options.add_option("", option_1);
  749 + options.add_option("TEST", {"a,aggregate", "test option 2", cxxopts::value<int>(), "AGGREGATE"});
  750 +
  751 + Argv argv_({
  752 + "test",
  753 + "--test",
  754 + "5",
  755 + "-a",
  756 + "4"
  757 + });
  758 + auto argc = argv_.argc();
  759 + char** argv = argv_.argv();
  760 + auto result = options.parse(argc, argv);
  761 +
  762 + CHECK(result.arguments().size()==2);
  763 + CHECK(options.groups().size() == 2);
  764 + CHECK(result.count("address") == 0);
  765 + CHECK(result.count("aggregate") == 1);
  766 + CHECK(result.count("test") == 1);
  767 + CHECK(result["aggregate"].as<int>() == 4);
  768 + CHECK(result["test"].as<int>() == 5);
  769 +}
... ...