mirror of
https://github.com/KeqingMoe/argparse.git
synced 2025-07-04 15:14:39 +00:00
Merge pull request #13 from svanveen/fix/exceptions
Replaced exit(0) by std::runtime_error
This commit is contained in:
commit
50f2df36aa
@ -39,6 +39,7 @@ SOFTWARE.
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace argparse {
|
namespace argparse {
|
||||||
|
|
||||||
@ -77,8 +78,8 @@ public:
|
|||||||
, mIsOptional((is_optional(args) || ...))
|
, mIsOptional((is_optional(args) || ...))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Argument& help(const std::string& aHelp) {
|
Argument& help(std::string aHelp) {
|
||||||
mHelp = aHelp;
|
mHelp = std::move(aHelp);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,15 +322,19 @@ class ArgumentParser {
|
|||||||
add_parents(Fargs...);
|
add_parents(Fargs...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call parse_args_internal - which does all the work
|
/* Call parse_args_internal - which does all the work
|
||||||
// Then, validate the parsed arguments
|
* Then, validate the parsed arguments
|
||||||
// This variant is used mainly for testing
|
* This variant is used mainly for testing
|
||||||
|
* @throws std::runtime_error in case of any invalid argument
|
||||||
|
*/
|
||||||
void parse_args(const std::vector<std::string>& aArguments) {
|
void parse_args(const std::vector<std::string>& aArguments) {
|
||||||
parse_args_internal(aArguments);
|
parse_args_internal(aArguments);
|
||||||
parse_args_validate();
|
parse_args_validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main entry point for parsing command-line arguments using this ArgumentParser
|
/* Main entry point for parsing command-line arguments using this ArgumentParser
|
||||||
|
* @throws std::runtime_error in case of any invalid argument
|
||||||
|
*/
|
||||||
void parse_args(int argc, char * argv[]) {
|
void parse_args(int argc, char * argv[]) {
|
||||||
parse_args_internal(argc, argv);
|
parse_args_internal(argc, argv);
|
||||||
parse_args_validate();
|
parse_args_validate();
|
||||||
@ -458,6 +463,9 @@ class ArgumentParser {
|
|||||||
return (tIterator != mArgumentMap.end());
|
return (tIterator != mArgumentMap.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @throws std::runtime_error in case of any invalid argument
|
||||||
|
*/
|
||||||
void parse_args_internal(const std::vector<std::string>& aArguments) {
|
void parse_args_internal(const std::vector<std::string>& aArguments) {
|
||||||
std::vector<char*> argv;
|
std::vector<char*> argv;
|
||||||
for (const auto& arg : aArguments)
|
for (const auto& arg : aArguments)
|
||||||
@ -466,14 +474,16 @@ class ArgumentParser {
|
|||||||
return parse_args_internal(int(argv.size()) - 1, argv.data());
|
return parse_args_internal(int(argv.size()) - 1, argv.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @throws std::runtime_error in case of any invalid argument
|
||||||
|
*/
|
||||||
void parse_args_internal(int argc, char * argv[]) {
|
void parse_args_internal(int argc, char * argv[]) {
|
||||||
if (mProgramName.empty() && argc > 0)
|
if (mProgramName.empty() && argc > 0)
|
||||||
mProgramName = argv[0];
|
mProgramName = argv[0];
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
auto tCurrentArgument = std::string(argv[i]);
|
auto tCurrentArgument = std::string(argv[i]);
|
||||||
if (tCurrentArgument == "-h" || tCurrentArgument == "--help") {
|
if (tCurrentArgument == "-h" || tCurrentArgument == "--help") {
|
||||||
print_help();
|
throw std::runtime_error("help called");
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
auto tIterator = mArgumentMap.find(argv[i]);
|
auto tIterator = mArgumentMap.find(argv[i]);
|
||||||
if (tIterator != mArgumentMap.end()) {
|
if (tIterator != mArgumentMap.end()) {
|
||||||
@ -553,9 +563,9 @@ class ArgumentParser {
|
|||||||
// This is a positional argument.
|
// This is a positional argument.
|
||||||
// Parse and save into mPositionalArguments vector
|
// Parse and save into mPositionalArguments vector
|
||||||
if (mNextPositionalArgument >= mPositionalArguments.size()) {
|
if (mNextPositionalArgument >= mPositionalArguments.size()) {
|
||||||
std::cout << "error: unexpected positional argument " << argv[i] << std::endl;
|
std::stringstream stream;
|
||||||
print_help();
|
stream << "error: unexpected positional argument " << argv[i] << std::endl;
|
||||||
exit(0);
|
throw std::runtime_error(stream.str());
|
||||||
}
|
}
|
||||||
auto tArgument = mPositionalArguments[mNextPositionalArgument];
|
auto tArgument = mPositionalArguments[mNextPositionalArgument];
|
||||||
auto tCount = tArgument->mNumArgs - tArgument->mRawValues.size();
|
auto tCount = tArgument->mNumArgs - tArgument->mRawValues.size();
|
||||||
@ -587,15 +597,18 @@ class ArgumentParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @throws std::runtime_error in case of any invalid argument
|
||||||
|
*/
|
||||||
void parse_args_validate() {
|
void parse_args_validate() {
|
||||||
// Check if all positional arguments are parsed
|
// Check if all positional arguments are parsed
|
||||||
for (const auto& tArgument : mPositionalArguments) {
|
for (const auto& tArgument : mPositionalArguments) {
|
||||||
if (tArgument->mValues.size() != tArgument->mNumArgs) {
|
if (tArgument->mValues.size() != tArgument->mNumArgs) {
|
||||||
std::cout << "error: " << tArgument->mUsedName << ": expected "
|
std::stringstream stream;
|
||||||
|
stream << "error: " << tArgument->mUsedName << ": expected "
|
||||||
<< tArgument->mNumArgs << (tArgument->mNumArgs == 1 ? " argument. " : " arguments. ")
|
<< tArgument->mNumArgs << (tArgument->mNumArgs == 1 ? " argument. " : " arguments. ")
|
||||||
<< tArgument->mValues.size() << " provided.\n" << std::endl;
|
<< tArgument->mValues.size() << " provided.\n" << std::endl;
|
||||||
print_help();
|
throw std::runtime_error(stream.str());
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,11 +619,11 @@ class ArgumentParser {
|
|||||||
// All cool if there's a default value to return
|
// All cool if there's a default value to return
|
||||||
// If no default value, then there's a problem
|
// If no default value, then there's a problem
|
||||||
if (!tArgument->mDefaultValue.has_value()) {
|
if (!tArgument->mDefaultValue.has_value()) {
|
||||||
std::cout << "error: " << tArgument->mUsedName << ": expected "
|
std::stringstream stream;
|
||||||
|
stream << "error: " << tArgument->mUsedName << ": expected "
|
||||||
<< tArgument->mNumArgs << (tArgument->mNumArgs == 1 ? " argument. " : " arguments. ")
|
<< tArgument->mNumArgs << (tArgument->mNumArgs == 1 ? " argument. " : " arguments. ")
|
||||||
<< tArgument->mValues.size() << " provided.\n" << std::endl;
|
<< tArgument->mValues.size() << " provided.\n" << std::endl;
|
||||||
print_help();
|
throw std::runtime_error(stream.str());
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -657,4 +670,13 @@ class ArgumentParser {
|
|||||||
std::map<std::string, std::shared_ptr<Argument>> mArgumentMap;
|
std::map<std::string, std::shared_ptr<Argument>> mArgumentMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define PARSE_ARGS(parser, argc, argv) \
|
||||||
|
try { \
|
||||||
|
parser.parse_args(argc, argv); \
|
||||||
|
} catch (const std::runtime_error& err) { \
|
||||||
|
std::cerr << err.what() << std::endl; \
|
||||||
|
parser.print_help(); \
|
||||||
|
exit(0); \
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user