mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-04 15:14:39 +00:00
Merge pull request #61 from zhihaoy/exit-on-help
Default --help to print help and exit
This commit is contained in:
commit
473d550ea3
@ -30,6 +30,7 @@ SOFTWARE.
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <any>
|
#include <any>
|
||||||
|
#include <cstdlib>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
@ -372,20 +373,15 @@ private:
|
|||||||
bool mIsOptional : 1;
|
bool mIsOptional : 1;
|
||||||
bool mIsRequired : 1;
|
bool mIsRequired : 1;
|
||||||
bool mIsUsed : 1; // True if the optional argument is used by user
|
bool mIsUsed : 1; // True if the optional argument is used by user
|
||||||
|
|
||||||
static constexpr auto mHelpOption = "-h";
|
|
||||||
static constexpr auto mHelpOptionLong = "--help";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ArgumentParser {
|
class ArgumentParser {
|
||||||
public:
|
public:
|
||||||
explicit ArgumentParser(std::string aProgramName = {})
|
explicit ArgumentParser(std::string aProgramName = {})
|
||||||
: mProgramName(std::move(aProgramName)) {
|
: mProgramName(std::move(aProgramName)) {
|
||||||
add_argument(Argument::mHelpOption, Argument::mHelpOptionLong)
|
add_argument("-h", "--help")
|
||||||
.help("show this help message and exit")
|
.help("show this help message and exit")
|
||||||
.nargs(0)
|
.nargs(0);
|
||||||
.default_value(false)
|
|
||||||
.implicit_value(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgumentParser(ArgumentParser &&) noexcept = default;
|
ArgumentParser(ArgumentParser &&) noexcept = default;
|
||||||
@ -542,10 +538,6 @@ private:
|
|||||||
auto positionalArgumentIt = std::begin(mPositionalArguments);
|
auto positionalArgumentIt = std::begin(mPositionalArguments);
|
||||||
for (auto it = std::next(std::begin(aArguments)); it != end;) {
|
for (auto it = std::next(std::begin(aArguments)); it != end;) {
|
||||||
const auto &tCurrentArgument = *it;
|
const auto &tCurrentArgument = *it;
|
||||||
if (tCurrentArgument == Argument::mHelpOption ||
|
|
||||||
tCurrentArgument == Argument::mHelpOptionLong) {
|
|
||||||
throw std::runtime_error("help called");
|
|
||||||
}
|
|
||||||
if (Argument::is_positional(tCurrentArgument)) {
|
if (Argument::is_positional(tCurrentArgument)) {
|
||||||
if (positionalArgumentIt == std::end(mPositionalArguments)) {
|
if (positionalArgumentIt == std::end(mPositionalArguments)) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
@ -553,9 +545,19 @@ private:
|
|||||||
}
|
}
|
||||||
auto tArgument = positionalArgumentIt++;
|
auto tArgument = positionalArgumentIt++;
|
||||||
it = tArgument->consume(it, end);
|
it = tArgument->consume(it, end);
|
||||||
} else if (auto tIterator = mArgumentMap.find(tCurrentArgument);
|
continue;
|
||||||
tIterator != mArgumentMap.end()) {
|
}
|
||||||
|
|
||||||
|
auto tIterator = mArgumentMap.find(tCurrentArgument);
|
||||||
|
if (tIterator != mArgumentMap.end()) {
|
||||||
auto tArgument = tIterator->second;
|
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);
|
it = tArgument->consume(std::next(it), end, tCurrentArgument);
|
||||||
} else if (const auto &tCompoundArgument = tCurrentArgument;
|
} else if (const auto &tCompoundArgument = tCurrentArgument;
|
||||||
tCompoundArgument.size() > 1 && tCompoundArgument[0] == '-' &&
|
tCompoundArgument.size() > 1 && tCompoundArgument[0] == '-' &&
|
||||||
@ -607,7 +609,7 @@ private:
|
|||||||
|
|
||||||
void index_argument(list_iterator argIt) {
|
void index_argument(list_iterator argIt) {
|
||||||
for (auto &mName : std::as_const(argIt->mNames))
|
for (auto &mName : std::as_const(argIt->mNames))
|
||||||
mArgumentMap.emplace(mName, argIt);
|
mArgumentMap.insert_or_assign(mName, argIt);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string mProgramName;
|
std::string mProgramName;
|
||||||
|
@ -17,3 +17,27 @@ TEST_CASE("Users can format help message" * test_suite("help")) {
|
|||||||
auto msg = program.help().str();
|
auto msg = program.help().str();
|
||||||
REQUIRE(msg == s.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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user