Add exit_on_default_arguments parameter to ArgumentParser

Allows users to opt-out of std::exit call in default arguments without
needing to replace with new --help and --version arguments.

Signed-off-by: Sean Robinson <sean.robinson@scottsdalecc.edu>
This commit is contained in:
Sean Robinson 2023-03-22 09:07:45 -07:00
parent e516556733
commit 0ae3c7d919
3 changed files with 32 additions and 5 deletions

View File

@ -68,7 +68,7 @@ argparse::ArgumentParser program("program_name");
**NOTE:** There is an optional second argument to the `ArgumentParser` which is the program version. Example: `argparse::ArgumentParser program("libfoo", "1.9.0");` **NOTE:** There is an optional second argument to the `ArgumentParser` which is the program version. Example: `argparse::ArgumentParser program("libfoo", "1.9.0");`
**NOTE:** There is an optional third argument to the `ArgumentParser` which controls default arguments. Example: `argparse::ArgumentParser program("libfoo", "1.9.0", default_arguments::none);` See [Default Arguments](#default-arguments), below. **NOTE:** There are optional third and fourth arguments to the `ArgumentParser` which control default arguments. Example: `argparse::ArgumentParser program("libfoo", "1.9.0", default_arguments::help, false);` See [Default Arguments](#default-arguments), below.
To add a new argument, simply call ```.add_argument(...)```. You can provide a variadic list of argument names that you want to group together, e.g., ```-v``` and ```--verbose``` To add a new argument, simply call ```.add_argument(...)```. You can provide a variadic list of argument names that you want to group together, e.g., ```-v``` and ```--verbose```
@ -559,7 +559,9 @@ The grammar follows `std::from_chars`, but does not exactly duplicate it. For ex
### Default Arguments ### Default Arguments
`argparse` provides predefined arguments and actions for `-h`/`--help` and `-v`/`--version`. These default actions **exit** the program after displaying a help or version message, respectively. These defaults arguments can be disabled during `ArgumentParser` creation so that you can handle these arguments in your own way. (Note that a program name and version must be included when choosing default arguments.) `argparse` provides predefined arguments and actions for `-h`/`--help` and `-v`/`--version`. By default, these actions will **exit** the program after displaying a help or version message, respectively. This exit does not call destructors, skipping clean-up of taken resources.
These default arguments can be disabled during `ArgumentParser` creation so that you can handle these arguments in your own way. (Note that a program name and version must be included when choosing default arguments.)
```cpp ```cpp
argparse::ArgumentParser program("test", "1.0", default_arguments::none); argparse::ArgumentParser program("test", "1.0", default_arguments::none);
@ -578,6 +580,12 @@ The above code snippet outputs a help message and continues to run. It does not
The default is `default_arguments::all` for included arguments. No default arguments will be added with `default_arguments::none`. `default_arguments::help` and `default_arguments::version` will individually add `--help` and `--version`. The default is `default_arguments::all` for included arguments. No default arguments will be added with `default_arguments::none`. `default_arguments::help` and `default_arguments::version` will individually add `--help` and `--version`.
The default arguments can be used while disabling the default exit with these arguments. This forth argument to `ArgumentParser` (`exit_on_default_arguments`) is a bool flag with a default **true** value. The following call will retain `--help` and `--version`, but will not exit when those arguments are used.
```cpp
argparse::ArgumentParser program("test", "1.0", default_arguments::all, false)
```
### Gathering Remaining Arguments ### Gathering Remaining Arguments
`argparse` supports gathering "remaining" arguments at the end of the command, e.g., for use in a compiler: `argparse` supports gathering "remaining" arguments at the end of the command, e.g., for use in a compiler:

View File

@ -1052,14 +1052,18 @@ class ArgumentParser {
public: public:
explicit ArgumentParser(std::string program_name = {}, explicit ArgumentParser(std::string program_name = {},
std::string version = "1.0", std::string version = "1.0",
default_arguments add_args = default_arguments::all) default_arguments add_args = default_arguments::all,
bool exit_on_default_arguments = true)
: m_program_name(std::move(program_name)), m_version(std::move(version)), : m_program_name(std::move(program_name)), m_version(std::move(version)),
m_exit_on_default_arguments(exit_on_default_arguments),
m_parser_path(m_program_name) { m_parser_path(m_program_name) {
if ((add_args & default_arguments::help) == default_arguments::help) { if ((add_args & default_arguments::help) == default_arguments::help) {
add_argument("-h", "--help") add_argument("-h", "--help")
.action([&](const auto & /*unused*/) { .action([&](const auto & /*unused*/) {
std::cout << help().str(); std::cout << help().str();
std::exit(0); if (m_exit_on_default_arguments) {
std::exit(0);
}
}) })
.default_value(false) .default_value(false)
.help("shows help message and exits") .help("shows help message and exits")
@ -1070,7 +1074,9 @@ public:
add_argument("-v", "--version") add_argument("-v", "--version")
.action([&](const auto & /*unused*/) { .action([&](const auto & /*unused*/) {
std::cout << m_version << std::endl; std::cout << m_version << std::endl;
std::exit(0); if (m_exit_on_default_arguments) {
std::exit(0);
}
}) })
.default_value(false) .default_value(false)
.help("prints version information and exits") .help("prints version information and exits")
@ -1676,6 +1682,7 @@ private:
std::string m_version; std::string m_version;
std::string m_description; std::string m_description;
std::string m_epilog; std::string m_epilog;
bool m_exit_on_default_arguments = true;
std::string m_prefix_chars{"-"}; std::string m_prefix_chars{"-"};
std::string m_assign_chars{"="}; std::string m_assign_chars{"="};
bool m_is_parsed = false; bool m_is_parsed = false;

View File

@ -1,5 +1,7 @@
#include <argparse/argparse.hpp> #include <argparse/argparse.hpp>
#include <doctest.hpp> #include <doctest.hpp>
#include <sstream>
#include <streambuf>
using doctest::test_suite; using doctest::test_suite;
@ -17,3 +19,13 @@ TEST_CASE("Do not include default arguments" * test_suite("default_args")) {
REQUIRE_THROWS_AS(parser.get("--help"), std::logic_error); REQUIRE_THROWS_AS(parser.get("--help"), std::logic_error);
REQUIRE_THROWS_AS(parser.get("--version"), std::logic_error); REQUIRE_THROWS_AS(parser.get("--version"), std::logic_error);
} }
TEST_CASE("Do not exit on default arguments" * test_suite("default_args")) {
argparse::ArgumentParser parser("test", "1.0",
argparse::default_arguments::all, false);
std::stringstream buf;
std::streambuf* saved_cout_buf = std::cout.rdbuf(buf.rdbuf());
parser.parse_args({"test", "--help"});
std::cout.rdbuf(saved_cout_buf);
REQUIRE(parser.is_used("--help"));
}