diff --git a/include/cxxopts.hpp b/include/cxxopts.hpp index 163a3e1..1e49266 100644 --- a/include/cxxopts.hpp +++ b/include/cxxopts.hpp @@ -397,6 +397,18 @@ namespace cxxopts } }; + class option_required_exception : public OptionParseException + { + public: + option_required_exception(const std::string& option) + : OptionParseException + ( + u8"Option ‘" + option + u8"’ is required but not present" + ) + { + } + }; + namespace values { template @@ -841,9 +853,25 @@ namespace cxxopts std::string m_group; }; + // A helper function for setting required arguments + void + check_required + ( + const Options& options, + const std::vector& required + ) + { + for (auto& r : required) + { + if (options.count(r) == 0) + { + throw option_required_exception(r); + } + } + } + namespace { - constexpr int OPTION_LONGEST = 30; constexpr int OPTION_DESC_GAP = 2; diff --git a/test/options.cpp b/test/options.cpp index 389178b..1f46c61 100644 --- a/test/options.cpp +++ b/test/options.cpp @@ -100,6 +100,27 @@ TEST_CASE("Short options", "[options]") cxxopts::invalid_option_format_error); } +TEST_CASE("Required arguments", "[options]") +{ + cxxopts::Options options("required", " - test required options"); + options.add_options() + ("one", "one option") + ("two", "second option") + ; + + Argv argv({ + "required", + "--one" + }); + + auto aargv = argv.argv(); + auto argc = argv.argc(); + + options.parse(argc, aargv); + REQUIRE_THROWS_AS(cxxopts::check_required(options, {"two"}), + cxxopts::option_required_exception); +} + TEST_CASE("No positional", "[positional]") { cxxopts::Options options("test_no_positional",