mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-04 07:04:39 +00:00
Initial commit for implementing MutuallyExclusiveGroup
This commit is contained in:
parent
281f1ab017
commit
39988ec62d
@ -52,6 +52,7 @@ SOFTWARE.
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <unordered_set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -1455,6 +1456,43 @@ public:
|
|||||||
return *argument;
|
return *argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MutuallyExclusiveGroup {
|
||||||
|
friend class ArgumentParser;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MutuallyExclusiveGroup() = delete;
|
||||||
|
|
||||||
|
explicit MutuallyExclusiveGroup(ArgumentParser &parent,
|
||||||
|
bool required = false)
|
||||||
|
: m_parent(parent), m_required(required), m_elements({}) {}
|
||||||
|
|
||||||
|
MutuallyExclusiveGroup(const MutuallyExclusiveGroup &other) = delete;
|
||||||
|
MutuallyExclusiveGroup &
|
||||||
|
operator=(const MutuallyExclusiveGroup &other) = delete;
|
||||||
|
|
||||||
|
MutuallyExclusiveGroup(MutuallyExclusiveGroup &&other) noexcept
|
||||||
|
: m_parent(other.m_parent), m_required(other.m_required),
|
||||||
|
m_elements(std::move(other.m_elements)) {
|
||||||
|
other.m_elements.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Targs> Argument &add_argument(Targs... f_args) {
|
||||||
|
auto &argument = m_parent.add_argument(std::forward<Targs>(f_args)...);
|
||||||
|
m_elements.insert(&argument);
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ArgumentParser &m_parent;
|
||||||
|
bool m_required{false};
|
||||||
|
std::unordered_set<Argument *> m_elements{};
|
||||||
|
};
|
||||||
|
|
||||||
|
MutuallyExclusiveGroup &add_mutually_exclusive_group(bool required = false) {
|
||||||
|
m_mutually_exclusive_groups.emplace_back(*this, required);
|
||||||
|
return m_mutually_exclusive_groups.back();
|
||||||
|
}
|
||||||
|
|
||||||
// Parameter packed add_parents method
|
// Parameter packed add_parents method
|
||||||
// Accepts a variadic number of ArgumentParser objects
|
// Accepts a variadic number of ArgumentParser objects
|
||||||
template <typename... Targs>
|
template <typename... Targs>
|
||||||
@ -1520,6 +1558,24 @@ public:
|
|||||||
for ([[maybe_unused]] const auto &[unused, argument] : m_argument_map) {
|
for ([[maybe_unused]] const auto &[unused, argument] : m_argument_map) {
|
||||||
argument->validate();
|
argument->validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check each mutually exclusive group and make sure
|
||||||
|
// there are no constraint violations
|
||||||
|
for (const auto &group : m_mutually_exclusive_groups) {
|
||||||
|
auto mutex_argument_used{false};
|
||||||
|
Argument *mutex_argument_it{nullptr};
|
||||||
|
for (Argument *arg : group.m_elements) {
|
||||||
|
if (!mutex_argument_used && arg->m_is_used) {
|
||||||
|
mutex_argument_used = true;
|
||||||
|
mutex_argument_it = arg;
|
||||||
|
} else if (mutex_argument_used && arg->m_is_used) {
|
||||||
|
// Violation
|
||||||
|
throw std::runtime_error("Argument '" + arg->get_usage_full() +
|
||||||
|
"' not allowed with '" +
|
||||||
|
mutex_argument_it->get_usage_full() + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call parse_known_args_internal - which does all the work
|
/* Call parse_known_args_internal - which does all the work
|
||||||
@ -2006,6 +2062,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
using argument_it = std::list<Argument>::iterator;
|
using argument_it = std::list<Argument>::iterator;
|
||||||
|
using mutex_group_it = std::vector<MutuallyExclusiveGroup>::iterator;
|
||||||
using argument_parser_it =
|
using argument_parser_it =
|
||||||
std::list<std::reference_wrapper<ArgumentParser>>::iterator;
|
std::list<std::reference_wrapper<ArgumentParser>>::iterator;
|
||||||
|
|
||||||
@ -2030,6 +2087,9 @@ private:
|
|||||||
std::list<std::reference_wrapper<ArgumentParser>> m_subparsers;
|
std::list<std::reference_wrapper<ArgumentParser>> m_subparsers;
|
||||||
std::map<std::string_view, argument_parser_it> m_subparser_map;
|
std::map<std::string_view, argument_parser_it> m_subparser_map;
|
||||||
std::map<std::string_view, bool> m_subparser_used;
|
std::map<std::string_view, bool> m_subparser_used;
|
||||||
|
std::vector<MutuallyExclusiveGroup>
|
||||||
|
m_mutually_exclusive_groups; /// TODO: Add this to the copy/move
|
||||||
|
/// constructors
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace argparse
|
} // namespace argparse
|
||||||
|
@ -41,6 +41,7 @@ file(GLOB ARGPARSE_TEST_SOURCES
|
|||||||
test_invalid_arguments.cpp
|
test_invalid_arguments.cpp
|
||||||
test_is_used.cpp
|
test_is_used.cpp
|
||||||
test_issue_37.cpp
|
test_issue_37.cpp
|
||||||
|
test_mutually_exclusive_group.cpp
|
||||||
test_negative_numbers.cpp
|
test_negative_numbers.cpp
|
||||||
test_optional_arguments.cpp
|
test_optional_arguments.cpp
|
||||||
test_parent_parsers.cpp
|
test_parent_parsers.cpp
|
||||||
|
21
test/test_mutually_exclusive_group.cpp
Normal file
21
test/test_mutually_exclusive_group.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifdef WITH_MODULE
|
||||||
|
import argparse;
|
||||||
|
#else
|
||||||
|
#include <argparse/argparse.hpp>
|
||||||
|
#endif
|
||||||
|
#include <doctest.hpp>
|
||||||
|
|
||||||
|
using doctest::test_suite;
|
||||||
|
|
||||||
|
TEST_CASE("User-supplied argument" * test_suite("is_used")) {
|
||||||
|
argparse::ArgumentParser program("test");
|
||||||
|
|
||||||
|
auto &group = program.add_mutually_exclusive_group();
|
||||||
|
group.add_argument("--first");
|
||||||
|
group.add_argument("--second");
|
||||||
|
|
||||||
|
REQUIRE_THROWS_WITH_AS(
|
||||||
|
program.parse_args({"test", "--first", "1", "--second", "2"}),
|
||||||
|
"Argument '--first VAR' not allowed with '--second VAR'",
|
||||||
|
std::runtime_error);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user