diff --git a/src/argparse.hpp b/src/argparse.hpp index ed7ff53..f4316c2 100644 --- a/src/argparse.hpp +++ b/src/argparse.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include #include #include @@ -242,7 +243,14 @@ class ArgumentParser { public: ArgumentParser(const std::string& aProgramName = "") : mProgramName(aProgramName), - mNextPositionalArgument(0) {} + mNextPositionalArgument(0) { + std::shared_ptr tArgument = std::make_shared(); + tArgument->mNames = { "-h", "--help" }; + tArgument->mHelp = "show this help message and exit"; + mOptionalArguments.push_back(tArgument); + upsert(mArgumentMap, std::string("-h"), tArgument); + upsert(mArgumentMap, std::string("--help"), tArgument); + } template Argument& add_argument(T value, Targs... Fargs) { @@ -278,7 +286,11 @@ class ArgumentParser { if (mProgramName == "" && argc > 0) mProgramName = argv[0]; for (int i = 1; i < argc; i++) { - auto tCurrentArgument = argv[i]; + auto tCurrentArgument = std::string(argv[i]); + if (tCurrentArgument == "-h" || tCurrentArgument == "--help") { + print_help(); + exit(0); + } std::map>::iterator tIterator = mArgumentMap.find(argv[i]); if (tIterator != mArgumentMap.end()) { // Start parsing optional argument @@ -398,10 +410,6 @@ class ArgumentParser { return T(); } - std::map> get_arguments() const { - return mArgumentMap; - } - Argument& operator[](const std::string& aArgumentName) { std::map>::iterator tIterator = mArgumentMap.find(aArgumentName); if (tIterator != mArgumentMap.end()) { @@ -423,7 +431,8 @@ class ArgumentParser { } stream << "\n\n"; - stream << "Positional arguments:\n"; + if (mPositionalArguments.size() > 0) + stream << "Positional arguments:\n"; for (size_t i = 0; i < mPositionalArguments.size(); i++) { size_t tCurrentLength = 0; auto tNames = mPositionalArguments[i]->mNames; @@ -445,7 +454,10 @@ class ArgumentParser { stream << mPositionalArguments[i]->mHelp << "\n"; } - stream << "\nOptional arguments:\n"; + if (mOptionalArguments.size() > 0 && mPositionalArguments.size() > 0) + stream << "\nOptional arguments:\n"; + else if (mOptionalArguments.size() > 0) + stream << "Optional arguments:\n"; for (size_t i = 0; i < mOptionalArguments.size(); i++) { size_t tCurrentLength = 0; auto tNames = mOptionalArguments[i]->mNames; diff --git a/tests/main.cpp b/tests/main.cpp index 475bb81..8892744 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,7 +1,6 @@ #define CATCH_CONFIG_MAIN #include #include -#include #include #include #include diff --git a/tests/test_actions.hpp b/tests/test_actions.hpp index 9e7bfd8..357ad1c 100644 --- a/tests/test_actions.hpp +++ b/tests/test_actions.hpp @@ -15,7 +15,5 @@ TEST_CASE("Users can use defaul value inside actions", "[actions]") { }); program.parse_args({ "test", "fez" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); REQUIRE(program.get("input") == "bar"); } \ No newline at end of file diff --git a/tests/test_add_argument.hpp b/tests/test_add_argument.hpp deleted file mode 100644 index da3923b..0000000 --- a/tests/test_add_argument.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#include -#include - -TEST_CASE("Add a simple argument", "[add_argument]") { - argparse::ArgumentParser program("test"); - program.add_argument("--foo"); - - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); - REQUIRE(arguments["--foo"] != nullptr); - REQUIRE(arguments["--foo"]->mNames == std::vector{"--foo"}); - REQUIRE(arguments["--foo"]->mHelp == ""); - REQUIRE(arguments["--foo"]->mNumArgs == 1); - REQUIRE(arguments["--foo"]->mRawValues.size() == 0); - REQUIRE(arguments["--foo"]->mValues.size() == 0); -} - -TEST_CASE("Add a simple argument with help", "[add_argument]") { - argparse::ArgumentParser program("test"); - program.add_argument("--foo") - .help("input file"); - - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); - REQUIRE(arguments["--foo"] != nullptr); - REQUIRE(arguments["--foo"]->mNames == std::vector{"--foo"}); - REQUIRE(arguments["--foo"]->mHelp == "input file"); - REQUIRE(arguments["--foo"]->mNumArgs == 1); - REQUIRE(arguments["--foo"]->mRawValues.size() == 0); - REQUIRE(arguments["--foo"]->mValues.size() == 0); -} \ No newline at end of file diff --git a/tests/test_compound_arguments.hpp b/tests/test_compound_arguments.hpp index f171024..6413ea1 100644 --- a/tests/test_compound_arguments.hpp +++ b/tests/test_compound_arguments.hpp @@ -17,8 +17,6 @@ TEST_CASE("Parse compound toggle arguments with implicit values", "[compound_arg .implicit_value(true); program.parse_args({ "./test.exe", "-aux" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 3); REQUIRE(program.get("-a") == true); REQUIRE(program.get("-u") == true); REQUIRE(program.get("-x") == true); @@ -43,8 +41,6 @@ TEST_CASE("Parse compound toggle arguments with implicit values and nargs", "[co program.parse_args({ "./test.exe", "-abc", "3.14", "2.718", "--input_files", "a.txt", "b.txt", "c.txt" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 4); REQUIRE(program.get("-a") == true); REQUIRE(program.get("-b") == true); auto c = program.get>("-c"); @@ -83,8 +79,6 @@ TEST_CASE("Parse compound toggle arguments with implicit values and nargs and ot program.parse_args({ "./test.exe", "1", "-abc", "3.14", "2.718", "2", "--input_files", "a.txt", "b.txt", "c.txt", "3" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 5); REQUIRE(program.get("-a") == true); REQUIRE(program.get("-b") == true); auto c = program.get>("-c"); diff --git a/tests/test_container_arguments.hpp b/tests/test_container_arguments.hpp index 7ea4928..6e34eaf 100644 --- a/tests/test_container_arguments.hpp +++ b/tests/test_container_arguments.hpp @@ -9,9 +9,6 @@ TEST_CASE("Parse vector of arguments", "[vector]") { 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"); @@ -25,8 +22,6 @@ TEST_CASE("Parse list of arguments", "[vector]") { 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"); @@ -41,8 +36,6 @@ TEST_CASE("Parse list of arguments with default values", "[vector]") { 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); diff --git a/tests/test_optional_arguments.hpp b/tests/test_optional_arguments.hpp index a89154e..151f6ad 100644 --- a/tests/test_optional_arguments.hpp +++ b/tests/test_optional_arguments.hpp @@ -9,8 +9,6 @@ TEST_CASE("Parse toggle arguments with default value", "[optional_arguments]") { .implicit_value(true); program.parse_args({ "./test.exe" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 2); REQUIRE(program.get("--verbose") == false); REQUIRE(program["--verbose"] == false); } @@ -22,8 +20,6 @@ TEST_CASE("Parse toggle arguments with implicit value", "[optional_arguments]") .implicit_value(true); program.parse_args({ "./test.exe", "--verbose" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); REQUIRE(program.get("--verbose") == true); REQUIRE(program["--verbose"] == true); REQUIRE(program["--verbose"] != false); @@ -44,8 +40,6 @@ TEST_CASE("Parse multiple toggle arguments with implicit values", "[optional_arg .implicit_value(true); program.parse_args({ "./test.exe", "-a", "-x" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 3); REQUIRE(program.get("-a") == true); REQUIRE(program.get("-u") == false); REQUIRE(program.get("-x") == true); diff --git a/tests/test_parse_args.hpp b/tests/test_parse_args.hpp index 6922e60..5fa500a 100644 --- a/tests/test_parse_args.hpp +++ b/tests/test_parse_args.hpp @@ -6,8 +6,6 @@ TEST_CASE("Parse a string argument with value", "[parse_args]") { argparse::ArgumentParser program("test"); program.add_argument("--config"); program.parse_args({ "test", "--config", "config.yml"}); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); REQUIRE(program.get("--config") == "config.yml"); } @@ -16,8 +14,6 @@ TEST_CASE("Parse a string argument with default value", "[parse_args]") { program.add_argument("--config") .default_value(std::string("foo.yml")); program.parse_args({ "test", "--config" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); REQUIRE(program.get("--config") == "foo.yml"); } @@ -26,8 +22,6 @@ TEST_CASE("Parse an int argument with value", "[parse_args]") { program.add_argument("--count") .action([](const std::string& value) { return std::stoi(value); }); program.parse_args({ "test", "--count", "5" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); REQUIRE(program.get("--count") == 5); } @@ -37,8 +31,6 @@ TEST_CASE("Parse an int argument with default value", "[parse_args]") { .default_value(2) .action([](const std::string& value) { return std::stoi(value); }); program.parse_args({ "test", "--count" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); REQUIRE(program.get("--count") == 2); } @@ -47,8 +39,6 @@ TEST_CASE("Parse a float argument with value", "[parse_args]") { program.add_argument("--ratio") .action([](const std::string& value) { return std::stof(value); }); program.parse_args({ "test", "--ratio", "5.6645" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); REQUIRE(program.get("--ratio") == 5.6645f); } @@ -58,8 +48,6 @@ TEST_CASE("Parse a float argument with default value", "[parse_args]") { .default_value(3.14f) .action([](const std::string& value) { return std::stof(value); }); program.parse_args({ "test", "--ratio" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); REQUIRE(program.get("--ratio") == 3.14f); } @@ -68,8 +56,6 @@ TEST_CASE("Parse a double argument with value", "[parse_args]") { program.add_argument("--ratio") .action([](const std::string& value) { return std::stod(value); }); program.parse_args({ "test", "--ratio", "5.6645" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); REQUIRE(program.get("--ratio") == 5.6645); } @@ -79,8 +65,6 @@ TEST_CASE("Parse a double argument with default value", "[parse_args]") { .default_value(3.14) .action([](const std::string& value) { return std::stod(value); }); program.parse_args({ "test", "--ratio" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); REQUIRE(program.get("--ratio") == 3.14); } @@ -90,8 +74,6 @@ TEST_CASE("Parse a vector of integer arguments", "[parse_args]") { .nargs(5) .action([](const std::string& value) { return std::stoi(value); }); program.parse_args({ "test", "--vector", "1", "2", "3", "4", "5" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); auto vector = program.get>("--vector"); REQUIRE(vector.size() == 5); REQUIRE(vector[0] == 1); @@ -107,8 +89,6 @@ TEST_CASE("Parse a vector of float arguments", "[parse_args]") { .nargs(5) .action([](const std::string& value) { return std::stof(value); }); program.parse_args({ "test", "--vector", "1.1", "2.2", "3.3", "4.4", "5.5" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); auto vector = program.get>("--vector"); REQUIRE(vector.size() == 5); REQUIRE(vector[0] == 1.1f); @@ -124,8 +104,6 @@ TEST_CASE("Parse a vector of double arguments", "[parse_args]") { .nargs(5) .action([](const std::string& value) { return std::stod(value); }); program.parse_args({ "test", "--vector", "1.1", "2.2", "3.3", "4.4", "5.5" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); auto vector = program.get>("--vector"); REQUIRE(vector.size() == 5); REQUIRE(vector[0] == 1.1); @@ -141,8 +119,6 @@ TEST_CASE("Parse a vector of string arguments", "[parse_args]") { .nargs(5) .action([](const std::string& value) { return value; }); program.parse_args({ "test", "--vector", "abc", "def", "ghi", "jkl", "mno" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); auto vector = program.get>("--vector"); REQUIRE(vector.size() == 5); REQUIRE(vector[0] == "abc"); @@ -158,8 +134,6 @@ TEST_CASE("Parse a vector of character arguments", "[parse_args]") { .nargs(5) .action([](const std::string& value) { return value[0]; }); program.parse_args({ "test", "--vector", "a", "b", "c", "d", "e" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); auto vector = program.get>("--vector"); REQUIRE(vector.size() == 5); REQUIRE(vector[0] == 'a'); @@ -182,8 +156,6 @@ TEST_CASE("Parse a vector of string arguments and construct objects", "[parse_ar .nargs(5) .action([](const std::string& value) { return Foo(value); }); program.parse_args({ "test", "--vector", "abc", "def", "ghi", "jkl", "mno" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 1); auto vector = program.get>("--vector"); REQUIRE(vector.size() == 5); REQUIRE(vector[0].value == Foo("abc").value); diff --git a/tests/test_positional_arguments.hpp b/tests/test_positional_arguments.hpp index 67a1c8b..239e771 100644 --- a/tests/test_positional_arguments.hpp +++ b/tests/test_positional_arguments.hpp @@ -7,8 +7,6 @@ TEST_CASE("Parse positional arguments", "[positional_arguments]") { program.add_argument("input"); program.add_argument("output"); program.parse_args({ "test", "rocket.mesh", "thrust_profile.csv" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 2); REQUIRE(program.get("input") == "rocket.mesh"); REQUIRE(program.get("output") == "thrust_profile.csv"); } @@ -18,8 +16,6 @@ TEST_CASE("Parse positional arguments with fixed nargs", "[positional_arguments] program.add_argument("input"); program.add_argument("output").nargs(2); program.parse_args({ "test", "rocket.mesh", "thrust_profile.csv", "output.mesh" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 2); REQUIRE(program.get("input") == "rocket.mesh"); auto outputs = program.get>("output"); REQUIRE(outputs.size() == 2); @@ -34,8 +30,6 @@ TEST_CASE("Parse positional arguments with optional arguments", "[positional_arg program.add_argument("--num_iterations") .action([](const std::string& value) { return std::stoi(value); }); program.parse_args({ "test", "rocket.mesh", "--num_iterations", "15", "thrust_profile.csv", "output.mesh" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 3); REQUIRE(program.get("--num_iterations") == 15); REQUIRE(program.get("input") == "rocket.mesh"); auto outputs = program.get>("output"); @@ -51,8 +45,6 @@ TEST_CASE("Parse positional arguments with optional arguments in the middle", "[ program.add_argument("--num_iterations") .action([](const std::string& value) { return std::stoi(value); }); program.parse_args({ "test", "rocket.mesh", "thrust_profile.csv", "--num_iterations", "15", "output.mesh" }); - auto arguments = program.get_arguments(); - REQUIRE(arguments.size() == 3); REQUIRE(program.get("--num_iterations") == 15); REQUIRE(program.get("input") == "rocket.mesh"); auto outputs = program.get>("output");