Merge pull request #61 from zhihaoy/exit-on-help

Default --help to print help and exit
This commit is contained in:
Pranav 2019-11-22 18:01:23 -06:00 committed by GitHub
commit 473d550ea3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 14 deletions

View File

@ -30,6 +30,7 @@ SOFTWARE.
#pragma once
#include <algorithm>
#include <any>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <iterator>
@ -372,20 +373,15 @@ private:
bool mIsOptional : 1;
bool mIsRequired : 1;
bool mIsUsed : 1; // True if the optional argument is used by user
static constexpr auto mHelpOption = "-h";
static constexpr auto mHelpOptionLong = "--help";
};
class ArgumentParser {
public:
explicit ArgumentParser(std::string aProgramName = {})
: mProgramName(std::move(aProgramName)) {
add_argument(Argument::mHelpOption, Argument::mHelpOptionLong)
add_argument("-h", "--help")
.help("show this help message and exit")
.nargs(0)
.default_value(false)
.implicit_value(true);
.nargs(0);
}
ArgumentParser(ArgumentParser &&) noexcept = default;
@ -542,10 +538,6 @@ private:
auto positionalArgumentIt = std::begin(mPositionalArguments);
for (auto it = std::next(std::begin(aArguments)); it != end;) {
const auto &tCurrentArgument = *it;
if (tCurrentArgument == Argument::mHelpOption ||
tCurrentArgument == Argument::mHelpOptionLong) {
throw std::runtime_error("help called");
}
if (Argument::is_positional(tCurrentArgument)) {
if (positionalArgumentIt == std::end(mPositionalArguments)) {
throw std::runtime_error(
@ -553,9 +545,19 @@ private:
}
auto tArgument = positionalArgumentIt++;
it = tArgument->consume(it, end);
} else if (auto tIterator = mArgumentMap.find(tCurrentArgument);
tIterator != mArgumentMap.end()) {
continue;
}
auto tIterator = mArgumentMap.find(tCurrentArgument);
if (tIterator != mArgumentMap.end()) {
auto tArgument = tIterator->second;
// the first optional argument is --help
if (tArgument == mOptionalArguments.begin()) {
std::cout << *this;
std::exit(0);
}
it = tArgument->consume(std::next(it), end, tCurrentArgument);
} else if (const auto &tCompoundArgument = tCurrentArgument;
tCompoundArgument.size() > 1 && tCompoundArgument[0] == '-' &&
@ -607,7 +609,7 @@ private:
void index_argument(list_iterator argIt) {
for (auto &mName : std::as_const(argIt->mNames))
mArgumentMap.emplace(mName, argIt);
mArgumentMap.insert_or_assign(mName, argIt);
}
std::string mProgramName;

View File

@ -17,3 +17,27 @@ TEST_CASE("Users can format help message" * test_suite("help")) {
auto msg = program.help().str();
REQUIRE(msg == s.str());
}
TEST_CASE("Users can override the help options" * test_suite("help")) {
GIVEN("a program that meant to take -h as a normal option") {
argparse::ArgumentParser program("test");
program.add_argument("input");
program.add_argument("-h").implicit_value('h').default_value('x');
WHEN("provided -h without fulfilling other requirements") {
THEN("validation fails") {
REQUIRE_THROWS_AS(program.parse_args({"test", "-h"}),
std::runtime_error);
}
}
WHEN("provided arguments to all parameters") {
program.parse_args({"test", "-h", "some input"});
THEN("these parameters get their values") {
REQUIRE(program["-h"] == 'h');
REQUIRE(program.get("input") == "some input");
}
}
}
}