add_options variant with initializer list (#189)

Allow adding options with a single initializer list.
This commit is contained in:
Bartek 2019-06-28 00:39:37 +02:00 committed by jarro2783
parent e6858d3429
commit 3c73d91c0b
2 changed files with 146 additions and 1 deletions

View File

@ -1220,6 +1220,28 @@ namespace cxxopts
std::vector<KeyValue> m_sequential;
};
struct Option
{
Option
(
const std::string& opts,
const std::string& desc,
const std::shared_ptr<const Value>& value = ::cxxopts::value<bool>(),
const std::string& arg_help = ""
)
: opts_(opts)
, desc_(desc)
, value_(value)
, arg_help_(arg_help)
{
}
std::string opts_;
std::string desc_;
std::shared_ptr<const Value> value_;
std::string arg_help_;
};
class Options
{
@ -1272,6 +1294,20 @@ namespace cxxopts
OptionAdder
add_options(std::string group = "");
void
add_options
(
const std::string& group,
std::initializer_list<Option> options
);
void
add_option
(
const std::string& group,
const Option& option
);
void
add_option
@ -1511,6 +1547,21 @@ ParseResult::ParseResult
parse(argc, argv);
}
inline
void
Options::add_options
(
const std::string &group,
std::initializer_list<Option> options
)
{
OptionAdder option_adder(*this, group);
for (const auto &option: options)
{
option_adder(option.opts_, option.desc_, option.value_, option.arg_help_);
}
}
inline
OptionAdder
Options::add_options(std::string group)
@ -1885,6 +1936,17 @@ ParseResult::parse(int& argc, char**& argv)
}
inline
void
Options::add_option
(
const std::string& group,
const Option& option
)
{
add_options(group, {option});
}
inline
void
Options::add_option

View File

@ -93,7 +93,7 @@ TEST_CASE("Basic options", "[options]")
CHECK(arguments[1].key() == "short");
CHECK(arguments[2].key() == "value");
CHECK(arguments[3].key() == "av");
CHECK_THROWS_AS(result["nothing"].as<std::string>(), std::domain_error&);
}
@ -684,3 +684,86 @@ TEST_CASE("Invalid option syntax", "[options]") {
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_syntax_exception&);
}
}
TEST_CASE("Options empty", "[options]") {
cxxopts::Options options("Options list empty", " - test empty option list");
options.add_options();
options.add_options("");
options.add_options("", {});
options.add_options("test");
Argv argv_({
"test",
"--unknown"
});
auto argc = argv_.argc();
char** argv = argv_.argv();
CHECK(options.groups().empty());
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception&);
}
TEST_CASE("Initializer list with group", "[options]") {
cxxopts::Options options("Initializer list group", " - test initializer list with group");
options.add_options("", {
{"a, address", "server address", cxxopts::value<std::string>()->default_value("127.0.0.1")},
{"p, port", "server port", cxxopts::value<std::string>()->default_value("7110"), "PORT"},
});
cxxopts::Option help{"h,help", "Help"};
options.add_options("TEST_GROUP", {
{"t, test", "test option"},
help
});
Argv argv({
"test",
"--address",
"10.0.0.1",
"-p",
"8000",
"-t",
});
char** actual_argv = argv.argv();
auto argc = argv.argc();
auto result = options.parse(argc, actual_argv);
CHECK(options.groups().size() == 2);
CHECK(result.count("address") == 1);
CHECK(result.count("port") == 1);
CHECK(result.count("test") == 1);
CHECK(result.count("help") == 0);
CHECK(result["address"].as<std::string>() == "10.0.0.1");
CHECK(result["port"].as<std::string>() == "8000");
CHECK(result["test"].as<bool>() == true);
}
TEST_CASE("Option add with add_option(string, Option)", "[options]") {
cxxopts::Options options("Option add with add_option", " - test Option add with add_option(string, Option)");
cxxopts::Option option_1("t,test", "test option", cxxopts::value<int>()->default_value("7"), "TEST");
options.add_option("", option_1);
options.add_option("TEST", {"a,aggregate", "test option 2", cxxopts::value<int>(), "AGGREGATE"});
Argv argv_({
"test",
"--test",
"5",
"-a",
"4"
});
auto argc = argv_.argc();
char** argv = argv_.argv();
auto result = options.parse(argc, argv);
CHECK(result.arguments().size()==2);
CHECK(options.groups().size() == 2);
CHECK(result.count("address") == 0);
CHECK(result.count("aggregate") == 1);
CHECK(result.count("test") == 1);
CHECK(result["aggregate"].as<int>() == 4);
CHECK(result["test"].as<int>() == 5);
}