Commit ca6e9f70eb6b5fab44504daf57d92a9412ab301c
Committed by
jarro2783
1 parent
00e8ecc4
Allow unrecognised options. (#105)
Allows unrecognised options to be left alone by the parser without throwing an exception.
Showing
3 changed files
with
70 additions
and
4 deletions
include/cxxopts.hpp
| ... | ... | @@ -1095,6 +1095,7 @@ namespace cxxopts |
| 1095 | 1095 | ParseResult( |
| 1096 | 1096 | const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>&, |
| 1097 | 1097 | std::vector<std::string>, |
| 1098 | + bool allow_unrecognised, | |
| 1098 | 1099 | int&, char**&); |
| 1099 | 1100 | |
| 1100 | 1101 | size_t |
| ... | ... | @@ -1174,6 +1175,8 @@ namespace cxxopts |
| 1174 | 1175 | std::unordered_set<std::string> m_positional_set; |
| 1175 | 1176 | std::unordered_map<std::shared_ptr<OptionDetails>, OptionValue> m_results; |
| 1176 | 1177 | |
| 1178 | + bool m_allow_unrecognised; | |
| 1179 | + | |
| 1177 | 1180 | std::vector<KeyValue> m_sequential; |
| 1178 | 1181 | }; |
| 1179 | 1182 | |
| ... | ... | @@ -1187,6 +1190,7 @@ namespace cxxopts |
| 1187 | 1190 | , m_custom_help("[OPTION...]") |
| 1188 | 1191 | , m_positional_help("positional parameters") |
| 1189 | 1192 | , m_show_positional(false) |
| 1193 | + , m_allow_unrecognised(false) | |
| 1190 | 1194 | , m_next_positional(m_positional.end()) |
| 1191 | 1195 | { |
| 1192 | 1196 | } |
| ... | ... | @@ -1212,6 +1216,13 @@ namespace cxxopts |
| 1212 | 1216 | return *this; |
| 1213 | 1217 | } |
| 1214 | 1218 | |
| 1219 | + Options& | |
| 1220 | + allow_unrecognised_options() | |
| 1221 | + { | |
| 1222 | + m_allow_unrecognised = true; | |
| 1223 | + return *this; | |
| 1224 | + } | |
| 1225 | + | |
| 1215 | 1226 | ParseResult |
| 1216 | 1227 | parse(int& argc, char**& argv); |
| 1217 | 1228 | |
| ... | ... | @@ -1275,6 +1286,7 @@ namespace cxxopts |
| 1275 | 1286 | std::string m_custom_help; |
| 1276 | 1287 | std::string m_positional_help; |
| 1277 | 1288 | bool m_show_positional; |
| 1289 | + bool m_allow_unrecognised; | |
| 1278 | 1290 | |
| 1279 | 1291 | std::unordered_map<std::string, std::shared_ptr<OptionDetails>> m_options; |
| 1280 | 1292 | std::vector<std::string> m_positional; |
| ... | ... | @@ -1431,11 +1443,13 @@ ParseResult::ParseResult |
| 1431 | 1443 | ( |
| 1432 | 1444 | const std::unordered_map<std::string, std::shared_ptr<OptionDetails>>& options, |
| 1433 | 1445 | std::vector<std::string> positional, |
| 1446 | + bool allow_unrecognised, | |
| 1434 | 1447 | int& argc, char**& argv |
| 1435 | 1448 | ) |
| 1436 | 1449 | : m_options(options) |
| 1437 | 1450 | , m_positional(std::move(positional)) |
| 1438 | 1451 | , m_next_positional(m_positional.begin()) |
| 1452 | +, m_allow_unrecognised(allow_unrecognised) | |
| 1439 | 1453 | { |
| 1440 | 1454 | parse(argc, argv); |
| 1441 | 1455 | } |
| ... | ... | @@ -1641,7 +1655,7 @@ inline |
| 1641 | 1655 | ParseResult |
| 1642 | 1656 | Options::parse(int& argc, char**& argv) |
| 1643 | 1657 | { |
| 1644 | - ParseResult result(m_options, m_positional, argc, argv); | |
| 1658 | + ParseResult result(m_options, m_positional, m_allow_unrecognised, argc, argv); | |
| 1645 | 1659 | return result; |
| 1646 | 1660 | } |
| 1647 | 1661 | |
| ... | ... | @@ -1697,7 +1711,15 @@ ParseResult::parse(int& argc, char**& argv) |
| 1697 | 1711 | |
| 1698 | 1712 | if (iter == m_options.end()) |
| 1699 | 1713 | { |
| 1700 | - throw option_not_exists_exception(name); | |
| 1714 | + if (m_allow_unrecognised) | |
| 1715 | + { | |
| 1716 | + continue; | |
| 1717 | + } | |
| 1718 | + else | |
| 1719 | + { | |
| 1720 | + //error | |
| 1721 | + throw option_not_exists_exception(name); | |
| 1722 | + } | |
| 1701 | 1723 | } |
| 1702 | 1724 | |
| 1703 | 1725 | auto value = iter->second; |
| ... | ... | @@ -1726,7 +1748,19 @@ ParseResult::parse(int& argc, char**& argv) |
| 1726 | 1748 | |
| 1727 | 1749 | if (iter == m_options.end()) |
| 1728 | 1750 | { |
| 1729 | - throw option_not_exists_exception(name); | |
| 1751 | + if (m_allow_unrecognised) | |
| 1752 | + { | |
| 1753 | + // keep unrecognised options in argument list, skip to next argument | |
| 1754 | + argv[nextKeep] = argv[current]; | |
| 1755 | + ++nextKeep; | |
| 1756 | + ++current; | |
| 1757 | + continue; | |
| 1758 | + } | |
| 1759 | + else | |
| 1760 | + { | |
| 1761 | + //error | |
| 1762 | + throw option_not_exists_exception(name); | |
| 1763 | + } | |
| 1730 | 1764 | } |
| 1731 | 1765 | |
| 1732 | 1766 | auto opt = iter->second; | ... | ... |
src/example.cpp
| ... | ... | @@ -37,7 +37,9 @@ int main(int argc, char* argv[]) |
| 37 | 37 | |
| 38 | 38 | bool apple = false; |
| 39 | 39 | |
| 40 | - options.add_options() | |
| 40 | + options | |
| 41 | + .allow_unrecognised_options() | |
| 42 | + .add_options() | |
| 41 | 43 | ("a,apple", "an apple", cxxopts::value<bool>(apple)) |
| 42 | 44 | ("b,bob", "Bob") |
| 43 | 45 | ("t,true", "True", cxxopts::value<bool>()->default_value("true")) | ... | ... |
test/options.cpp
| ... | ... | @@ -473,3 +473,33 @@ TEST_CASE("std::optional", "[optional]") { |
| 473 | 473 | CHECK(*optional == "foo"); |
| 474 | 474 | } |
| 475 | 475 | #endif |
| 476 | + | |
| 477 | +TEST_CASE("Unrecognised options", "[options]") { | |
| 478 | + cxxopts::Options options("unknown_options", " - test unknown options"); | |
| 479 | + | |
| 480 | + options.add_options() | |
| 481 | + ("long", "a long option") | |
| 482 | + ("s,short", "a short option"); | |
| 483 | + | |
| 484 | + Argv av({ | |
| 485 | + "unknown_options", | |
| 486 | + "--unknown", | |
| 487 | + "--long", | |
| 488 | + "-su", | |
| 489 | + "--another_unknown", | |
| 490 | + }); | |
| 491 | + | |
| 492 | + char** argv = av.argv(); | |
| 493 | + auto argc = av.argc(); | |
| 494 | + | |
| 495 | + SECTION("Default behaviour") { | |
| 496 | + CHECK_THROWS_AS(options.parse(argc, argv), cxxopts::option_not_exists_exception); | |
| 497 | + } | |
| 498 | + | |
| 499 | + SECTION("After allowing unrecognised options") { | |
| 500 | + options.allow_unrecognised_options(); | |
| 501 | + CHECK_NOTHROW(options.parse(argc, argv)); | |
| 502 | + REQUIRE(argc == 3); | |
| 503 | + CHECK_THAT(argv[1], Catch::Equals("--unknown")); | |
| 504 | + } | |
| 505 | +} | |
| 476 | 506 | \ No newline at end of file | ... | ... |