Merge pull request #245 from skrobinson/feat-at-function

Add ArgumentParser::at to retrieve arguments and subparsers
This commit is contained in:
Pranav 2022-11-30 08:55:47 -06:00 committed by GitHub
commit d1d006f8f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 0 deletions

View File

@ -827,6 +827,20 @@ When a help message is requested from a subparser, only the help for that partic
Additionally, every parser has the `.is_subcommand_used("<command_name>")` and `.is_subcommand_used(subparser)` member functions to check if a subcommand was used.
### Getting Argument and Subparser Instances
```Argument``` and ```ArgumentParser``` instances added to an ```ArgumentParser``` can be retrieved with ```.at<T>()```. The default return type is ```Argument```.
```cpp
argparse::ArgumentParser program("test");
program.add_argument("--dir");
program.at("--dir").default_value(std::string("/home/user"));
program.add_subparser(argparse::ArgumentParser{"walk"});
program.at<argparse::ArgumentParser>("walk").add_argument("depth");
```
### Parse Known Args
Sometimes a program may only parse a few of the command-line arguments, passing the remaining arguments on to another script or program. In these cases, the `parse_known_args()` function can be useful. It works much like `parse_args()` except that it does not produce an error when extra arguments are present. Instead, it returns a list of remaining argument strings.

View File

@ -1167,6 +1167,22 @@ public:
return *this;
}
/* Getter for arguments and subparsers.
* @throws std::logic_error in case of an invalid argument or subparser name
*/
template <typename T = Argument>
T& at(std::string_view name) {
if constexpr (std::is_same_v<T, Argument>) {
return (*this)[name];
} else {
auto subparser_it = m_subparser_map.find(name);
if (subparser_it != m_subparser_map.end()) {
return subparser_it->second->get();
}
throw std::logic_error("No such subparser: " + std::string(name));
}
}
ArgumentParser &set_prefix_chars(std::string prefix_chars) {
m_prefix_chars = std::move(prefix_chars);
return *this;

View File

@ -27,6 +27,7 @@ file(GLOB ARGPARSE_TEST_SOURCES
main.cpp
test_actions.cpp
test_append.cpp
test_as_container.cpp
test_bool_operator.cpp
test_compound_arguments.cpp
test_container_arguments.cpp

View File

@ -0,0 +1,52 @@
#include <argparse/argparse.hpp>
#include <doctest.hpp>
using doctest::test_suite;
TEST_CASE("Get argument with .at()" * test_suite("as_container")) {
argparse::ArgumentParser program("test");
auto &dir_arg = program.add_argument("--dir");
program.at("--dir").default_value(std::string("/home/user"));
SUBCASE("and default value") {
program.parse_args({"test"});
REQUIRE(&(program.at("--dir")) == &dir_arg);
REQUIRE(program["--dir"] == std::string("/home/user"));
REQUIRE(program.at("--dir") == std::string("/home/user"));
}
SUBCASE("and user-supplied value") {
program.parse_args({"test", "--dir", "/usr/local/database"});
REQUIRE(&(program.at("--dir")) == &dir_arg);
REQUIRE(program["--dir"] == std::string("/usr/local/database"));
REQUIRE(program.at("--dir") == std::string("/usr/local/database"));
}
SUBCASE("with unknown argument") {
program.parse_args({"test"});
REQUIRE_THROWS_WITH_AS(program.at("--folder"),
"No such argument: --folder", std::logic_error);
}
}
TEST_CASE("Get subparser with .at()" * test_suite("as_container")) {
argparse::ArgumentParser program("test");
argparse::ArgumentParser walk_cmd("walk");
auto &speed = walk_cmd.add_argument("speed");
program.add_subparser(walk_cmd);
SUBCASE("and its argument") {
program.parse_args({"test", "walk", "4km/h"});
REQUIRE(&(program.at<argparse::ArgumentParser>("walk")) == &walk_cmd);
REQUIRE(&(program.at<argparse::ArgumentParser>("walk").at("speed")) == &speed);
REQUIRE(program.at<argparse::ArgumentParser>("walk").is_used("speed"));
}
SUBCASE("with unknown command") {
program.parse_args({"test"});
REQUIRE_THROWS_WITH_AS(program.at<argparse::ArgumentParser>("fly"),
"No such subparser: fly", std::logic_error);
}
}