Allow unrecognised options. (#105)
Allows unrecognised options to be left alone by the parser without throwing an exception.
This commit is contained in:
parent
00e8ecc482
commit
ca6e9f70eb
@ -1095,6 +1095,7 @@ namespace cxxopts
|
|||||||
ParseResult(
|
ParseResult(
|
||||||
const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>&,
|
const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>&,
|
||||||
std::vector<std::string>,
|
std::vector<std::string>,
|
||||||
|
bool allow_unrecognised,
|
||||||
int&, char**&);
|
int&, char**&);
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
@ -1174,6 +1175,8 @@ namespace cxxopts
|
|||||||
std::unordered_set<std::string> m_positional_set;
|
std::unordered_set<std::string> m_positional_set;
|
||||||
std::unordered_map<std::shared_ptr<OptionDetails>, OptionValue> m_results;
|
std::unordered_map<std::shared_ptr<OptionDetails>, OptionValue> m_results;
|
||||||
|
|
||||||
|
bool m_allow_unrecognised;
|
||||||
|
|
||||||
std::vector<KeyValue> m_sequential;
|
std::vector<KeyValue> m_sequential;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1187,6 +1190,7 @@ namespace cxxopts
|
|||||||
, m_custom_help("[OPTION...]")
|
, m_custom_help("[OPTION...]")
|
||||||
, m_positional_help("positional parameters")
|
, m_positional_help("positional parameters")
|
||||||
, m_show_positional(false)
|
, m_show_positional(false)
|
||||||
|
, m_allow_unrecognised(false)
|
||||||
, m_next_positional(m_positional.end())
|
, m_next_positional(m_positional.end())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -1212,6 +1216,13 @@ namespace cxxopts
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Options&
|
||||||
|
allow_unrecognised_options()
|
||||||
|
{
|
||||||
|
m_allow_unrecognised = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
ParseResult
|
ParseResult
|
||||||
parse(int& argc, char**& argv);
|
parse(int& argc, char**& argv);
|
||||||
|
|
||||||
@ -1275,6 +1286,7 @@ namespace cxxopts
|
|||||||
std::string m_custom_help;
|
std::string m_custom_help;
|
||||||
std::string m_positional_help;
|
std::string m_positional_help;
|
||||||
bool m_show_positional;
|
bool m_show_positional;
|
||||||
|
bool m_allow_unrecognised;
|
||||||
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<OptionDetails>> m_options;
|
std::unordered_map<std::string, std::shared_ptr<OptionDetails>> m_options;
|
||||||
std::vector<std::string> m_positional;
|
std::vector<std::string> m_positional;
|
||||||
@ -1431,11 +1443,13 @@ ParseResult::ParseResult
|
|||||||
(
|
(
|
||||||
const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>& options,
|
const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>& options,
|
||||||
std::vector<std::string> positional,
|
std::vector<std::string> positional,
|
||||||
|
bool allow_unrecognised,
|
||||||
int& argc, char**& argv
|
int& argc, char**& argv
|
||||||
)
|
)
|
||||||
: m_options(options)
|
: m_options(options)
|
||||||
, m_positional(std::move(positional))
|
, m_positional(std::move(positional))
|
||||||
, m_next_positional(m_positional.begin())
|
, m_next_positional(m_positional.begin())
|
||||||
|
, m_allow_unrecognised(allow_unrecognised)
|
||||||
{
|
{
|
||||||
parse(argc, argv);
|
parse(argc, argv);
|
||||||
}
|
}
|
||||||
@ -1641,7 +1655,7 @@ inline
|
|||||||
ParseResult
|
ParseResult
|
||||||
Options::parse(int& argc, char**& argv)
|
Options::parse(int& argc, char**& argv)
|
||||||
{
|
{
|
||||||
ParseResult result(m_options, m_positional, argc, argv);
|
ParseResult result(m_options, m_positional, m_allow_unrecognised, argc, argv);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1697,7 +1711,15 @@ ParseResult::parse(int& argc, char**& argv)
|
|||||||
|
|
||||||
if (iter == m_options.end())
|
if (iter == m_options.end())
|
||||||
{
|
{
|
||||||
throw option_not_exists_exception(name);
|
if (m_allow_unrecognised)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//error
|
||||||
|
throw option_not_exists_exception(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto value = iter->second;
|
auto value = iter->second;
|
||||||
@ -1726,7 +1748,19 @@ ParseResult::parse(int& argc, char**& argv)
|
|||||||
|
|
||||||
if (iter == m_options.end())
|
if (iter == m_options.end())
|
||||||
{
|
{
|
||||||
throw option_not_exists_exception(name);
|
if (m_allow_unrecognised)
|
||||||
|
{
|
||||||
|
// keep unrecognised options in argument list, skip to next argument
|
||||||
|
argv[nextKeep] = argv[current];
|
||||||
|
++nextKeep;
|
||||||
|
++current;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//error
|
||||||
|
throw option_not_exists_exception(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto opt = iter->second;
|
auto opt = iter->second;
|
||||||
|
|||||||
@ -37,7 +37,9 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
bool apple = false;
|
bool apple = false;
|
||||||
|
|
||||||
options.add_options()
|
options
|
||||||
|
.allow_unrecognised_options()
|
||||||
|
.add_options()
|
||||||
("a,apple", "an apple", cxxopts::value<bool>(apple))
|
("a,apple", "an apple", cxxopts::value<bool>(apple))
|
||||||
("b,bob", "Bob")
|
("b,bob", "Bob")
|
||||||
("t,true", "True", cxxopts::value<bool>()->default_value("true"))
|
("t,true", "True", cxxopts::value<bool>()->default_value("true"))
|
||||||
|
|||||||
@ -473,3 +473,33 @@ TEST_CASE("std::optional", "[optional]") {
|
|||||||
CHECK(*optional == "foo");
|
CHECK(*optional == "foo");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TEST_CASE("Unrecognised options", "[options]") {
|
||||||
|
cxxopts::Options options("unknown_options", " - test unknown options");
|
||||||
|
|
||||||
|
options.add_options()
|
||||||
|
("long", "a long option")
|
||||||
|
("s,short", "a short option");
|
||||||
|
|
||||||
|
Argv av({
|
||||||
|
"unknown_options",
|
||||||
|
"--unknown",
|
||||||
|
"--long",
|
||||||
|
"-su",
|
||||||
|
"--another_unknown",
|
||||||
|
});
|
||||||
|
|
||||||
|
char** argv = av.argv();
|
||||||
|
auto argc = av.argc();
|
||||||
|
|
||||||
|
SECTION("Default behaviour") {
|
||||||
|
CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("After allowing unrecognised options") {
|
||||||
|
options.allow_unrecognised_options();
|
||||||
|
CHECK_NOTHROW(options.parse(argc, argv));
|
||||||
|
REQUIRE(argc == 3);
|
||||||
|
CHECK_THAT(argv[1], Catch::Equals("--unknown"));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user