diff --git a/src/argparse.hpp b/src/argparse.hpp index 78921af..9557e75 100644 --- a/src/argparse.hpp +++ b/src/argparse.hpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,16 @@ bool starts_with(const std::string& haystack, const std::string& needle) { && std::equal(needle.begin(), needle.end(), haystack.begin()); }; +template +T get_from_list(const std::list& aList, size_t aIndex) { + if (aList.size() > aIndex) { + auto tIterator = aList.begin(); + std::advance(tIterator, aIndex); + return *tIterator; + } + return T(); +} + struct Argument { std::vector mNames; std::string mHelp; @@ -142,11 +153,46 @@ struct Argument { } } + template + T get_list() { + T tResult; + if (mValues.size() == 0) { + if (mDefaultValue.has_value()) { + T tDefaultValues = std::any_cast(mDefaultValue); + for (size_t i = 0; i < tDefaultValues.size(); i++) { + tResult.push_back(std::any_cast(get_from_list(tDefaultValues, i))); + } + return tResult; + } + else + return T(); + } + else { + if (mRawValues.size() > 0) { + for (size_t i = 0; i < mValues.size(); i++) { + tResult.push_back(std::any_cast(mValues[i])); + } + return tResult; + } + else { + if (mDefaultValue.has_value()) { + std::list tDefaultValues = std::any_cast>(mDefaultValue); + for (size_t i = 0; i < tDefaultValues.size(); i++) { + tResult.push_back(std::any_cast(get_from_list(tDefaultValues, i))); + } + return tResult; + } + else + return T(); + } + } + } + }; class ArgumentParser { public: - ArgumentParser(const std::string& aProgramName) : + ArgumentParser(const std::string& aProgramName = "") : mProgramName(aProgramName), mNextPositionalArgument(0) {} @@ -179,6 +225,8 @@ class ArgumentParser { } void parse_args(int argc, char * argv[]) { + if (mProgramName == "" && argc > 0) + mProgramName = argv[0]; for (int i = 1; i < argc; i++) { auto tCurrentArgument = argv[i]; std::map>::iterator tIterator = mArgumentMap.find(argv[i]); @@ -270,7 +318,8 @@ class ArgumentParser { } template - typename std::enable_if::value == false, T>::type + typename std::enable_if::value == false && + is_specialization::value == false, T>::type get(const char * aArgumentName) { std::map>::iterator tIterator = mArgumentMap.find(aArgumentName); if (tIterator != mArgumentMap.end()) { @@ -289,6 +338,16 @@ class ArgumentParser { return T(); } + template + typename std::enable_if::value, T>::type + get(const char * aArgumentName) { + std::map>::iterator tIterator = mArgumentMap.find(aArgumentName); + if (tIterator != mArgumentMap.end()) { + return tIterator->second->get_list(); + } + return T(); + } + std::map> get_arguments() const { return mArgumentMap; } diff --git a/tests/main.cpp b/tests/main.cpp index 48b27de..3cc7b1a 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -6,4 +6,5 @@ #include #include #include -#include \ No newline at end of file +#include +#include \ No newline at end of file diff --git a/tests/test_vector_list_arguments.hpp b/tests/test_vector_list_arguments.hpp new file mode 100644 index 0000000..fc6429b --- /dev/null +++ b/tests/test_vector_list_arguments.hpp @@ -0,0 +1,53 @@ +#pragma once +#include +#include + +TEST_CASE("Parse vector of arguments", "[vector]") { + argparse::ArgumentParser program("test"); + program.add_argument("input") + .nargs(2); + + program.parse_args({ "test", "rocket.mesh", "thrust_profile.csv" }); + + auto arguments = program.get_arguments(); + REQUIRE(arguments.size() == 1); + + auto inputs = program.get>("input"); + REQUIRE(inputs.size() == 2); + REQUIRE(inputs[0] == "rocket.mesh"); + REQUIRE(inputs[1] == "thrust_profile.csv"); +} + +TEST_CASE("Parse list of arguments", "[vector]") { + argparse::ArgumentParser program("test"); + program.add_argument("input") + .nargs(2); + + program.parse_args({ "test", "rocket.mesh", "thrust_profile.csv" }); + + auto arguments = program.get_arguments(); + REQUIRE(arguments.size() == 1); + auto inputs = program.get>("input"); + REQUIRE(inputs.size() == 2); + REQUIRE(argparse::get_from_list(inputs, 0) == "rocket.mesh"); + REQUIRE(argparse::get_from_list(inputs, 1) == "thrust_profile.csv"); +} + +TEST_CASE("Parse list of arguments with default values", "[vector]") { + argparse::ArgumentParser program("test"); + program.add_argument("input") + .default_value(std::list{1, 2, 3, 4, 5}) + .nargs(2); + + program.parse_args({ "test" }); + + auto arguments = program.get_arguments(); + REQUIRE(arguments.size() == 1); + auto inputs = program.get>("input"); + REQUIRE(inputs.size() == 5); + REQUIRE(argparse::get_from_list(inputs, 0) == 1); + REQUIRE(argparse::get_from_list(inputs, 1) == 2); + REQUIRE(argparse::get_from_list(inputs, 2) == 3); + REQUIRE(argparse::get_from_list(inputs, 3) == 4); + REQUIRE(argparse::get_from_list(inputs, 4) == 5); +} \ No newline at end of file