From de4239483dd55a95fd781a652b8bc8be0aa95235 Mon Sep 17 00:00:00 2001 From: Pranav Srinivas Kumar Date: Sat, 4 Nov 2023 15:36:01 -0500 Subject: [PATCH] Added logic and unit tests for the required flag in mutex_args --- README.md | 18 +++++++++++++++ include/argparse/argparse.hpp | 19 ++++++++++++++++ test/test_mutually_exclusive_group.cpp | 31 ++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/README.md b/README.md index 64b9236..9abd975 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ * [Deciding if the value was given by the user](#deciding-if-the-value-was-given-by-the-user) * [Joining values of repeated optional arguments](#joining-values-of-repeated-optional-arguments) * [Repeating an argument to increase a value](#repeating-an-argument-to-increase-a-value) + * [Mutually Exclusive Group](#mutually-exclusive-group) * [Negative Numbers](#negative-numbers) * [Combining Positional and Optional Arguments](#combining-positional-and-optional-arguments) * [Printing Help](#printing-help) @@ -280,6 +281,23 @@ program.parse_args(argc, argv); // Example: ./main -VVVV std::cout << "verbose level: " << verbosity << std::endl; // verbose level: 4 ``` +#### Mutually Exclusive Group + +Create a mutually exclusive group using `program.add_mutually_exclusive_group(required = false)`. `argparse`` will make sure that only one of the arguments in the mutually exclusive group was present on the command line: + +```cpp +auto &group = program.add_mutually_exclusive_group(); +group.add_argument("--first"); +group.add_argument("--second"); +``` + +with the following usage will yield an error: + +```console +foo@bar:/home/dev/$ ./main --first 1 --second 2 +Argument '--second VAR' not allowed with '--first VAR' +``` + ### Negative Numbers Optional arguments start with ```-```. Can ```argparse``` handle negative numbers? The answer is yes! diff --git a/include/argparse/argparse.hpp b/include/argparse/argparse.hpp index d4aec0e..d32d2e8 100644 --- a/include/argparse/argparse.hpp +++ b/include/argparse/argparse.hpp @@ -1588,6 +1588,25 @@ public: mutex_argument_it->get_usage_full() + "'"); } } + + if (!mutex_argument_used && group.m_required) { + // at least one argument from the group is + // required + std::string argument_names{}; + std::size_t i = 0; + std::size_t size = group.m_elements.size(); + for (Argument *arg : group.m_elements) { + if (i + 1 == size) { + // last + argument_names += "'" + arg->get_usage_full() + "' "; + } else { + argument_names += "'" + arg->get_usage_full() + "' or "; + } + i += 1; + } + throw std::runtime_error("One of the arguments " + argument_names + + "is required"); + } } } diff --git a/test/test_mutually_exclusive_group.cpp b/test/test_mutually_exclusive_group.cpp index 28c6bec..93d6215 100644 --- a/test/test_mutually_exclusive_group.cpp +++ b/test/test_mutually_exclusive_group.cpp @@ -21,6 +21,37 @@ TEST_CASE("Create mutually exclusive group with 2 arguments" * std::runtime_error); } +TEST_CASE( + "Create mutually exclusive group with 2 arguments with required flag" * + test_suite("mutex_args")) { + argparse::ArgumentParser program("test"); + + auto &group = program.add_mutually_exclusive_group(true); + group.add_argument("--first"); + group.add_argument("--second"); + + REQUIRE_THROWS_WITH_AS( + program.parse_args({"test"}), + "One of the arguments '--first VAR' or '--second VAR' is required", + std::runtime_error); +} + +TEST_CASE( + "Create mutually exclusive group with 3 arguments with required flag" * + test_suite("mutex_args")) { + argparse::ArgumentParser program("test"); + + auto &group = program.add_mutually_exclusive_group(true); + group.add_argument("--first"); + group.add_argument("--second"); + group.add_argument("--third"); + + REQUIRE_THROWS_WITH_AS(program.parse_args({"test"}), + "One of the arguments '--first VAR' or '--second VAR' " + "or '--third VAR' is required", + std::runtime_error); +} + TEST_CASE( "Create mutually exclusive group with 2 arguments, then copy the parser" * test_suite("mutex_args")) {