From 6c7da857b6e04cf90a127fcb7e4b1d7257a38fa8 Mon Sep 17 00:00:00 2001 From: Pranav Srinivas Kumar Date: Tue, 20 Sep 2022 20:27:24 -0700 Subject: [PATCH] Added table of contents to README and clang formatted code --- README.md | 29 +++++++++ clang_format.bash | 1 + include/argparse/argparse.hpp | 97 ++++++++++++++-------------- test/test_actions.cpp | 39 +++++------ test/test_append.cpp | 34 ++++------ test/test_compound_arguments.cpp | 94 +++++++++------------------ test/test_container_arguments.cpp | 34 +++++----- test/test_default_args.cpp | 2 +- test/test_get.cpp | 14 ++-- test/test_help.cpp | 10 ++- test/test_invalid_arguments.cpp | 35 +++++----- test/test_is_used.cpp | 12 ++-- test/test_issue_37.cpp | 45 +++++++------ test/test_negative_numbers.cpp | 65 ++++++++----------- test/test_optional_arguments.cpp | 53 ++++++--------- test/test_parent_parsers.cpp | 16 ++--- test/test_parse_args.cpp | 81 +++++++++-------------- test/test_positional_arguments.cpp | 45 +++++++------ test/test_required_arguments.cpp | 2 +- test/test_subparsers.cpp | 100 +++++++++++++++++++---------- test/test_version.cpp | 23 +++---- 21 files changed, 405 insertions(+), 426 deletions(-) create mode 100755 clang_format.bash diff --git a/README.md b/README.md index 5fbb18a..a9a1063 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,35 @@ * Requires C++17 * MIT License +## Table of Contents + +* [Quick Start](#quick-start) + * [Positional Arguments](#positional-arguments) + * [Optional Arguments](#optional-arguments) + * [Requiring optional arguments](#requiring-optional-arguments) + * [Accessing optional arguments without default values](#accessing-optional-arguments-without-default-values) + * [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) + * [Negative Numbers](#negative-numbers) + * [Combining Positional and Optional Arguments](#combining-positional-and-optional-arguments) + * [Printing Help](#printing-help) + * [Adding a description and an epilog to help](#adding-a-description-and-an-epilog-to-help) + * [List of Arguments](#list-of-arguments) + * [Compound Arguments](#compound-arguments) + * [Converting to Numeric Types](#converting-to-numeric-types) + * [Default Arguments](#default-arguments) + * [Gathering Remaining Arguments](#gathering-remaining-arguments) + * [Parent Parsers](#parent-parsers) +* [Further Examples](#further-examples) + * [Construct a JSON object from a filename argument](#construct-a-json-object-from-a-filename-argument) + * [Positional Arguments with Compound Toggle Arguments](#positional-arguments-with-compound-toggle-arguments) + * [Restricting the set of values for an argument](#restricting-the-set-of-values-for-an-argument) +* [CMake Integration](#cmake-integration) +* [Supported Toolchains](#supported-toolchains) +* [Contributing](#contributing) +* [License](#license) + ## Quick Start Simply include argparse.hpp and you're good to go. diff --git a/clang_format.bash b/clang_format.bash new file mode 100755 index 0000000..fa26930 --- /dev/null +++ b/clang_format.bash @@ -0,0 +1 @@ +clang-format -i include/argparse/*.hpp test/*.cpp diff --git a/include/argparse/argparse.hpp b/include/argparse/argparse.hpp index b5964e8..48307e0 100644 --- a/include/argparse/argparse.hpp +++ b/include/argparse/argparse.hpp @@ -149,8 +149,9 @@ constexpr bool standard_integer = standard_signed_integer || standard_unsigned_integer; template -constexpr decltype(auto) apply_plus_one_impl(F &&f, Tuple &&t, Extra &&x, - std::index_sequence /*unused*/) { +constexpr decltype(auto) +apply_plus_one_impl(F &&f, Tuple &&t, Extra &&x, + std::index_sequence /*unused*/) { return std::invoke(std::forward(f), std::get(std::forward(t))..., std::forward(x)); } @@ -328,11 +329,7 @@ template struct parse_number { } // namespace details -enum class nargs_pattern { - optional, - any, - at_least_one -}; +enum class nargs_pattern { optional, any, at_least_one }; enum class default_arguments : unsigned int { none = 0, @@ -395,7 +392,7 @@ public: } template - auto action(F &&callable, Args &&...bound_args) + auto action(F &&callable, Args &&... bound_args) -> std::enable_if_t, Argument &> { using action_type = std::conditional_t< @@ -429,7 +426,8 @@ public: if constexpr (is_one_of(Shape, 'd') && details::standard_integer) { action(details::parse_number()); - } else if constexpr (is_one_of(Shape, 'i') && details::standard_integer) { + } else if constexpr (is_one_of(Shape, 'i') && + details::standard_integer) { action(details::parse_number()); } else if constexpr (is_one_of(Shape, 'u') && details::standard_unsigned_integer) { @@ -506,7 +504,8 @@ public: std::visit([](const auto &f) { f({}); }, m_action); return start; } - if ((dist = static_cast(std::distance(start, end))) >= num_args_min) { + if ((dist = static_cast(std::distance(start, end))) >= + num_args_min) { if (num_args_max < dist) { end = std::next(start, num_args_max); } @@ -558,7 +557,8 @@ public: throw_required_arg_no_value_provided_error(); } } else { - if (!m_num_args_range.contains(m_values.size()) && !m_default_value.has_value()) { + if (!m_num_args_range.contains(m_values.size()) && + !m_default_value.has_value()) { throw_nargs_range_validation_error(); } } @@ -606,15 +606,13 @@ public: return get() == rhs; } else { auto lhs = get(); - return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs), - std::end(rhs), [](const auto &lhs, const auto &rhs) { - return lhs == rhs; - }); + return std::equal( + std::begin(lhs), std::end(lhs), std::begin(rhs), std::end(rhs), + [](const auto &lhs, const auto &rhs) { return lhs == rhs; }); } } private: - class NArgsRange { std::size_t m_min; std::size_t m_max; @@ -631,21 +629,15 @@ private: return value >= m_min && value <= m_max; } - bool is_exact() const { - return m_min == m_max; - } + bool is_exact() const { return m_min == m_max; } bool is_right_bounded() const { return m_max < std::numeric_limits::max(); } - std::size_t get_min() const { - return m_min; - } + std::size_t get_min() const { return m_min; } - std::size_t get_max() const { - return m_max; - } + std::size_t get_max() const { return m_max; } }; void throw_nargs_range_validation_error() const { @@ -656,7 +648,8 @@ private: if (m_num_args_range.is_exact()) { stream << m_num_args_range.get_min(); } else if (m_num_args_range.is_right_bounded()) { - stream << m_num_args_range.get_min() << " to " << m_num_args_range.get_max(); + stream << m_num_args_range.get_min() << " to " + << m_num_args_range.get_max(); } else { stream << m_num_args_range.get_min() << " or more"; } @@ -855,7 +848,9 @@ private: * Get argument value given a type * @throws std::logic_error in case of incompatible types */ - template auto get() const -> std::conditional_t, T, const T&> { + template + auto get() const + -> std::conditional_t, T, const T &> { if (!m_values.empty()) { if constexpr (details::IsContainer) { return any_cast_container(m_values); @@ -916,7 +911,7 @@ private: std::in_place_type, [](const std::string &value) { return value; }}; std::vector m_values; - NArgsRange m_num_args_range {1, 1}; + NArgsRange m_num_args_range{1, 1}; bool m_accepts_optional_like_value = false; bool m_is_optional : true; bool m_is_required : true; @@ -932,7 +927,7 @@ public: : m_program_name(std::move(program_name)), m_version(std::move(version)) { if ((add_args & default_arguments::help) == default_arguments::help) { add_argument("-h", "--help") - .action([&](const auto &/*unused*/) { + .action([&](const auto & /*unused*/) { std::cout << help().str(); std::exit(0); }) @@ -943,7 +938,7 @@ public: } if ((add_args & default_arguments::version) == default_arguments::version) { add_argument("-v", "--version") - .action([&](const auto &/*unused*/) { + .action([&](const auto & /*unused*/) { std::cout << m_version << std::endl; std::exit(0); }) @@ -958,10 +953,8 @@ public: ArgumentParser &operator=(ArgumentParser &&) = default; ArgumentParser(const ArgumentParser &other) - : m_program_name(other.m_program_name), - m_version(other.m_version), - m_description(other.m_description), - m_epilog(other.m_epilog), + : m_program_name(other.m_program_name), m_version(other.m_version), + m_description(other.m_description), m_epilog(other.m_epilog), m_is_parsed(other.m_is_parsed), m_positional_arguments(other.m_positional_arguments), m_optional_arguments(other.m_optional_arguments) { @@ -1002,7 +995,7 @@ public: // Parameter packed add_parents method // Accepts a variadic number of ArgumentParser objects template - ArgumentParser &add_parents(const Targs &...f_args) { + ArgumentParser &add_parents(const Targs &... f_args) { for (const ArgumentParser &parent_parser : {std::ref(f_args)...}) { for (const auto &argument : parent_parser.m_positional_arguments) { auto it = m_positional_arguments.insert( @@ -1036,7 +1029,7 @@ public: void parse_args(const std::vector &arguments) { parse_args_internal(arguments); // Check if all arguments are parsed - for ([[maybe_unused]] const auto& [unused, argument] : m_argument_map) { + for ([[maybe_unused]] const auto &[unused, argument] : m_argument_map) { argument->validate(); } } @@ -1056,8 +1049,9 @@ public: * @throws std::logic_error if the option has no value * @throws std::bad_any_cast if the option is not of type T */ - template auto get(std::string_view arg_name) const - -> std::conditional_t, T, const T&> { + template + auto get(std::string_view arg_name) const + -> std::conditional_t, T, const T &> { if (!m_is_parsed) { throw std::logic_error("Nothing parsed, no arguments are available."); } @@ -1148,17 +1142,16 @@ public: } if (!parser.m_subparser_map.empty()) { - stream << (parser.m_positional_arguments.empty() ? - (parser.m_optional_arguments.empty() ? "" : "\n") : - "\n") + stream << (parser.m_positional_arguments.empty() + ? (parser.m_optional_arguments.empty() ? "" : "\n") + : "\n") << "Subcommands:\n"; stream << "{"; - std::size_t i = 0; + std::size_t i = 0; for (const auto &[argument, unused] : parser.m_subparser_map) { if (i == 0) { stream << argument; - } - else { + } else { stream << ", " << argument; } ++i; @@ -1190,7 +1183,8 @@ public: return out.str(); } - void add_subparser(ArgumentParser& parser) { + void add_subparser(ArgumentParser &parser) { + auto it = m_subparsers.emplace(std::cend(m_subparsers), parser); m_subparser_map.insert_or_assign(parser.m_program_name, it); } @@ -1217,11 +1211,13 @@ private: if (subparser_it != m_subparser_map.end()) { // build list of remaining args - const auto unprocessed_arguments = std::vector(it, end); + const auto unprocessed_arguments = + std::vector(it, end); // invoke subparser m_is_parsed = true; - return subparser_it->second->get().parse_args(unprocessed_arguments); + return subparser_it->second->get().parse_args( + unprocessed_arguments); } throw std::runtime_error( @@ -1263,17 +1259,18 @@ private: return 0; } std::size_t max_size = 0; - for ([[maybe_unused]] const auto& [unused, argument] : m_argument_map) { + for ([[maybe_unused]] const auto &[unused, argument] : m_argument_map) { max_size = std::max(max_size, argument->get_arguments_length()); } - for ([[maybe_unused]] const auto& [command, unused] : m_subparser_map) { + for ([[maybe_unused]] const auto &[command, unused] : m_subparser_map) { max_size = std::max(max_size, command.size()); } return max_size; } using argument_it = std::list::iterator; - using argument_parser_it = std::list>::iterator; + using argument_parser_it = + std::list>::iterator; void index_argument(argument_it it) { for (const auto &name : std::as_const(it->m_names)) { diff --git a/test/test_actions.cpp b/test/test_actions.cpp index 5b0ef76..07f59c9 100644 --- a/test/test_actions.cpp +++ b/test/test_actions.cpp @@ -1,22 +1,21 @@ -#include #include +#include using doctest::test_suite; TEST_CASE("Users can use default value inside actions" * test_suite("actions")) { argparse::ArgumentParser program("test"); - program.add_argument("input") - .default_value("bar") - .action([=](const std::string& value) { - static const std::vector choices = { "foo", "bar", "baz" }; - if (std::find(choices.begin(), choices.end(), value) != choices.end()) { - return value; - } - return std::string{ "bar" }; - }); + program.add_argument("input").default_value("bar").action( + [=](const std::string &value) { + static const std::vector choices = {"foo", "bar", "baz"}; + if (std::find(choices.begin(), choices.end(), value) != choices.end()) { + return value; + } + return std::string{"bar"}; + }); - program.parse_args({ "test", "fez" }); + program.parse_args({"test", "fez"}); REQUIRE(program.get("input") == "bar"); } @@ -126,9 +125,11 @@ TEST_CASE("Users can use actions on nargs=ANY arguments" * argparse::ArgumentParser program("sum"); int result = 0; - program.add_argument("all").nargs(argparse::nargs_pattern::any).action( - [](int &sum, std::string const &value) { sum += std::stoi(value); }, - std::ref(result)); + program.add_argument("all") + .nargs(argparse::nargs_pattern::any) + .action( + [](int &sum, std::string const &value) { sum += std::stoi(value); }, + std::ref(result)); program.parse_args({"sum", "42", "100", "-3", "-20"}); REQUIRE(result == 119); @@ -154,11 +155,11 @@ TEST_CASE("Users can run actions on parameterless optional arguments" * GIVEN("a flag argument with a counting action") { int count = 0; program.add_argument("-V", "--verbose") - .action([&](const auto &) { ++count; }) - .append() - .default_value(false) - .implicit_value(true) - .nargs(0); + .action([&](const auto &) { ++count; }) + .append() + .default_value(false) + .implicit_value(true) + .nargs(0); WHEN("the flag is repeated") { program.parse_args({"test", "-VVVV"}); diff --git a/test/test_append.cpp b/test/test_append.cpp index 005bd92..4934514 100644 --- a/test/test_append.cpp +++ b/test/test_append.cpp @@ -1,46 +1,40 @@ -#include #include +#include using doctest::test_suite; TEST_CASE("Simplest .append" * test_suite("append")) { argparse::ArgumentParser program("test"); - program.add_argument("--dir") - .append(); - program.parse_args({ "test", "--dir", "./Docs" }); - std::string result { program.get("--dir") }; + program.add_argument("--dir").append(); + program.parse_args({"test", "--dir", "./Docs"}); + std::string result{program.get("--dir")}; REQUIRE(result == "./Docs"); } TEST_CASE("Two parameter .append" * test_suite("append")) { argparse::ArgumentParser program("test"); - program.add_argument("--dir") - .append(); - program.parse_args({ "test", "--dir", "./Docs", "--dir", "./Src" }); - auto result { program.get>("--dir") }; + program.add_argument("--dir").append(); + program.parse_args({"test", "--dir", "./Docs", "--dir", "./Src"}); + auto result{program.get>("--dir")}; REQUIRE(result.at(0) == "./Docs"); REQUIRE(result.at(1) == "./Src"); } TEST_CASE("Two int .append" * test_suite("append")) { argparse::ArgumentParser program("test"); - program.add_argument("--factor") - .append() - .scan<'i', int>(); - program.parse_args({ "test", "--factor", "2", "--factor", "5" }); - auto result { program.get>("--factor") }; + program.add_argument("--factor").append().scan<'i', int>(); + program.parse_args({"test", "--factor", "2", "--factor", "5"}); + auto result{program.get>("--factor")}; REQUIRE(result.at(0) == 2); REQUIRE(result.at(1) == 5); } TEST_CASE("Default value with .append" * test_suite("append")) { - std::vector expected { "./Src", "./Imgs" }; + std::vector expected{"./Src", "./Imgs"}; argparse::ArgumentParser program("test"); - program.add_argument("--dir") - .default_value(expected) - .append(); - program.parse_args({ "test" }); - auto result { program.get>("--dir") }; + program.add_argument("--dir").default_value(expected).append(); + program.parse_args({"test"}); + auto result{program.get>("--dir")}; REQUIRE(result == expected); } diff --git a/test/test_compound_arguments.cpp b/test/test_compound_arguments.cpp index dd19344..3bc1601 100644 --- a/test/test_compound_arguments.cpp +++ b/test/test_compound_arguments.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include using doctest::test_suite; @@ -7,19 +7,13 @@ using doctest::test_suite; TEST_CASE("Parse compound toggle arguments with implicit values" * test_suite("compound_arguments")) { argparse::ArgumentParser program("test"); - program.add_argument("-a") - .default_value(false) - .implicit_value(true); + program.add_argument("-a").default_value(false).implicit_value(true); - program.add_argument("-u") - .default_value(false) - .implicit_value(true); + program.add_argument("-u").default_value(false).implicit_value(true); - program.add_argument("-x") - .default_value(false) - .implicit_value(true); + program.add_argument("-x").default_value(false).implicit_value(true); - program.parse_args({ "./test.exe", "-aux" }); + program.parse_args({"./test.exe", "-aux"}); REQUIRE(program.get("-a") == true); REQUIRE(program.get("-u") == true); REQUIRE(program.get("-x") == true); @@ -28,23 +22,16 @@ TEST_CASE("Parse compound toggle arguments with implicit values" * TEST_CASE("Parse compound toggle arguments with implicit values and nargs" * test_suite("compound_arguments")) { argparse::ArgumentParser program("test"); - program.add_argument("-a") - .default_value(false) - .implicit_value(true); + program.add_argument("-a").default_value(false).implicit_value(true); - program.add_argument("-b") - .default_value(false) - .implicit_value(true); + program.add_argument("-b").default_value(false).implicit_value(true); - program.add_argument("-c") - .nargs(2) - .scan<'g', float>(); + program.add_argument("-c").nargs(2).scan<'g', float>(); - program.add_argument("--input_files") - .nargs(3); + program.add_argument("--input_files").nargs(3); - program.parse_args({ "./test.exe", "-abc", "3.14", "2.718", "--input_files", - "a.txt", "b.txt", "c.txt" }); + program.parse_args({"./test.exe", "-abc", "3.14", "2.718", "--input_files", + "a.txt", "b.txt", "c.txt"}); REQUIRE(program.get("-a") == true); REQUIRE(program.get("-b") == true); auto c = program.get>("-c"); @@ -63,49 +50,36 @@ TEST_CASE("Parse compound toggle arguments with implicit values and nargs and " test_suite("compound_arguments")) { argparse::ArgumentParser program("test"); - program.add_argument("numbers") - .nargs(3) - .scan<'i', int>(); + program.add_argument("numbers").nargs(3).scan<'i', int>(); - program.add_argument("-a") - .default_value(false) - .implicit_value(true); + program.add_argument("-a").default_value(false).implicit_value(true); - program.add_argument("-b") - .default_value(false) - .implicit_value(true); + program.add_argument("-b").default_value(false).implicit_value(true); - program.add_argument("-c") - .nargs(2) - .scan<'g', float>(); + program.add_argument("-c").nargs(2).scan<'g', float>(); - program.add_argument("--input_files") - .nargs(3); + program.add_argument("--input_files").nargs(3); - REQUIRE_THROWS(program.parse_args({ "./test.exe", "1", "-abc", "3.14", "2.718", "2", "--input_files", "a.txt", "b.txt", "c.txt", "3" })); + REQUIRE_THROWS( + program.parse_args({"./test.exe", "1", "-abc", "3.14", "2.718", "2", + "--input_files", "a.txt", "b.txt", "c.txt", "3"})); } TEST_CASE("Parse out-of-order compound arguments" * test_suite("compound_arguments")) { argparse::ArgumentParser program("test"); - program.add_argument("-a") - .default_value(false) - .implicit_value(true); + program.add_argument("-a").default_value(false).implicit_value(true); - program.add_argument("-b") - .default_value(false) - .implicit_value(true); + program.add_argument("-b").default_value(false).implicit_value(true); - program.add_argument("-c") - .nargs(2) - .scan<'g', float>(); + program.add_argument("-c").nargs(2).scan<'g', float>(); - program.parse_args({ "./main", "-cab", "3.14", "2.718" }); + program.parse_args({"./main", "-cab", "3.14", "2.718"}); - auto a = program.get("-a"); // true - auto b = program.get("-b"); // true - auto c = program.get>("-c"); // {3.14f, 2.718f} + auto a = program.get("-a"); // true + auto b = program.get("-b"); // true + auto c = program.get>("-c"); // {3.14f, 2.718f} REQUIRE(a == true); REQUIRE(b == true); REQUIRE(program["-c"] == std::vector{3.14f, 2.718f}); @@ -115,20 +89,16 @@ TEST_CASE("Parse out-of-order compound arguments. Second variation" * test_suite("compound_arguments")) { argparse::ArgumentParser program("test"); - program.add_argument("-a") - .default_value(false) - .implicit_value(true); + program.add_argument("-a").default_value(false).implicit_value(true); - program.add_argument("-b") - .default_value(false) - .implicit_value(true); + program.add_argument("-b").default_value(false).implicit_value(true); program.add_argument("-c") - .nargs(2) - .default_value(std::vector{0.0f, 0.0f}) - .scan<'g', float>(); + .nargs(2) + .default_value(std::vector{0.0f, 0.0f}) + .scan<'g', float>(); - program.parse_args({"./main", "-cb"}); + program.parse_args({"./main", "-cb"}); auto a = program.get("-a"); auto b = program.get("-b"); diff --git a/test/test_container_arguments.cpp b/test/test_container_arguments.cpp index 69258dd..5eab026 100644 --- a/test/test_container_arguments.cpp +++ b/test/test_container_arguments.cpp @@ -1,15 +1,14 @@ -#include #include +#include #include using doctest::test_suite; TEST_CASE("Parse vector of arguments" * test_suite("vector")) { argparse::ArgumentParser program("test"); - program.add_argument("input") - .nargs(2); + program.add_argument("input").nargs(2); - program.parse_args({ "test", "rocket.mesh", "thrust_profile.csv" }); + program.parse_args({"test", "rocket.mesh", "thrust_profile.csv"}); auto inputs = program.get>("input"); REQUIRE(inputs.size() == 2); @@ -19,10 +18,9 @@ TEST_CASE("Parse vector of arguments" * test_suite("vector")) { TEST_CASE("Parse list of arguments" * test_suite("vector")) { argparse::ArgumentParser program("test"); - program.add_argument("input") - .nargs(2); + program.add_argument("input").nargs(2); - program.parse_args({ "test", "rocket.mesh", "thrust_profile.csv" }); + program.parse_args({"test", "rocket.mesh", "thrust_profile.csv"}); auto inputs = program.get>("input"); REQUIRE(inputs.size() == 2); @@ -34,10 +32,10 @@ TEST_CASE("Parse list of arguments with default values" * test_suite("vector")) { argparse::ArgumentParser program("test"); program.add_argument("--input") - .default_value(std::list{1, 2, 3, 4, 5}) - .nargs(5); + .default_value(std::list{1, 2, 3, 4, 5}) + .nargs(5); - program.parse_args({ "test" }); + program.parse_args({"test"}); auto inputs = program.get>("--input"); REQUIRE(inputs.size() == 5); @@ -54,19 +52,20 @@ TEST_CASE("Parse list of arguments and save in an object" * struct ConfigManager { std::vector files; - void add_file(const std::string& file) { - files.push_back(file); - } + void add_file(const std::string &file) { files.push_back(file); } }; ConfigManager config_manager; argparse::ArgumentParser program("test"); program.add_argument("--input_files") - .nargs(2) - .action([&](const std::string& value) { config_manager.add_file(value); return value; }); + .nargs(2) + .action([&](const std::string &value) { + config_manager.add_file(value); + return value; + }); - program.parse_args({ "test", "--input_files", "config.xml", "system.json" }); + program.parse_args({"test", "--input_files", "config.xml", "system.json"}); auto file_args = program.get>("--input_files"); REQUIRE(file_args.size() == 2); @@ -76,5 +75,6 @@ TEST_CASE("Parse list of arguments and save in an object" * REQUIRE(config_manager.files.size() == 2); REQUIRE(config_manager.files[0] == "config.xml"); REQUIRE(config_manager.files[1] == "system.json"); - REQUIRE(program["--input_files"] == std::vector{"config.xml", "system.json"}); + REQUIRE(program["--input_files"] == + std::vector{"config.xml", "system.json"}); } diff --git a/test/test_default_args.cpp b/test/test_default_args.cpp index 046b88e..7b5e581 100644 --- a/test/test_default_args.cpp +++ b/test/test_default_args.cpp @@ -5,7 +5,7 @@ using doctest::test_suite; TEST_CASE("Include all default arguments" * test_suite("default_args")) { argparse::ArgumentParser parser("test"); - auto help_msg { parser.help().str() }; + auto help_msg{parser.help().str()}; REQUIRE(help_msg.find("shows help message") != std::string::npos); REQUIRE(help_msg.find("prints version information") != std::string::npos); } diff --git a/test/test_get.cpp b/test/test_get.cpp index db316ba..9cc046c 100644 --- a/test/test_get.cpp +++ b/test/test_get.cpp @@ -1,12 +1,12 @@ -#include #include +#include using doctest::test_suite; TEST_CASE("Getting a simple argument" * test_suite("ArgumentParser::get")) { argparse::ArgumentParser program("test"); program.add_argument("-s", "--stuff"); - REQUIRE_NOTHROW(program.parse_args({ "test", "-s", "./src" })); + REQUIRE_NOTHROW(program.parse_args({"test", "-s", "./src"})); REQUIRE(program.get("--stuff") == "./src"); } @@ -21,17 +21,15 @@ TEST_CASE("Skipped call to parse_args" * test_suite("ArgumentParser::get")) { TEST_CASE("Missing argument" * test_suite("ArgumentParser::get")) { argparse::ArgumentParser program("test"); program.add_argument("-s", "--stuff"); - REQUIRE_NOTHROW(program.parse_args({ "test" })); + REQUIRE_NOTHROW(program.parse_args({"test"})); REQUIRE_THROWS_WITH_AS(program.get("--stuff"), - "No value provided for '--stuff'.", - std::logic_error); + "No value provided for '--stuff'.", std::logic_error); } TEST_CASE("Implicit argument" * test_suite("ArgumentParser::get")) { argparse::ArgumentParser program("test"); program.add_argument("-s", "--stuff").nargs(1); - REQUIRE_NOTHROW(program.parse_args({ "test" })); + REQUIRE_NOTHROW(program.parse_args({"test"})); REQUIRE_THROWS_WITH_AS(program.get("--stuff"), - "No value provided for '--stuff'.", - std::logic_error); + "No value provided for '--stuff'.", std::logic_error); } diff --git a/test/test_help.cpp b/test/test_help.cpp index e3bb225..a81af42 100644 --- a/test/test_help.cpp +++ b/test/test_help.cpp @@ -64,12 +64,10 @@ TEST_CASE("Users can replace default -h/--help" * test_suite("help")) { argparse::default_arguments::version); std::stringstream buffer; program.add_argument("-h", "--help") - .action([&](const auto &) { - buffer << program; - }) - .default_value(false) - .implicit_value(true) - .nargs(0); + .action([&](const auto &) { buffer << program; }) + .default_value(false) + .implicit_value(true) + .nargs(0); REQUIRE(buffer.str().empty()); program.parse_args({"test", "--help"}); diff --git a/test/test_invalid_arguments.cpp b/test/test_invalid_arguments.cpp index bb44f1e..e8db3f2 100644 --- a/test/test_invalid_arguments.cpp +++ b/test/test_invalid_arguments.cpp @@ -1,5 +1,5 @@ -#include #include +#include using doctest::test_suite; @@ -8,33 +8,32 @@ TEST_CASE("Parse unknown optional argument" * argparse::ArgumentParser bfm("bfm"); - bfm.add_argument("-l","--load") - .help("load a VMM into the kernel"); + bfm.add_argument("-l", "--load").help("load a VMM into the kernel"); bfm.add_argument("-x", "--start") - .default_value(false) - .implicit_value(true) - .help("start a previously loaded VMM"); + .default_value(false) + .implicit_value(true) + .help("start a previously loaded VMM"); bfm.add_argument("-d", "--dump") - .default_value(false) - .implicit_value(true) - .help("output the contents of the VMM's debug buffer"); + .default_value(false) + .implicit_value(true) + .help("output the contents of the VMM's debug buffer"); bfm.add_argument("-s", "--stop") - .default_value(false) - .implicit_value(true) - .help("stop a previously started VMM"); + .default_value(false) + .implicit_value(true) + .help("stop a previously started VMM"); bfm.add_argument("-u", "--unload") - .default_value(false) - .implicit_value(true) - .help("unload a previously loaded VMM"); + .default_value(false) + .implicit_value(true) + .help("unload a previously loaded VMM"); bfm.add_argument("-m", "--mem") - .default_value(64ULL) - .scan<'u', unsigned long long>() - .help("memory in MB to give the VMM when loading"); + .default_value(64ULL) + .scan<'u', unsigned long long>() + .help("memory in MB to give the VMM when loading"); REQUIRE_THROWS_WITH_AS(bfm.parse_args({"./test.exe", "-om"}), "Unknown argument: -om", std::runtime_error); diff --git a/test/test_is_used.cpp b/test/test_is_used.cpp index 4d0f7a4..8d67b85 100644 --- a/test/test_is_used.cpp +++ b/test/test_is_used.cpp @@ -1,22 +1,20 @@ -#include #include +#include using doctest::test_suite; TEST_CASE("User-supplied argument" * test_suite("is_used")) { argparse::ArgumentParser program("test"); - program.add_argument("--dir") - .default_value(std::string("/")); - program.parse_args({ "test", "--dir", "/home/user" }); + program.add_argument("--dir").default_value(std::string("/")); + program.parse_args({"test", "--dir", "/home/user"}); REQUIRE(program.get("--dir") == "/home/user"); REQUIRE(program.is_used("--dir") == true); } TEST_CASE("Not user-supplied argument" * test_suite("is_used")) { argparse::ArgumentParser program("test"); - program.add_argument("--dir") - .default_value(std::string("/")); - program.parse_args({ "test" }); + program.add_argument("--dir").default_value(std::string("/")); + program.parse_args({"test"}); REQUIRE(program.get("--dir") == "/"); REQUIRE(program.is_used("--dir") == false); } diff --git a/test/test_issue_37.cpp b/test/test_issue_37.cpp index caa80a4..ab9c984 100644 --- a/test/test_issue_37.cpp +++ b/test/test_issue_37.cpp @@ -1,39 +1,38 @@ -#include #include +#include using doctest::test_suite; TEST_CASE("Issues with implicit values #37" * test_suite("implicit_values")) { argparse::ArgumentParser m_bfm("test"); - m_bfm.add_argument("-l", "--load") - .help("load a VMM into the kernel"); - + m_bfm.add_argument("-l", "--load").help("load a VMM into the kernel"); + m_bfm.add_argument("-u", "--unload") - .default_value(false) - .implicit_value(true) - .help("unload a previously loaded VMM"); - + .default_value(false) + .implicit_value(true) + .help("unload a previously loaded VMM"); + m_bfm.add_argument("-x", "--start") - .default_value(false) - .implicit_value(true) - .help("start a previously loaded VMM"); - + .default_value(false) + .implicit_value(true) + .help("start a previously loaded VMM"); + m_bfm.add_argument("-s", "--stop") - .default_value(false) - .implicit_value(true) - .help("stop a previously started VMM"); + .default_value(false) + .implicit_value(true) + .help("stop a previously started VMM"); m_bfm.add_argument("-d", "--dump") - .default_value(false) - .implicit_value(true) - .help("output the contents of the VMM's debug buffer"); + .default_value(false) + .implicit_value(true) + .help("output the contents of the VMM's debug buffer"); m_bfm.add_argument("-m", "--mem") - .default_value(100) - .required() - .scan<'u', unsigned long long>() - .help("memory in MB to give the VMM when loading"); - m_bfm.parse_args({ "test", "-l", "blah", "-d", "-u" }); + .default_value(100) + .required() + .scan<'u', unsigned long long>() + .help("memory in MB to give the VMM when loading"); + m_bfm.parse_args({"test", "-l", "blah", "-d", "-u"}); REQUIRE(m_bfm.get("--load") == "blah"); REQUIRE(m_bfm.get("-l") == "blah"); diff --git a/test/test_negative_numbers.cpp b/test/test_negative_numbers.cpp index 0e8ddb0..fd9b1f9 100644 --- a/test/test_negative_numbers.cpp +++ b/test/test_negative_numbers.cpp @@ -1,18 +1,16 @@ -#include #include +#include using doctest::test_suite; TEST_CASE("Parse negative integer" * test_suite("positional_arguments")) { argparse::ArgumentParser program; program.add_argument("--verbose", "-v") - .help("enable verbose logging") - .default_value(false) - .implicit_value(true); + .help("enable verbose logging") + .default_value(false) + .implicit_value(true); - program.add_argument("number") - .help("Input number") - .scan<'i', int>(); + program.add_argument("number").help("Input number").scan<'i', int>(); program.parse_args({"./main", "-1"}); REQUIRE(program.get("number") == -1); @@ -22,14 +20,11 @@ TEST_CASE("Parse negative integers into a vector" * test_suite("positional_arguments")) { argparse::ArgumentParser program; program.add_argument("--verbose", "-v") - .help("enable verbose logging") - .default_value(false) - .implicit_value(true); + .help("enable verbose logging") + .default_value(false) + .implicit_value(true); - program.add_argument("number") - .help("Input number") - .nargs(3) - .scan<'i', int>(); + program.add_argument("number").help("Input number").nargs(3).scan<'i', int>(); program.parse_args({"./main", "-1", "-2", "3"}); REQUIRE(program["number"] == std::vector{-1, -2, 3}); @@ -38,13 +33,11 @@ TEST_CASE("Parse negative integers into a vector" * TEST_CASE("Parse negative float" * test_suite("positional_arguments")) { argparse::ArgumentParser program; program.add_argument("--verbose", "-v") - .help("enable verbose logging") - .default_value(false) - .implicit_value(true); + .help("enable verbose logging") + .default_value(false) + .implicit_value(true); - program.add_argument("number") - .help("Input number") - .scan<'g', float>(); + program.add_argument("number").help("Input number").scan<'g', float>(); program.parse_args({"./main", "-1.0"}); REQUIRE(program.get("number") == -1.0); @@ -54,14 +47,14 @@ TEST_CASE("Parse negative floats into a vector" * test_suite("positional_arguments")) { argparse::ArgumentParser program; program.add_argument("--verbose", "-v") - .help("enable verbose logging") - .default_value(false) - .implicit_value(true); + .help("enable verbose logging") + .default_value(false) + .implicit_value(true); program.add_argument("number") - .help("Input number") - .nargs(3) - .scan<'g', double>(); + .help("Input number") + .nargs(3) + .scan<'g', double>(); program.parse_args({"./main", "-1.001", "-2.002", "3.003"}); REQUIRE(program["number"] == std::vector{-1.001, -2.002, 3.003}); @@ -70,13 +63,11 @@ TEST_CASE("Parse negative floats into a vector" * TEST_CASE("Parse numbers in E notation" * test_suite("positional_arguments")) { argparse::ArgumentParser program; program.add_argument("--verbose", "-v") - .help("enable verbose logging") - .default_value(false) - .implicit_value(true); + .help("enable verbose logging") + .default_value(false) + .implicit_value(true); - program.add_argument("number") - .help("Input number") - .scan<'g', double>(); + program.add_argument("number").help("Input number").scan<'g', double>(); program.parse_args({"./main", "-1.2e3"}); REQUIRE(program.get("number") == -1200.0); @@ -86,13 +77,11 @@ TEST_CASE("Parse numbers in E notation (capital E)" * test_suite("positional_arguments")) { argparse::ArgumentParser program; program.add_argument("--verbose", "-v") - .help("enable verbose logging") - .default_value(false) - .implicit_value(true); + .help("enable verbose logging") + .default_value(false) + .implicit_value(true); - program.add_argument("number") - .help("Input number") - .scan<'g', double>(); + program.add_argument("number").help("Input number").scan<'g', double>(); program.parse_args({"./main", "-1.32E4"}); REQUIRE(program.get("number") == -13200.0); diff --git a/test/test_optional_arguments.cpp b/test/test_optional_arguments.cpp index 5f90984..dd9cec6 100644 --- a/test/test_optional_arguments.cpp +++ b/test/test_optional_arguments.cpp @@ -1,5 +1,5 @@ -#include #include +#include using doctest::test_suite; @@ -7,10 +7,10 @@ TEST_CASE("Parse toggle arguments with default value" * test_suite("optional_arguments")) { argparse::ArgumentParser program("test"); program.add_argument("--verbose", "-v") - .default_value(false) - .implicit_value(true); + .default_value(false) + .implicit_value(true); - program.parse_args({ "./test.exe" }); + program.parse_args({"./test.exe"}); REQUIRE(program.get("--verbose") == false); REQUIRE(program["--verbose"] == false); } @@ -19,18 +19,16 @@ TEST_CASE("Argument '-' is not an optional argument" * test_suite("optional_arguments")) { argparse::ArgumentParser program("test"); program.add_argument("input"); - program.parse_args({ "./test.exe", "-"}); + program.parse_args({"./test.exe", "-"}); REQUIRE(program.get("input") == "-"); } TEST_CASE("Argument '-' is not an optional argument but '-l' is" * test_suite("optional_arguments")) { argparse::ArgumentParser program("test"); - program.add_argument("-l") - .default_value(false) - .implicit_value(true); + program.add_argument("-l").default_value(false).implicit_value(true); program.add_argument("input"); - program.parse_args({ "./test.exe", "-l", "-"}); + program.parse_args({"./test.exe", "-l", "-"}); REQUIRE(program.get("-l") == true); REQUIRE(program.get("input") == "-"); } @@ -38,11 +36,9 @@ TEST_CASE("Argument '-' is not an optional argument but '-l' is" * TEST_CASE("Argument '-l' is an optional argument but '-' is not" * test_suite("optional_arguments")) { argparse::ArgumentParser program("test"); - program.add_argument("-l") - .default_value(false) - .implicit_value(true); + program.add_argument("-l").default_value(false).implicit_value(true); program.add_argument("input"); - program.parse_args({ "./test.exe", "-", "-l"}); + program.parse_args({"./test.exe", "-", "-l"}); REQUIRE(program.get("-l") == true); REQUIRE(program.get("input") == "-"); } @@ -50,11 +46,9 @@ TEST_CASE("Argument '-l' is an optional argument but '-' is not" * TEST_CASE("Parse toggle arguments with implicit value" * test_suite("optional_arguments")) { argparse::ArgumentParser program("test"); - program.add_argument("--verbose") - .default_value(false) - .implicit_value(true); + program.add_argument("--verbose").default_value(false).implicit_value(true); - program.parse_args({ "./test.exe", "--verbose" }); + program.parse_args({"./test.exe", "--verbose"}); REQUIRE(program.get("--verbose") == true); REQUIRE(program["--verbose"] == true); REQUIRE(program["--verbose"] != false); @@ -63,19 +57,13 @@ TEST_CASE("Parse toggle arguments with implicit value" * TEST_CASE("Parse multiple toggle arguments with implicit values" * test_suite("optional_arguments")) { argparse::ArgumentParser program("test"); - program.add_argument("-a") - .default_value(false) - .implicit_value(true); + program.add_argument("-a").default_value(false).implicit_value(true); - program.add_argument("-u") - .default_value(false) - .implicit_value(true); + program.add_argument("-u").default_value(false).implicit_value(true); - program.add_argument("-x") - .default_value(false) - .implicit_value(true); + program.add_argument("-x").default_value(false).implicit_value(true); - program.parse_args({ "./test.exe", "-a", "-x" }); + program.parse_args({"./test.exe", "-a", "-x"}); REQUIRE(program.get("-a") == true); REQUIRE(program.get("-u") == false); REQUIRE(program.get("-x") == true); @@ -114,7 +102,9 @@ TEST_CASE("Parse 2 optional arguments of many values" * test_suite("optional_arguments")) { GIVEN("a program that accepts 2 optional arguments of many values") { argparse::ArgumentParser program("test"); - program.add_argument("-i").nargs(argparse::nargs_pattern::any).scan<'i', int>(); + program.add_argument("-i") + .nargs(argparse::nargs_pattern::any) + .scan<'i', int>(); program.add_argument("-s").nargs(argparse::nargs_pattern::any); WHEN("provided no argument") { @@ -129,8 +119,8 @@ TEST_CASE("Parse 2 optional arguments of many values" * } WHEN("provided 2 options with many arguments") { - program.parse_args( - {"test", "-i", "-42", "8", "100", "300", "-s", "ok", "this", "works"}); + program.parse_args({"test", "-i", "-42", "8", "100", "300", "-s", "ok", + "this", "works"}); THEN("the optional parameter consumes each arguments") { auto i = program.get>("-i"); @@ -171,8 +161,7 @@ TEST_CASE("Parse an optional argument of many values" } WHEN("provided many arguments followed by an option with many arguments") { - program.parse_args( - {"test", "foo", "bar", "-s", "ok", "this", "works"}); + program.parse_args({"test", "foo", "bar", "-s", "ok", "this", "works"}); THEN("the parameters consume each arguments") { auto s = program.get>("-s"); diff --git a/test/test_parent_parsers.cpp b/test/test_parent_parsers.cpp index 301309f..ffb9e00 100644 --- a/test/test_parent_parsers.cpp +++ b/test/test_parent_parsers.cpp @@ -1,17 +1,17 @@ -#include #include +#include using doctest::test_suite; TEST_CASE("Add parent parsers" * test_suite("parent_parsers")) { argparse::ArgumentParser parent_parser("main"); parent_parser.add_argument("--verbose") - .default_value(false) - .implicit_value(true); + .default_value(false) + .implicit_value(true); argparse::ArgumentParser child_parser("foo"); child_parser.add_parents(parent_parser); - child_parser.parse_args({ "./main", "--verbose"}); + child_parser.parse_args({"./main", "--verbose"}); REQUIRE(child_parser["--verbose"] == true); REQUIRE(parent_parser["--verbose"] == false); } @@ -19,20 +19,18 @@ TEST_CASE("Add parent parsers" * test_suite("parent_parsers")) { TEST_CASE("Add parent to multiple parent parsers" * test_suite("parent_parsers")) { argparse::ArgumentParser parent_parser("main"); - parent_parser.add_argument("--parent") - .default_value(0) - .scan<'i', int>(); + parent_parser.add_argument("--parent").default_value(0).scan<'i', int>(); argparse::ArgumentParser foo_parser("foo"); foo_parser.add_argument("foo"); foo_parser.add_parents(parent_parser); - foo_parser.parse_args({ "./main", "--parent", "2", "XXX" }); + foo_parser.parse_args({"./main", "--parent", "2", "XXX"}); REQUIRE(foo_parser["--parent"] == 2); REQUIRE(foo_parser["foo"] == std::string("XXX")); REQUIRE(parent_parser["--parent"] == 0); argparse::ArgumentParser bar_parser("bar"); bar_parser.add_argument("--bar"); - bar_parser.parse_args({ "./main", "--bar", "YYY" }); + bar_parser.parse_args({"./main", "--bar", "YYY"}); REQUIRE(bar_parser["--bar"] == std::string("YYY")); } diff --git a/test/test_parse_args.cpp b/test/test_parse_args.cpp index 146dfff..76e7f0e 100644 --- a/test/test_parse_args.cpp +++ b/test/test_parse_args.cpp @@ -1,12 +1,12 @@ -#include #include +#include using doctest::test_suite; TEST_CASE("Missing argument" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); program.add_argument("--config").nargs(1); - REQUIRE_THROWS_WITH_AS(program.parse_args({ "test", "--config" }), + REQUIRE_THROWS_WITH_AS(program.parse_args({"test", "--config"}), "Too few arguments for '--config'.", std::runtime_error); } @@ -14,16 +14,15 @@ TEST_CASE("Missing argument" * test_suite("parse_args")) { TEST_CASE("Parse a string argument with value" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); program.add_argument("--config"); - program.parse_args({ "test", "--config", "config.yml"}); + program.parse_args({"test", "--config", "config.yml"}); REQUIRE(program.get("--config") == "config.yml"); } TEST_CASE("Parse a string argument with default value" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); - program.add_argument("--config") - .default_value(std::string("foo.yml")); - program.parse_args({ "test", "--config" }); + program.add_argument("--config").default_value(std::string("foo.yml")); + program.parse_args({"test", "--config"}); REQUIRE(program.get("--config") == "foo.yml"); } @@ -55,64 +54,53 @@ TEST_CASE("Parse a string argument without default value" * TEST_CASE("Parse an int argument with value" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); - program.add_argument("--count") - .scan<'i', int>(); - program.parse_args({ "test", "--count", "5" }); + program.add_argument("--count").scan<'i', int>(); + program.parse_args({"test", "--count", "5"}); REQUIRE(program.get("--count") == 5); } TEST_CASE("Parse an int argument with default value" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); - program.add_argument("--count") - .default_value(2) - .scan<'i', int>(); - program.parse_args({ "test", "--count" }); + program.add_argument("--count").default_value(2).scan<'i', int>(); + program.parse_args({"test", "--count"}); REQUIRE(program.get("--count") == 2); } TEST_CASE("Parse a float argument with value" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); - program.add_argument("--ratio") - .scan<'g', float>(); - program.parse_args({ "test", "--ratio", "5.6645" }); + program.add_argument("--ratio").scan<'g', float>(); + program.parse_args({"test", "--ratio", "5.6645"}); REQUIRE(program.get("--ratio") == 5.6645f); } TEST_CASE("Parse a float argument with default value" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); - program.add_argument("--ratio") - .default_value(3.14f) - .scan<'g', float>(); - program.parse_args({ "test", "--ratio" }); + program.add_argument("--ratio").default_value(3.14f).scan<'g', float>(); + program.parse_args({"test", "--ratio"}); REQUIRE(program.get("--ratio") == 3.14f); } TEST_CASE("Parse a double argument with value" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); - program.add_argument("--ratio") - .scan<'g', double>(); - program.parse_args({ "test", "--ratio", "5.6645" }); + program.add_argument("--ratio").scan<'g', double>(); + program.parse_args({"test", "--ratio", "5.6645"}); REQUIRE(program.get("--ratio") == 5.6645); } TEST_CASE("Parse a double argument with default value" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); - program.add_argument("--ratio") - .default_value(3.14) - .scan<'g', double>(); - program.parse_args({ "test", "--ratio" }); + program.add_argument("--ratio").default_value(3.14).scan<'g', double>(); + program.parse_args({"test", "--ratio"}); REQUIRE(program.get("--ratio") == 3.14); } TEST_CASE("Parse a vector of integer arguments" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); - program.add_argument("--vector") - .nargs(5) - .scan<'i', int>(); - program.parse_args({ "test", "--vector", "1", "2", "3", "4", "5" }); + program.add_argument("--vector").nargs(5).scan<'i', int>(); + program.parse_args({"test", "--vector", "1", "2", "3", "4", "5"}); auto vector = program.get>("--vector"); REQUIRE(vector.size() == 5); REQUIRE(vector[0] == 1); @@ -124,10 +112,8 @@ TEST_CASE("Parse a vector of integer arguments" * test_suite("parse_args")) { TEST_CASE("Parse a vector of float arguments" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); - program.add_argument("--vector") - .nargs(5) - .scan<'g', float>(); - program.parse_args({ "test", "--vector", "1.1", "2.2", "3.3", "4.4", "5.5" }); + program.add_argument("--vector").nargs(5).scan<'g', float>(); + program.parse_args({"test", "--vector", "1.1", "2.2", "3.3", "4.4", "5.5"}); auto vector = program.get>("--vector"); REQUIRE(vector.size() == 5); REQUIRE(vector[0] == 1.1f); @@ -170,10 +156,8 @@ TEST_CASE("Parse a vector of float without default value" * TEST_CASE("Parse a vector of double arguments" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); - program.add_argument("--vector") - .nargs(5) - .scan<'g', double>(); - program.parse_args({ "test", "--vector", "1.1", "2.2", "3.3", "4.4", "5.5" }); + program.add_argument("--vector").nargs(5).scan<'g', double>(); + program.parse_args({"test", "--vector", "1.1", "2.2", "3.3", "4.4", "5.5"}); auto vector = program.get>("--vector"); REQUIRE(vector.size() == 5); REQUIRE(vector[0] == 1.1); @@ -185,9 +169,8 @@ TEST_CASE("Parse a vector of double arguments" * test_suite("parse_args")) { TEST_CASE("Parse a vector of string arguments" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); - program.add_argument("--vector") - .nargs(5); - program.parse_args({ "test", "--vector", "abc", "def", "ghi", "jkl", "mno" }); + program.add_argument("--vector").nargs(5); + program.parse_args({"test", "--vector", "abc", "def", "ghi", "jkl", "mno"}); auto vector = program.get>("--vector"); REQUIRE(vector.size() == 5); REQUIRE(vector[0] == "abc"); @@ -200,9 +183,9 @@ TEST_CASE("Parse a vector of string arguments" * test_suite("parse_args")) { TEST_CASE("Parse a vector of character arguments" * test_suite("parse_args")) { argparse::ArgumentParser program("test"); program.add_argument("--vector") - .nargs(5) - .action([](const std::string& value) { return value[0]; }); - program.parse_args({ "test", "--vector", "a", "b", "c", "d", "e" }); + .nargs(5) + .action([](const std::string &value) { return value[0]; }); + program.parse_args({"test", "--vector", "a", "b", "c", "d", "e"}); auto vector = program.get>("--vector"); REQUIRE(vector.size() == 5); REQUIRE(vector[0] == 'a'); @@ -217,15 +200,15 @@ TEST_CASE("Parse a vector of string arguments and construct objects" * class Foo { public: - Foo(const std::string& value) : value(value) {} + Foo(const std::string &value) : value(value) {} std::string value; }; argparse::ArgumentParser program("test"); program.add_argument("--vector") - .nargs(5) - .action([](const std::string& value) { return Foo(value); }); - program.parse_args({ "test", "--vector", "abc", "def", "ghi", "jkl", "mno" }); + .nargs(5) + .action([](const std::string &value) { return Foo(value); }); + program.parse_args({"test", "--vector", "abc", "def", "ghi", "jkl", "mno"}); auto vector = program.get>("--vector"); REQUIRE(vector.size() == 5); REQUIRE(vector[0].value == Foo("abc").value); diff --git a/test/test_positional_arguments.cpp b/test/test_positional_arguments.cpp index 459f5dc..0875669 100644 --- a/test/test_positional_arguments.cpp +++ b/test/test_positional_arguments.cpp @@ -1,6 +1,6 @@ -#include #include #include +#include using doctest::test_suite; @@ -8,7 +8,7 @@ TEST_CASE("Parse positional arguments" * test_suite("positional_arguments")) { argparse::ArgumentParser program("test"); program.add_argument("input"); program.add_argument("output"); - program.parse_args({ "test", "rocket.mesh", "thrust_profile.csv" }); + program.parse_args({"test", "rocket.mesh", "thrust_profile.csv"}); REQUIRE(program.get("input") == "rocket.mesh"); REQUIRE(program.get("output") == "thrust_profile.csv"); } @@ -17,7 +17,7 @@ TEST_CASE("Missing expected positional argument" * test_suite("positional_arguments")) { argparse::ArgumentParser program("test"); program.add_argument("input"); - REQUIRE_THROWS_WITH_AS(program.parse_args({ "test" }), + REQUIRE_THROWS_WITH_AS(program.parse_args({"test"}), "1 argument(s) expected. 0 provided.", std::runtime_error); } @@ -27,7 +27,8 @@ TEST_CASE("Parse positional arguments with fixed nargs" * argparse::ArgumentParser program("test"); program.add_argument("input"); program.add_argument("output").nargs(2); - program.parse_args({ "test", "rocket.mesh", "thrust_profile.csv", "output.mesh" }); + program.parse_args( + {"test", "rocket.mesh", "thrust_profile.csv", "output.mesh"}); REQUIRE(program.get("input") == "rocket.mesh"); auto outputs = program.get>("output"); REQUIRE(outputs.size() == 2); @@ -40,9 +41,9 @@ TEST_CASE("Parse positional arguments with optional arguments" * argparse::ArgumentParser program("test"); program.add_argument("input"); program.add_argument("output").nargs(2); - program.add_argument("--num_iterations") - .scan<'i', int>(); - program.parse_args({ "test", "rocket.mesh", "--num_iterations", "15", "thrust_profile.csv", "output.mesh" }); + program.add_argument("--num_iterations").scan<'i', int>(); + program.parse_args({"test", "rocket.mesh", "--num_iterations", "15", + "thrust_profile.csv", "output.mesh"}); REQUIRE(program.get("--num_iterations") == 15); REQUIRE(program.get("input") == "rocket.mesh"); auto outputs = program.get>("output"); @@ -56,14 +57,16 @@ TEST_CASE("Parse positional arguments with optional arguments in the middle" * argparse::ArgumentParser program("test"); program.add_argument("input"); program.add_argument("output").nargs(2); - program.add_argument("--num_iterations") - .scan<'i', int>(); - REQUIRE_THROWS(program.parse_args({ "test", "rocket.mesh", "thrust_profile.csv", "--num_iterations", "15", "output.mesh" })); + program.add_argument("--num_iterations").scan<'i', int>(); + REQUIRE_THROWS( + program.parse_args({"test", "rocket.mesh", "thrust_profile.csv", + "--num_iterations", "15", "output.mesh"})); } TEST_CASE("Parse positional nargs=1..2 arguments" * test_suite("positional_arguments")) { - GIVEN("a program that accepts an optional argument and nargs=1..2 positional arguments") { + GIVEN("a program that accepts an optional argument and nargs=1..2 positional " + "arguments") { argparse::ArgumentParser program("test"); program.add_argument("-o"); program.add_argument("input").nargs(1, 2); @@ -131,7 +134,8 @@ TEST_CASE("Parse positional nargs=1..2 arguments" * WHEN("provided an optional in between positional arguments") { THEN("the program does not accept it") { - REQUIRE_THROWS(program.parse_args({"test", "a.c", "-o", "a.out", "b.c"})); + REQUIRE_THROWS( + program.parse_args({"test", "a.c", "-o", "a.out", "b.c"})); } } } @@ -139,7 +143,8 @@ TEST_CASE("Parse positional nargs=1..2 arguments" * TEST_CASE("Parse positional nargs=ANY arguments" * test_suite("positional_arguments")) { - GIVEN("a program that accepts an optional argument and nargs=ANY positional arguments") { + GIVEN("a program that accepts an optional argument and nargs=ANY positional " + "arguments") { argparse::ArgumentParser program("test"); program.add_argument("-o"); program.add_argument("input").nargs(argparse::nargs_pattern::any); @@ -236,19 +241,21 @@ TEST_CASE("Parse remaining arguments deemed positional" * TEST_CASE("Reversed order nargs is not allowed" * test_suite("positional_arguments")) { argparse::ArgumentParser program("test"); - REQUIRE_THROWS_AS(program.add_argument("output").nargs(2, 1), std::logic_error); + REQUIRE_THROWS_AS(program.add_argument("output").nargs(2, 1), + std::logic_error); } TEST_CASE("Square a number" * test_suite("positional_arguments")) { argparse::ArgumentParser program; program.add_argument("--verbose", "-v") - .help("enable verbose logging") - .default_value(false) - .implicit_value(true); + .help("enable verbose logging") + .default_value(false) + .implicit_value(true); program.add_argument("square") - .help("display a square of a given number") - .action([](const std::string& value) { return pow(std::stoi(value), 2); }); + .help("display a square of a given number") + .action( + [](const std::string &value) { return pow(std::stoi(value), 2); }); program.parse_args({"./main", "15"}); REQUIRE(program.get("square") == 225); diff --git a/test/test_required_arguments.cpp b/test/test_required_arguments.cpp index 9f98437..299808a 100644 --- a/test/test_required_arguments.cpp +++ b/test/test_required_arguments.cpp @@ -1,5 +1,5 @@ -#include #include +#include using doctest::test_suite; diff --git a/test/test_subparsers.cpp b/test/test_subparsers.cpp index 19d4e60..c40ec1d 100644 --- a/test/test_subparsers.cpp +++ b/test/test_subparsers.cpp @@ -1,6 +1,6 @@ -#include #include #include +#include using doctest::test_suite; @@ -16,7 +16,7 @@ TEST_CASE("Add subparsers" * test_suite("subparsers")) { program.add_subparser(command_1); program.add_subparser(command_2); - program.parse_args({ "test", "--output", "thrust_profile.csv" }); + program.parse_args({"test", "--output", "thrust_profile.csv"}); REQUIRE(program.get("--output") == "thrust_profile.csv"); } @@ -29,49 +29,82 @@ TEST_CASE("Parse subparser command" * test_suite("subparsers")) { argparse::ArgumentParser command_2("clean"); command_2.add_argument("--fullclean") - .default_value(false) - .implicit_value(true); + .default_value(false) + .implicit_value(true); program.add_subparser(command_1); program.add_subparser(command_2); SUBCASE("command 1") { - program.parse_args({ "test", "add", "file1.txt", "file2.txt" }); + program.parse_args({"test", "add", "file1.txt", "file2.txt"}); REQUIRE(command_1.is_used("file")); - REQUIRE((command_1.get>("file") == std::vector{"file1.txt", "file2.txt"})); + REQUIRE((command_1.get>("file") == + std::vector{"file1.txt", "file2.txt"})); } SUBCASE("command 2") { - program.parse_args({ "test", "clean", "--fullclean" }); + program.parse_args({"test", "clean", "--fullclean"}); REQUIRE(command_2.get("--fullclean") == true); } } -TEST_CASE("Parse subparser command with optional argument" * test_suite("subparsers")) { +TEST_CASE("Parse subparser command with optional argument" * + test_suite("subparsers")) { argparse::ArgumentParser program("test"); - program.add_argument("--verbose") - .default_value(false) - .implicit_value(true); + program.add_argument("--verbose").default_value(false).implicit_value(true); argparse::ArgumentParser command_1("add"); command_1.add_argument("file"); argparse::ArgumentParser command_2("clean"); command_2.add_argument("--fullclean") - .default_value(false) - .implicit_value(true); + .default_value(false) + .implicit_value(true); program.add_subparser(command_1); program.add_subparser(command_2); SUBCASE("Optional argument BEFORE subcommand") { - program.parse_args({ "test", "--verbose", "clean", "--fullclean" }); + program.parse_args({"test", "--verbose", "clean", "--fullclean"}); REQUIRE(program.get("--verbose") == true); REQUIRE(command_2.get("--fullclean") == true); } SUBCASE("Optional argument AFTER subcommand") { - REQUIRE_THROWS_WITH_AS(program.parse_args({ "test", "clean", "--fullclean", "--verbose" }), + REQUIRE_THROWS_WITH_AS( + program.parse_args({"test", "clean", "--fullclean", "--verbose"}), + "Unknown argument: --verbose", std::runtime_error); + } +} + +TEST_CASE("Parse subparser command with parent parser" * + test_suite("subparsers")) { + argparse::ArgumentParser program("test"); + + argparse::ArgumentParser parent("parent"); + parent.add_argument("--verbose").default_value(false).implicit_value(true); + program.add_parents(parent); + + argparse::ArgumentParser command_1("add"); + command_1.add_argument("file"); + + argparse::ArgumentParser command_2("clean"); + command_2.add_argument("--fullclean") + .default_value(false) + .implicit_value(true); + + program.add_subparser(command_1); + program.add_subparser(command_2); + + SUBCASE("Optional argument BEFORE subcommand") { + program.parse_args({"test", "--verbose", "clean", "--fullclean"}); + REQUIRE(program.get("--verbose") == true); + REQUIRE(command_2.get("--fullclean") == true); + } + + SUBCASE("Optional argument AFTER subcommand") { + REQUIRE_THROWS_WITH_AS( + program.parse_args({"test", "clean", "--fullclean", "--verbose"}), "Unknown argument: --verbose", std::runtime_error); } } @@ -80,13 +113,10 @@ TEST_CASE("Parse git commands" * test_suite("subparsers")) { argparse::ArgumentParser program("git"); argparse::ArgumentParser add_command("add"); - add_command.add_argument("files") - .remaining(); + add_command.add_argument("files").remaining(); argparse::ArgumentParser commit_command("commit"); - commit_command.add_argument("-a") - .default_value(false) - .implicit_value(true); + commit_command.add_argument("-a").default_value(false).implicit_value(true); commit_command.add_argument("-m"); @@ -97,11 +127,11 @@ TEST_CASE("Parse git commands" * test_suite("subparsers")) { argparse::ArgumentParser submodule_command("submodule"); argparse::ArgumentParser submodule_update_command("update"); submodule_update_command.add_argument("--init") - .default_value(false) - .implicit_value(true); + .default_value(false) + .implicit_value(true); submodule_update_command.add_argument("--recursive") - .default_value(false) - .implicit_value(true); + .default_value(false) + .implicit_value(true); submodule_command.add_subparser(submodule_update_command); program.add_subparser(add_command); @@ -110,43 +140,45 @@ TEST_CASE("Parse git commands" * test_suite("subparsers")) { program.add_subparser(submodule_command); SUBCASE("git add") { - program.parse_args({ "git", "add", "main.cpp", "foo.hpp", "foo.cpp" }); - REQUIRE((add_command.get>("files") == std::vector{"main.cpp", "foo.hpp", "foo.cpp"})); + program.parse_args({"git", "add", "main.cpp", "foo.hpp", "foo.cpp"}); + REQUIRE((add_command.get>("files") == + std::vector{"main.cpp", "foo.hpp", "foo.cpp"})); } SUBCASE("git commit") { - program.parse_args({ "git", "commit", "-am", "Initial commit" }); + program.parse_args({"git", "commit", "-am", "Initial commit"}); REQUIRE(commit_command.get("-a") == true); - REQUIRE(commit_command.get("-m") == std::string{"Initial commit"}); + REQUIRE(commit_command.get("-m") == + std::string{"Initial commit"}); } SUBCASE("git cat-file -t") { - program.parse_args({ "git", "cat-file", "-t", "3739f5" }); + program.parse_args({"git", "cat-file", "-t", "3739f5"}); REQUIRE(catfile_command.get("-t") == std::string{"3739f5"}); } SUBCASE("git cat-file -p") { - program.parse_args({ "git", "cat-file", "-p", "3739f5" }); + program.parse_args({"git", "cat-file", "-p", "3739f5"}); REQUIRE(catfile_command.get("-p") == std::string{"3739f5"}); } SUBCASE("git submodule update") { - program.parse_args({ "git", "submodule", "update" }); + program.parse_args({"git", "submodule", "update"}); } SUBCASE("git submodule update --init") { - program.parse_args({ "git", "submodule", "update", "--init" }); + program.parse_args({"git", "submodule", "update", "--init"}); REQUIRE(submodule_update_command.get("--init") == true); REQUIRE(submodule_update_command.get("--recursive") == false); } SUBCASE("git submodule update --recursive") { - program.parse_args({ "git", "submodule", "update", "--recursive" }); + program.parse_args({"git", "submodule", "update", "--recursive"}); REQUIRE(submodule_update_command.get("--recursive") == true); } SUBCASE("git submodule update --init --recursive") { - program.parse_args({ "git", "submodule", "update", "--init", "--recursive" }); + program.parse_args({"git", "submodule", "update", "--init", "--recursive"}); REQUIRE(submodule_update_command.get("--init") == true); REQUIRE(submodule_update_command.get("--recursive") == true); } diff --git a/test/test_version.cpp b/test/test_version.cpp index aba2e26..377126e 100644 --- a/test/test_version.cpp +++ b/test/test_version.cpp @@ -1,15 +1,14 @@ -#include #include +#include #include using doctest::test_suite; -TEST_CASE("Users can print version and exit" * test_suite("version") - * doctest::skip()) { +TEST_CASE("Users can print version and exit" * test_suite("version") * + doctest::skip()) { argparse::ArgumentParser program("cli-test", "1.9.0"); - program.add_argument("-d", "--dir") - .required(); - program.parse_args( { "test", "--version" }); + program.add_argument("-d", "--dir").required(); + program.parse_args({"test", "--version"}); REQUIRE(program.get("--version") == "1.9.0"); } @@ -21,17 +20,15 @@ TEST_CASE("Users can disable default -v/--version" * test_suite("version")) { } TEST_CASE("Users can replace default -v/--version" * test_suite("version")) { - std::string version { "3.1415" }; + std::string version{"3.1415"}; argparse::ArgumentParser program("test", version, argparse::default_arguments::help); std::stringstream buffer; program.add_argument("-v", "--version") - .action([&](const auto &) { - buffer << version; - }) - .default_value(true) - .implicit_value(false) - .nargs(0); + .action([&](const auto &) { buffer << version; }) + .default_value(true) + .implicit_value(false) + .nargs(0); REQUIRE(buffer.str().empty()); program.parse_args({"test", "--version"});