Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add exit_on_default_arguments parameter to ArgumentParser #264

Merged
merged 2 commits into from
Mar 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 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```

Expand Down Expand Up @@ -99,7 +99,7 @@ int main(int argc, char *argv[]) {
catch (const std::runtime_error& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

auto input = program.get<int>("square");
Expand Down Expand Up @@ -559,7 +559,9 @@ The grammar follows `std::from_chars`, but does not exactly duplicate it. For ex

### 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
argparse::ArgumentParser program("test", "1.0", default_arguments::none);
Expand All @@ -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 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

`argparse` supports gathering "remaining" arguments at the end of the command, e.g., for use in a compiler:
Expand Down Expand Up @@ -773,7 +781,7 @@ int main(int argc, char *argv[]) {
catch (const std::runtime_error& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

// Use arguments
Expand Down Expand Up @@ -900,7 +908,7 @@ int main(int argc, char *argv[]) {
catch (const std::runtime_error& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

if (program.is_used("+f")) {
Expand Down Expand Up @@ -948,7 +956,7 @@ int main(int argc, char *argv[]) {
catch (const std::runtime_error& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

if (program.is_used("--foo")) {
Expand Down Expand Up @@ -1096,7 +1104,7 @@ int main(int argc, char *argv[]) {
catch (const std::runtime_error& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

if (program.is_used("--foo")) {
Expand Down
13 changes: 10 additions & 3 deletions include/argparse/argparse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1052,14 +1052,18 @@ class ArgumentParser {
public:
explicit ArgumentParser(std::string program_name = {},
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_exit_on_default_arguments(exit_on_default_arguments),
m_parser_path(m_program_name) {
if ((add_args & default_arguments::help) == default_arguments::help) {
add_argument("-h", "--help")
.action([&](const auto & /*unused*/) {
std::cout << help().str();
std::exit(0);
if (m_exit_on_default_arguments) {
std::exit(0);
}
})
.default_value(false)
.help("shows help message and exits")
Expand All @@ -1070,7 +1074,9 @@ class ArgumentParser {
add_argument("-v", "--version")
.action([&](const auto & /*unused*/) {
std::cout << m_version << std::endl;
std::exit(0);
if (m_exit_on_default_arguments) {
std::exit(0);
}
})
.default_value(false)
.help("prints version information and exits")
Expand Down Expand Up @@ -1676,6 +1682,7 @@ class ArgumentParser {
std::string m_version;
std::string m_description;
std::string m_epilog;
bool m_exit_on_default_arguments = true;
std::string m_prefix_chars{"-"};
std::string m_assign_chars{"="};
bool m_is_parsed = false;
Expand Down
2 changes: 1 addition & 1 deletion samples/compound_arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ int main(int argc, char *argv[]) {
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

auto a = program.get<bool>("-a"); // true
Expand Down
2 changes: 1 addition & 1 deletion samples/custom_assignment_characters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

if (program.is_used("--foo")) {
Expand Down
2 changes: 1 addition & 1 deletion samples/custom_prefix_characters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

if (program.is_used("+f")) {
Expand Down
2 changes: 1 addition & 1 deletion samples/gathering_remaining_arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ int main(int argc, char *argv[]) {
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

try {
Expand Down
2 changes: 1 addition & 1 deletion samples/is_used.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

auto color = program.get<std::string>("--color"); // "orange"
Expand Down
2 changes: 1 addition & 1 deletion samples/joining_repeated_optional_arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

auto colors = program.get<std::vector<std::string>>(
Expand Down
2 changes: 1 addition & 1 deletion samples/list_of_arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

auto files = program.get<std::vector<std::string>>(
Expand Down
2 changes: 1 addition & 1 deletion samples/negative_numbers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ int main(int argc, char *argv[]) {
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

if (program.is_used("integer")) {
Expand Down
2 changes: 1 addition & 1 deletion samples/optional_flag_argument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ int main(int argc, char *argv[]) {
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

if (program["--verbose"] == true) {
Expand Down
2 changes: 1 addition & 1 deletion samples/positional_argument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ int main(int argc, char *argv[]) {
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

int input = program.get<int>("square");
Expand Down
2 changes: 1 addition & 1 deletion samples/required_optional_argument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ int main(int argc, char *argv[]) {
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

std::cout << "Output written to " << program.get("-o") << "\n";
Expand Down
2 changes: 1 addition & 1 deletion samples/subcommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ int main(int argc, char *argv[]) {
} catch (const std::runtime_error &err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
return 1;
}

// Use arguments
Expand Down
12 changes: 12 additions & 0 deletions test/test_default_args.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <argparse/argparse.hpp>
#include <doctest.hpp>
#include <sstream>
#include <streambuf>

using doctest::test_suite;

Expand All @@ -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("--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"));
}