From 6cf6888489b40a33e043ab0593c75bafdeb35fdd Mon Sep 17 00:00:00 2001 From: Marek Roszko Date: Sun, 13 Nov 2022 11:50:27 -0500 Subject: [PATCH] Update argparse --- thirdparty/CMakeLists.txt | 1 + thirdparty/argparse/CMakeLists.txt | 66 +++++++++++++- thirdparty/argparse/README.md | 13 ++- .../argparse/include/argparse/argparse.hpp | 42 +++++++-- thirdparty/argparse/samples/CMakeLists.txt | 1 - .../argparse/samples/compound_arguments.cpp | 2 + .../samples/custom_assignment_characters.cpp | 2 + .../samples/custom_prefix_characters.cpp | 2 + .../samples/description_epilog_metavar.cpp | 2 + .../samples/gathering_remaining_arguments.cpp | 2 + thirdparty/argparse/samples/is_used.cpp | 2 + .../joining_repeated_optional_arguments.cpp | 2 + .../argparse/samples/list_of_arguments.cpp | 2 + .../argparse/samples/negative_numbers.cpp | 2 + .../samples/optional_flag_argument.cpp | 2 + .../argparse/samples/parse_known_args.cpp | 2 + .../argparse/samples/positional_argument.cpp | 2 + .../repeating_argument_to_increase_value.cpp | 2 + .../samples/required_optional_argument.cpp | 2 + thirdparty/argparse/samples/subcommands.cpp | 2 + thirdparty/argparse/test/CMakeLists.txt | 1 + .../argparse/test/test_bool_operator.cpp | 85 +++++++++++++++++++ .../test/test_positional_arguments.cpp | 2 +- thirdparty/argparse/test/test_subparsers.cpp | 37 ++++++++ 24 files changed, 262 insertions(+), 16 deletions(-) create mode 100644 thirdparty/argparse/test/test_bool_operator.cpp diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index bf255fdb70..2a0a150dae 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -23,6 +23,7 @@ # Note: The glew folder isn't added here because it is added inside the main CMakeLists.txt +set( ARGPARSE_INSTALL OFF ) add_subdirectory( argparse ) add_subdirectory( clipper ) add_subdirectory( clipper2 ) diff --git a/thirdparty/argparse/CMakeLists.txt b/thirdparty/argparse/CMakeLists.txt index 20579177a8..ddc87c579e 100644 --- a/thirdparty/argparse/CMakeLists.txt +++ b/thirdparty/argparse/CMakeLists.txt @@ -1,12 +1,13 @@ cmake_minimum_required(VERSION 3.12.4) project(argparse - VERSION 2.9.0 + VERSION 2.9.0 DESCRIPTION "A single header argument parser for C++17" HOMEPAGE_URL "https://github.com/p-ranav/argparse" LANGUAGES CXX ) +option(ARGPARSE_INSTALL ON) option(ARGPARSE_BUILD_TESTS OFF) option(ARGPARSE_LONG_VERSION_ARG_ONLY OFF) @@ -36,4 +37,65 @@ if(ARGPARSE_BUILD_TESTS) add_subdirectory(test) endif() -## Modified to remove undesirable install steps \ No newline at end of file +if(ARGPARSE_INSTALL) + install(TARGETS argparse EXPORT argparseConfig) + install(EXPORT argparseConfig + NAMESPACE argparse:: + DESTINATION ${CMAKE_INSTALL_LIBDIR_ARCHIND}/cmake/${PROJECT_NAME}) + install(FILES ${CMAKE_CURRENT_LIST_DIR}/include/argparse/argparse.hpp + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/argparse) + + + set(CONFIG_FILE_NAME_WITHOUT_EXT "${PROJECT_NAME}Config") + set(CMAKE_CONFIG_FILE_BASENAME "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_FILE_NAME_WITHOUT_EXT}") + set(CMAKE_CONFIG_VERSION_FILE_NAME "${CMAKE_CONFIG_FILE_BASENAME}-version.cmake") + set(CMAKE_CONFIG_FILE_NAME "${CMAKE_CONFIG_FILE_BASENAME}.cmake") + + if(${CMAKE_VERSION} VERSION_GREATER "3.14") + set(OPTIONAL_ARCH_INDEPENDENT "ARCH_INDEPENDENT") + endif() + + write_basic_package_version_file("${CMAKE_CONFIG_VERSION_FILE_NAME}" + COMPATIBILITY ExactVersion + ${OPTIONAL_ARCH_INDEPENDENT} + ) + + export(EXPORT argparseConfig + NAMESPACE argparse::) + + install(FILES "${CMAKE_CONFIG_VERSION_FILE_NAME}" + DESTINATION "${CMAKE_INSTALL_LIBDIR_ARCHIND}/cmake/${PROJECT_NAME}") + + set(PackagingTemplatesDir "${CMAKE_CURRENT_SOURCE_DIR}/packaging") + + set(CPACK_PACKAGE_NAME "${PROJECT_NAME}") + set(CPACK_PACKAGE_VENDOR "argparse (C++) developers") + set(CPACK_PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}") + set(CPACK_DEBIAN_PACKAGE_NAME "${CPACK_PACKAGE_NAME}") + set(CPACK_RPM_PACKAGE_NAME "${CPACK_PACKAGE_NAME}") + set(CPACK_PACKAGE_HOMEPAGE_URL "${PROJECT_HOMEPAGE_URL}") + set(CPACK_PACKAGE_MAINTAINER "Pranav Srinivas Kumar") + set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_MAINTAINER}") + set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") + set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") + + set(CPACK_DEBIAN_PACKAGE_NAME "lib${PROJECT_NAME}-dev") + set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6-dev") + set(CPACK_DEBIAN_PACKAGE_SUGGESTS "cmake, pkg-config, pkg-conf") + + set(CPACK_RPM_PACKAGE_NAME "lib${PROJECT_NAME}-devel") + set(CPACK_RPM_PACKAGE_SUGGESTS "${CPACK_DEBIAN_PACKAGE_SUGGESTS}") + + set(CPACK_DEB_COMPONENT_INSTALL ON) + set(CPACK_RPM_COMPONENT_INSTALL ON) + set(CPACK_NSIS_COMPONENT_INSTALL ON) + set(CPACK_DEBIAN_COMPRESSION_TYPE "xz") + + set(PKG_CONFIG_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc") + configure_file("${PackagingTemplatesDir}/pkgconfig.pc.in" "${PKG_CONFIG_FILE_NAME}" @ONLY) + install(FILES "${PKG_CONFIG_FILE_NAME}" + DESTINATION "${CMAKE_INSTALL_LIBDIR_ARCHIND}/pkgconfig" + ) +endif() + +include(CPack) diff --git a/thirdparty/argparse/README.md b/thirdparty/argparse/README.md index 74265f90be..078489a15b 100644 --- a/thirdparty/argparse/README.md +++ b/thirdparty/argparse/README.md @@ -38,6 +38,7 @@ * [Parent Parsers](#parent-parsers) * [Subcommands](#subcommands) * [Parse Known Args](#parse-known-args) + * [ArgumentParser in bool Context](#argumentparser-in-bool-context) * [Custom Prefix Characters](#custom-prefix-characters) * [Custom Assignment Characters](#custom-assignment-characters) * [Further Examples](#further-examples) @@ -824,7 +825,7 @@ Subcommands: When a help message is requested from a subparser, only the help for that particular parser will be printed. The help message will not include parent parser or sibling parser messages. -Additionally, every parser has a `.is_subcommand_used("")` member function to check if a subcommand was used. +Additionally, every parser has the `.is_subcommand_used("")` and `.is_subcommand_used(subparser)` member functions to check if a subcommand was used. ### Parse Known Args @@ -848,7 +849,13 @@ int main(int argc, char *argv[]) { } ``` -### Custom Prefix Characters +### ArgumentParser in bool Context + +An `ArgumentParser` is `false` until it (or one of its subparsers) have extracted +known value(s) with `.parse_args` or `.parse_known_args`. When using `.parse_known_args`, +unknown arguments will not make a parser `true`. + +### Custom Prefix Characters Most command-line options will use `-` as the prefix, e.g. `-f/--foo`. Parsers that need to support different or additional prefix characters, e.g. for options like `+f` or `/foo`, may specify them using the `set_prefix_chars()`. @@ -1092,7 +1099,7 @@ foo@bar:/home/dev/$ ./test --bar=BAR --foo Use the latest argparse in your CMake project without copying any content. ```cmake -cmake_minimum_required(VERSION 3.11) +cmake_minimum_required(VERSION 3.14) PROJECT(myproject) diff --git a/thirdparty/argparse/include/argparse/argparse.hpp b/thirdparty/argparse/include/argparse/argparse.hpp index 5e826c58b2..f4e4c6b248 100644 --- a/thirdparty/argparse/include/argparse/argparse.hpp +++ b/thirdparty/argparse/include/argparse/argparse.hpp @@ -63,6 +63,8 @@ struct HasContainerTraits : std::false_type {}; template <> struct HasContainerTraits : std::false_type {}; +template <> struct HasContainerTraits : std::false_type {}; + template struct HasContainerTraits< T, std::void_t().begin()), @@ -597,7 +599,7 @@ public: std::string get_inline_usage() const { std::stringstream usage; // Find the longest variant to show in the usage string - std::string longest_name = m_names[0]; + std::string longest_name = m_names.front(); for (const auto &s : m_names) { if (s.size() > longest_name.size()) { longest_name = s; @@ -758,6 +760,8 @@ private: std::stringstream stream; if (!m_used_name.empty()) { stream << m_used_name << ": "; + } else { + stream << m_names.front() << ": "; } if (m_num_args_range.is_exact()) { stream << m_num_args_range.get_min(); @@ -773,7 +777,7 @@ private: void throw_required_arg_not_used_error() const { std::stringstream stream; - stream << m_names[0] << ": required."; + stream << m_names.front() << ": required."; throw std::runtime_error(stream.str()); } @@ -1102,6 +1106,21 @@ public: return *this; } + explicit operator bool() const { + auto arg_used = std::any_of(m_argument_map.cbegin(), + m_argument_map.cend(), + [](auto &it) { + return it.second->m_is_used; + }); + auto subparser_used = std::any_of(m_subparser_used.cbegin(), + m_subparser_used.cend(), + [](auto &it) { + return it.second; + }); + + return m_is_parsed && (arg_used || subparser_used); + } + // Parameter packing // Call add_argument with variadic number of string arguments template Argument &add_argument(Targs... f_args) { @@ -1236,13 +1255,18 @@ public: return (*this)[arg_name].m_is_used; } - /* Getter that returns true for user-supplied options. Returns false if not - * user-supplied, even with a default value. + /* Getter that returns true if a subcommand is used. */ auto is_subcommand_used(std::string_view subcommand_name) const { return m_subparser_used.at(subcommand_name); } + /* Getter that returns true if a subcommand is used. + */ + auto is_subcommand_used(const ArgumentParser &subparser) const { + return is_subcommand_used(subparser.m_program_name); + } + /* Indexing operator. Return a reference to an Argument object * Used in conjuction with Argument.operator== e.g., parser["foo"] == true * @throws std::logic_error in case of an invalid argument name @@ -1341,9 +1365,9 @@ public: // Add any options inline here for (const auto &argument : this->m_optional_arguments) { - if (argument.m_names[0] == "-v") { + if (argument.m_names.front() == "-v") { continue; - } else if (argument.m_names[0] == "-h") { + } else if (argument.m_names.front() == "-h") { stream << " [-h]"; } else { stream << " " << argument.get_inline_usage(); @@ -1642,11 +1666,11 @@ private: bool m_is_parsed = false; std::list m_positional_arguments; std::list m_optional_arguments; - std::map> m_argument_map; + std::map m_argument_map; std::string m_parser_path; std::list> m_subparsers; - std::map> m_subparser_map; - std::map> m_subparser_used; + std::map m_subparser_map; + std::map m_subparser_used; }; } // namespace argparse diff --git a/thirdparty/argparse/samples/CMakeLists.txt b/thirdparty/argparse/samples/CMakeLists.txt index b146b2d251..94ba3b5ff9 100644 --- a/thirdparty/argparse/samples/CMakeLists.txt +++ b/thirdparty/argparse/samples/CMakeLists.txt @@ -25,7 +25,6 @@ endif() function(add_sample NAME) ADD_EXECUTABLE(ARGPARSE_SAMPLE_${NAME} ${NAME}.cpp) INCLUDE_DIRECTORIES("../include" ".") - TARGET_LINK_LIBRARIES(ARGPARSE_SAMPLE_${NAME} PRIVATE argparse::argparse) set_target_properties(ARGPARSE_SAMPLE_${NAME} PROPERTIES OUTPUT_NAME ${NAME}) endfunction() diff --git a/thirdparty/argparse/samples/compound_arguments.cpp b/thirdparty/argparse/samples/compound_arguments.cpp index c44d02d9f0..66d5c920e1 100644 --- a/thirdparty/argparse/samples/compound_arguments.cpp +++ b/thirdparty/argparse/samples/compound_arguments.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include int main(int argc, char *argv[]) { diff --git a/thirdparty/argparse/samples/custom_assignment_characters.cpp b/thirdparty/argparse/samples/custom_assignment_characters.cpp index 7d9ab39d42..d5deff126b 100644 --- a/thirdparty/argparse/samples/custom_assignment_characters.cpp +++ b/thirdparty/argparse/samples/custom_assignment_characters.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include #include diff --git a/thirdparty/argparse/samples/custom_prefix_characters.cpp b/thirdparty/argparse/samples/custom_prefix_characters.cpp index cdce04de67..01e248a650 100644 --- a/thirdparty/argparse/samples/custom_prefix_characters.cpp +++ b/thirdparty/argparse/samples/custom_prefix_characters.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include #include diff --git a/thirdparty/argparse/samples/description_epilog_metavar.cpp b/thirdparty/argparse/samples/description_epilog_metavar.cpp index ef7f11eaf8..02f12dd1c8 100644 --- a/thirdparty/argparse/samples/description_epilog_metavar.cpp +++ b/thirdparty/argparse/samples/description_epilog_metavar.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include int main(int argc, char *argv[]) { diff --git a/thirdparty/argparse/samples/gathering_remaining_arguments.cpp b/thirdparty/argparse/samples/gathering_remaining_arguments.cpp index e3fb84eede..4f404544f1 100644 --- a/thirdparty/argparse/samples/gathering_remaining_arguments.cpp +++ b/thirdparty/argparse/samples/gathering_remaining_arguments.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include int main(int argc, char *argv[]) { diff --git a/thirdparty/argparse/samples/is_used.cpp b/thirdparty/argparse/samples/is_used.cpp index a2f0a149c9..27e0373b23 100644 --- a/thirdparty/argparse/samples/is_used.cpp +++ b/thirdparty/argparse/samples/is_used.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include int main(int argc, char *argv[]) { diff --git a/thirdparty/argparse/samples/joining_repeated_optional_arguments.cpp b/thirdparty/argparse/samples/joining_repeated_optional_arguments.cpp index ab819c8fc6..eebbdc6170 100644 --- a/thirdparty/argparse/samples/joining_repeated_optional_arguments.cpp +++ b/thirdparty/argparse/samples/joining_repeated_optional_arguments.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include int main(int argc, char *argv[]) { diff --git a/thirdparty/argparse/samples/list_of_arguments.cpp b/thirdparty/argparse/samples/list_of_arguments.cpp index ef4d421051..e533e477ee 100644 --- a/thirdparty/argparse/samples/list_of_arguments.cpp +++ b/thirdparty/argparse/samples/list_of_arguments.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include int main(int argc, char *argv[]) { diff --git a/thirdparty/argparse/samples/negative_numbers.cpp b/thirdparty/argparse/samples/negative_numbers.cpp index bb1c888f77..ac4284fb4d 100644 --- a/thirdparty/argparse/samples/negative_numbers.cpp +++ b/thirdparty/argparse/samples/negative_numbers.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include int main(int argc, char *argv[]) { diff --git a/thirdparty/argparse/samples/optional_flag_argument.cpp b/thirdparty/argparse/samples/optional_flag_argument.cpp index fff720a9e1..2f859540fd 100644 --- a/thirdparty/argparse/samples/optional_flag_argument.cpp +++ b/thirdparty/argparse/samples/optional_flag_argument.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include int main(int argc, char *argv[]) { diff --git a/thirdparty/argparse/samples/parse_known_args.cpp b/thirdparty/argparse/samples/parse_known_args.cpp index 17b5f4f2c5..e87ead6cd0 100644 --- a/thirdparty/argparse/samples/parse_known_args.cpp +++ b/thirdparty/argparse/samples/parse_known_args.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include #include diff --git a/thirdparty/argparse/samples/positional_argument.cpp b/thirdparty/argparse/samples/positional_argument.cpp index 646ddc378b..03ffb0a68e 100644 --- a/thirdparty/argparse/samples/positional_argument.cpp +++ b/thirdparty/argparse/samples/positional_argument.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include int main(int argc, char *argv[]) { diff --git a/thirdparty/argparse/samples/repeating_argument_to_increase_value.cpp b/thirdparty/argparse/samples/repeating_argument_to_increase_value.cpp index e0de41e9ff..eb1cfd6917 100644 --- a/thirdparty/argparse/samples/repeating_argument_to_increase_value.cpp +++ b/thirdparty/argparse/samples/repeating_argument_to_increase_value.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include int main(int argc, char *argv[]) { diff --git a/thirdparty/argparse/samples/required_optional_argument.cpp b/thirdparty/argparse/samples/required_optional_argument.cpp index 1fe2dccc40..efea523154 100644 --- a/thirdparty/argparse/samples/required_optional_argument.cpp +++ b/thirdparty/argparse/samples/required_optional_argument.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include int main(int argc, char *argv[]) { diff --git a/thirdparty/argparse/samples/subcommands.cpp b/thirdparty/argparse/samples/subcommands.cpp index f88f05cec1..74d610e14c 100644 --- a/thirdparty/argparse/samples/subcommands.cpp +++ b/thirdparty/argparse/samples/subcommands.cpp @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + #include int main(int argc, char *argv[]) { diff --git a/thirdparty/argparse/test/CMakeLists.txt b/thirdparty/argparse/test/CMakeLists.txt index c7a56572bc..47b9ba5c7b 100644 --- a/thirdparty/argparse/test/CMakeLists.txt +++ b/thirdparty/argparse/test/CMakeLists.txt @@ -27,6 +27,7 @@ file(GLOB ARGPARSE_TEST_SOURCES main.cpp test_actions.cpp test_append.cpp + test_bool_operator.cpp test_compound_arguments.cpp test_container_arguments.cpp test_const_correct.cpp diff --git a/thirdparty/argparse/test/test_bool_operator.cpp b/thirdparty/argparse/test/test_bool_operator.cpp new file mode 100644 index 0000000000..93a3be23d8 --- /dev/null +++ b/thirdparty/argparse/test/test_bool_operator.cpp @@ -0,0 +1,85 @@ +#include +#include + +using doctest::test_suite; + +TEST_CASE("ArgumentParser in bool context" * + test_suite("argument_parser")) { + argparse::ArgumentParser program("test"); + program.add_argument("cases").remaining(); + + program.parse_args({"test"}); + REQUIRE_FALSE(program); + + program.parse_args({"test", "one", "two"}); + REQUIRE(program); +} + +TEST_CASE("With subparsers in bool context" * test_suite("argument_parser")) { + argparse::ArgumentParser program("test"); + + argparse::ArgumentParser cmd_fly("fly"); + cmd_fly.add_argument("plane"); + + argparse::ArgumentParser cmd_soar("soar"); + cmd_soar.add_argument("direction"); + + program.add_subparser(cmd_fly); + program.add_subparser(cmd_soar); + + program.parse_args({"test", "fly", "glider"}); + REQUIRE(program); + REQUIRE(cmd_fly); + REQUIRE_FALSE(cmd_soar); +} + +TEST_CASE("Parsers remain false with unknown arguments" * + test_suite("argument_parser")) { + argparse::ArgumentParser program("test"); + + argparse::ArgumentParser cmd_build("build"); + cmd_build.add_argument("--file").nargs(1); + + argparse::ArgumentParser cmd_run("run"); + cmd_run.add_argument("--file").nargs(1); + + program.add_subparser(cmd_build); + program.add_subparser(cmd_run); + + auto unknowns = + program.parse_known_args({"test", "badger", "--add-meal", "grubs"}); + REQUIRE_FALSE(program); + REQUIRE_FALSE(cmd_build); + REQUIRE_FALSE(cmd_run); +} + +TEST_CASE("Multi-level parsers match subparser bool" * + test_suite("argument_parser")) { + argparse::ArgumentParser program("test"); + + argparse::ArgumentParser cmd_cook("cook"); + cmd_cook.add_argument("--temperature"); + + argparse::ArgumentParser cmd_cook_boil("boil"); + cmd_cook_boil.add_argument("--rate"); + + argparse::ArgumentParser cmd_cook_boil_stir("stir"); + cmd_cook_boil_stir.add_argument("--rate"); + + argparse::ArgumentParser cmd_wash("wash"); + + program.add_subparser(cmd_cook); + cmd_cook.add_subparser(cmd_cook_boil); + cmd_cook_boil.add_subparser(cmd_cook_boil_stir); + + program.add_subparser(cmd_wash); + + auto unknowns = program.parse_known_args( + {"test", "cook", "boil", "stir", "--rate", "fast"}); + + REQUIRE(program); + REQUIRE(cmd_cook); + REQUIRE(cmd_cook_boil); + REQUIRE(cmd_cook_boil_stir); + REQUIRE_FALSE(cmd_wash); +} diff --git a/thirdparty/argparse/test/test_positional_arguments.cpp b/thirdparty/argparse/test/test_positional_arguments.cpp index 0875669737..cfee488152 100644 --- a/thirdparty/argparse/test/test_positional_arguments.cpp +++ b/thirdparty/argparse/test/test_positional_arguments.cpp @@ -18,7 +18,7 @@ TEST_CASE("Missing expected positional argument" * argparse::ArgumentParser program("test"); program.add_argument("input"); REQUIRE_THROWS_WITH_AS(program.parse_args({"test"}), - "1 argument(s) expected. 0 provided.", + "input: 1 argument(s) expected. 0 provided.", std::runtime_error); } diff --git a/thirdparty/argparse/test/test_subparsers.cpp b/thirdparty/argparse/test/test_subparsers.cpp index e4a42746cd..0830ce1e09 100644 --- a/thirdparty/argparse/test/test_subparsers.cpp +++ b/thirdparty/argparse/test/test_subparsers.cpp @@ -199,4 +199,41 @@ TEST_CASE("Parse git commands" * test_suite("subparsers")) { REQUIRE(submodule_update_command.get("--init") == true); REQUIRE(submodule_update_command.get("--recursive") == true); } +} + +TEST_CASE("Check is_subcommand_used after parse" * test_suite("subparsers")) { + argparse::ArgumentParser command_1("add"); + + argparse::ArgumentParser command_2("clean"); + command_2.add_argument("--fullclean") + .default_value(false) + .implicit_value(true); + + argparse::ArgumentParser program("test"); + program.add_subparser(command_1); + program.add_subparser(command_2); + + SUBCASE("command 1") { + program.parse_args({"test", "add"}); + REQUIRE(program.is_subcommand_used("add") == true); + REQUIRE(program.is_subcommand_used(command_1) == true); + REQUIRE(program.is_subcommand_used("clean") == false); + REQUIRE(program.is_subcommand_used(command_2) == false); + } + + SUBCASE("command 2") { + program.parse_args({"test", "clean", "--fullclean"}); + REQUIRE(program.is_subcommand_used("add") == false); + REQUIRE(program.is_subcommand_used(command_1) == false); + REQUIRE(program.is_subcommand_used("clean") == true); + REQUIRE(program.is_subcommand_used(command_2) == true); + } + + SUBCASE("none") { + program.parse_args({"test"}); + REQUIRE(program.is_subcommand_used("add") == false); + REQUIRE(program.is_subcommand_used(command_1) == false); + REQUIRE(program.is_subcommand_used("clean") == false); + REQUIRE(program.is_subcommand_used(command_2) == false); + } } \ No newline at end of file