From 14a7fe9ffeb2cb2f3f36293b521598440304dceb Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 16 Mar 2024 14:47:14 +0100 Subject: [PATCH] Prevent an argument with an already registered name to be added except if it is -h/--help/-v/--version and they are default arguments. For very complex programs with lots of options, this can help detecting accidental redefinitions of already used argument names. --- include/argparse/argparse.hpp | 10 ++++++++++ test/test_error_reporting.cpp | 14 +++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/include/argparse/argparse.hpp b/include/argparse/argparse.hpp index e1718241..5a80a6ee 100644 --- a/include/argparse/argparse.hpp +++ b/include/argparse/argparse.hpp @@ -1545,6 +1545,7 @@ class ArgumentParser { std::ostream &os = std::cout) : m_program_name(std::move(program_name)), m_version(std::move(version)), m_exit_on_default_arguments(exit_on_default_arguments), + m_default_arguments(add_args), m_parser_path(m_program_name) { if ((add_args & default_arguments::help) == default_arguments::help) { add_argument("-h", "--help") @@ -2431,6 +2432,14 @@ class ArgumentParser { void index_argument(argument_it it) { for (const auto &name : std::as_const(it->m_names)) { + if (!((name == "-h" || name == "--help") && + (m_default_arguments & default_arguments::help) == default_arguments::help) && + !((name == "-v" || name == "--version") && + (m_default_arguments & default_arguments::version) == default_arguments::version) && + m_argument_map.find(name) != m_argument_map.end()) { + throw std::runtime_error("Argument with name " + name + + " already registered"); + } m_argument_map.insert_or_assign(name, it); } } @@ -2440,6 +2449,7 @@ class ArgumentParser { std::string m_description; std::string m_epilog; bool m_exit_on_default_arguments = true; + default_arguments m_default_arguments; std::string m_prefix_chars{"-"}; std::string m_assign_chars{"="}; bool m_is_parsed = false; diff --git a/test/test_error_reporting.cpp b/test/test_error_reporting.cpp index 0c911321..e643d62d 100644 --- a/test/test_error_reporting.cpp +++ b/test/test_error_reporting.cpp @@ -121,4 +121,16 @@ TEST_CASE("Detect unknown subcommand" * test_suite("error_reporting")) { "Failed to parse 'logic', did you mean 'log'", std::runtime_error); } -} \ No newline at end of file +} + +TEST_CASE("Duplicate argument" * test_suite("error_reporting")) { + argparse::ArgumentParser program("program"); + program.add_argument("-a"); + program.add_argument("-h"); // redefining default arguments is allowed + program.add_argument("--help"); // redefining default arguments is allowed + program.add_argument("-v"); // redefining default arguments is allowed + program.add_argument("--version"); // redefining default arguments is allowed + REQUIRE_THROWS_WITH_AS(program.add_argument("-a"), + "Argument with name -a already registered", + std::runtime_error); +}