mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-29 12:13:52 +00:00
Dropping name from simple print, better seperation for Errors
Some error codes are renamed
This commit is contained in:
parent
1735306815
commit
a958ffece2
@ -746,7 +746,7 @@ class App {
|
|||||||
return e.get_exit_code();
|
return e.get_exit_code();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e.exit_code != static_cast<int>(ExitCodes::Success)) {
|
if(e.get_exit_code() != static_cast<int>(ExitCodes::Success)) {
|
||||||
if(failure_message_)
|
if(failure_message_)
|
||||||
err << failure_message_(this, e) << std::flush;
|
err << failure_message_(this, e) << std::flush;
|
||||||
}
|
}
|
||||||
@ -1514,7 +1514,7 @@ inline std::string simple(const App *app, const Error &e) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline std::string help(const App *app, const Error &e) {
|
inline std::string help(const App *app, const Error &e) {
|
||||||
std::string header = std::string("ERROR: ") + e.what() + "\n";
|
std::string header = std::string("ERROR: ") + e.get_name() + ": " + e.what() + "\n";
|
||||||
header += app->help();
|
header += app->help();
|
||||||
return header;
|
return header;
|
||||||
};
|
};
|
||||||
|
@ -7,6 +7,20 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
// Use one of these on all error classes
|
||||||
|
#define CLI11_ERROR_DEF(parent, name) \
|
||||||
|
protected: \
|
||||||
|
name(std::string name, std::string msg, int exit_code) : parent(name, msg, exit_code) {} \
|
||||||
|
name(std::string name, std::string msg, ExitCodes exit_code) : parent(name, msg, exit_code) {} \
|
||||||
|
\
|
||||||
|
public: \
|
||||||
|
name(std::string msg, ExitCodes exit_code) : parent(#name, msg, exit_code) {} \
|
||||||
|
name(std::string msg, int exit_code) : parent(#name, msg, exit_code) {}
|
||||||
|
|
||||||
|
// This is added after the one above if a class is used directly and builds its own message
|
||||||
|
#define CLI11_ERROR_SIMPLE(name) \
|
||||||
|
name(std::string msg) : name(#name, msg, ExitCodes::name) {}
|
||||||
|
|
||||||
namespace CLI {
|
namespace CLI {
|
||||||
|
|
||||||
/// These codes are part of every error in CLI. They can be obtained from e using e.exit_code or as a quick shortcut,
|
/// These codes are part of every error in CLI. They can be obtained from e using e.exit_code or as a quick shortcut,
|
||||||
@ -17,15 +31,15 @@ enum class ExitCodes {
|
|||||||
BadNameString,
|
BadNameString,
|
||||||
OptionAlreadyAdded,
|
OptionAlreadyAdded,
|
||||||
File,
|
File,
|
||||||
Conversion,
|
ConversionError,
|
||||||
Validation,
|
ValidationError,
|
||||||
Required,
|
RequiredError,
|
||||||
Requires,
|
RequiresError,
|
||||||
Excludes,
|
ExcludesError,
|
||||||
Extras,
|
ExtrasError,
|
||||||
ExtrasINI,
|
ExtrasINIError,
|
||||||
Invalid,
|
InvalidError,
|
||||||
Horrible,
|
HorribleError,
|
||||||
OptionNotFound,
|
OptionNotFound,
|
||||||
BaseClass = 127
|
BaseClass = 127
|
||||||
};
|
};
|
||||||
@ -39,126 +53,141 @@ enum class ExitCodes {
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
/// All errors derive from this one
|
/// All errors derive from this one
|
||||||
struct Error : public std::runtime_error {
|
class Error : public std::runtime_error {
|
||||||
int exit_code;
|
int exit_code;
|
||||||
|
std::string name{"Error"};
|
||||||
|
|
||||||
|
public:
|
||||||
int get_exit_code() const { return exit_code; }
|
int get_exit_code() const { return exit_code; }
|
||||||
|
|
||||||
Error(std::string parent, std::string name, ExitCodes exit_code = ExitCodes::BaseClass)
|
std::string get_name() const { return name; }
|
||||||
: runtime_error(parent + ": " + name), exit_code(static_cast<int>(exit_code)) {}
|
|
||||||
Error(std::string parent, std::string name, int exit_code = static_cast<int>(ExitCodes::BaseClass))
|
Error(std::string name, std::string msg, int exit_code = static_cast<int>(ExitCodes::BaseClass))
|
||||||
: runtime_error(parent + ": " + name), exit_code(exit_code) {}
|
: runtime_error(msg), exit_code(exit_code), name(name) {}
|
||||||
|
|
||||||
|
Error(std::string name, std::string msg, ExitCodes exit_code) : Error(name, msg, static_cast<int>(exit_code)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Note: Using Error::Error constructors does not work on GCC 4.7
|
||||||
|
|
||||||
/// Construction errors (not in parsing)
|
/// Construction errors (not in parsing)
|
||||||
struct ConstructionError : public Error {
|
class ConstructionError : public Error {
|
||||||
// Using Error::Error constructors seem to not work on GCC 4.7
|
CLI11_ERROR_DEF(Error, ConstructionError)
|
||||||
ConstructionError(std::string parent, std::string name, ExitCodes exit_code = ExitCodes::BaseClass)
|
|
||||||
: Error(parent, name, exit_code) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when an option is set to conflicting values (non-vector and multi args, for example)
|
/// Thrown when an option is set to conflicting values (non-vector and multi args, for example)
|
||||||
struct IncorrectConstruction : public ConstructionError {
|
class IncorrectConstruction : public ConstructionError {
|
||||||
IncorrectConstruction(std::string name)
|
CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction)
|
||||||
: ConstructionError("IncorrectConstruction", name, ExitCodes::IncorrectConstruction) {}
|
CLI11_ERROR_SIMPLE(IncorrectConstruction)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown on construction of a bad name
|
/// Thrown on construction of a bad name
|
||||||
struct BadNameString : public ConstructionError {
|
class BadNameString : public ConstructionError {
|
||||||
BadNameString(std::string name) : ConstructionError("BadNameString", name, ExitCodes::BadNameString) {}
|
CLI11_ERROR_DEF(ConstructionError, BadNameString)
|
||||||
|
CLI11_ERROR_SIMPLE(BadNameString)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when an option already exists
|
/// Thrown when an option already exists
|
||||||
struct OptionAlreadyAdded : public ConstructionError {
|
class OptionAlreadyAdded : public ConstructionError {
|
||||||
OptionAlreadyAdded(std::string name)
|
CLI11_ERROR_DEF(ConstructionError, OptionAlreadyAdded)
|
||||||
: ConstructionError("OptionAlreadyAdded", name, ExitCodes::OptionAlreadyAdded) {}
|
CLI11_ERROR_SIMPLE(OptionAlreadyAdded)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parsing errors
|
// Parsing errors
|
||||||
|
|
||||||
/// Anything that can error in Parse
|
/// Anything that can error in Parse
|
||||||
struct ParseError : public Error {
|
class ParseError : public Error {
|
||||||
ParseError(std::string parent, std::string name, ExitCodes exit_code = ExitCodes::BaseClass)
|
CLI11_ERROR_DEF(Error, ParseError)
|
||||||
: Error(parent, name, exit_code) {}
|
|
||||||
ParseError(std::string parent, std::string name, int exit_code = static_cast<int>(ExitCodes::BaseClass))
|
|
||||||
: Error(parent, name, exit_code) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Not really "errors"
|
// Not really "errors"
|
||||||
|
|
||||||
/// This is a successful completion on parsing, supposed to exit
|
/// This is a successful completion on parsing, supposed to exit
|
||||||
struct Success : public ParseError {
|
class Success : public ParseError {
|
||||||
Success() : ParseError("Success", "Successfully completed, should be caught and quit", ExitCodes::Success) {}
|
CLI11_ERROR_DEF(ParseError, Success)
|
||||||
|
Success() : Success("Successfully completed, should be caught and quit", ExitCodes::Success) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// -h or --help on command line
|
/// -h or --help on command line
|
||||||
struct CallForHelp : public ParseError {
|
class CallForHelp : public ParseError {
|
||||||
CallForHelp()
|
CLI11_ERROR_DEF(ParseError, CallForHelp)
|
||||||
: ParseError("CallForHelp", "This should be caught in your main function, see examples", ExitCodes::Success) {}
|
CallForHelp() : CallForHelp("This should be caught in your main function, see examples", ExitCodes::Success) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Does not output a diagnostic in CLI11_PARSE, but allows to return from main() with a specific error code.
|
/// Does not output a diagnostic in CLI11_PARSE, but allows to return from main() with a specific error code.
|
||||||
struct RuntimeError : public ParseError {
|
class RuntimeError : public ParseError {
|
||||||
RuntimeError(int exit_code = 1) : ParseError("RuntimeError", "runtime error", exit_code) {}
|
CLI11_ERROR_DEF(ParseError, RuntimeError)
|
||||||
|
RuntimeError(int exit_code = 1) : RuntimeError("Runtime error", exit_code) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when parsing an INI file and it is missing
|
/// Thrown when parsing an INI file and it is missing
|
||||||
struct FileError : public ParseError {
|
class FileError : public ParseError {
|
||||||
FileError(std::string name) : ParseError("FileError", name, ExitCodes::File) {}
|
CLI11_ERROR_DEF(ParseError, FileError)
|
||||||
|
FileError(std::string msg) : FileError(msg, ExitCodes::File) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when conversion call back fails, such as when an int fails to coerce to a string
|
/// Thrown when conversion call back fails, such as when an int fails to coerce to a string
|
||||||
struct ConversionError : public ParseError {
|
class ConversionError : public ParseError {
|
||||||
ConversionError(std::string name) : ParseError("ConversionError", name, ExitCodes::Conversion) {}
|
CLI11_ERROR_DEF(ParseError, ConversionError)
|
||||||
|
CLI11_ERROR_SIMPLE(ConversionError)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when validation of results fails
|
/// Thrown when validation of results fails
|
||||||
struct ValidationError : public ParseError {
|
class ValidationError : public ParseError {
|
||||||
ValidationError(std::string name) : ParseError("ValidationError", name, ExitCodes::Validation) {}
|
CLI11_ERROR_DEF(ParseError, ValidationError)
|
||||||
|
CLI11_ERROR_SIMPLE(ValidationError)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when a required option is missing
|
/// Thrown when a required option is missing
|
||||||
struct RequiredError : public ParseError {
|
class RequiredError : public ParseError {
|
||||||
RequiredError(std::string name) : ParseError("RequiredError", name, ExitCodes::Required) {}
|
CLI11_ERROR_DEF(ParseError, RequiredError)
|
||||||
|
CLI11_ERROR_SIMPLE(RequiredError)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when a requires option is missing
|
/// Thrown when a requires option is missing
|
||||||
struct RequiresError : public ParseError {
|
class RequiresError : public ParseError {
|
||||||
RequiresError(std::string name, std::string subname)
|
CLI11_ERROR_DEF(ParseError, RequiresError)
|
||||||
: ParseError("RequiresError", name + " requires " + subname, ExitCodes::Requires) {}
|
RequiresError(std::string curname, std::string subname)
|
||||||
|
: RequiresError(curname + " requires " + subname, ExitCodes::RequiresError) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when a exludes option is present
|
/// Thrown when a exludes option is present
|
||||||
struct ExcludesError : public ParseError {
|
class ExcludesError : public ParseError {
|
||||||
ExcludesError(std::string name, std::string subname)
|
CLI11_ERROR_DEF(ParseError, ExcludesError)
|
||||||
: ParseError("ExcludesError", name + " excludes " + subname, ExitCodes::Excludes) {}
|
ExcludesError(std::string curname, std::string subname)
|
||||||
|
: ExcludesError(curname + " excludes " + subname, ExitCodes::ExcludesError) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when too many positionals or options are found
|
/// Thrown when too many positionals or options are found
|
||||||
struct ExtrasError : public ParseError {
|
class ExtrasError : public ParseError {
|
||||||
ExtrasError(std::string name) : ParseError("ExtrasError", name, ExitCodes::Extras) {}
|
CLI11_ERROR_DEF(ParseError, ExtrasError)
|
||||||
|
CLI11_ERROR_SIMPLE(ExtrasError)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when extra values are found in an INI file
|
/// Thrown when extra values are found in an INI file
|
||||||
struct ExtrasINIError : public ParseError {
|
class ExtrasINIError : public ParseError {
|
||||||
ExtrasINIError(std::string name) : ParseError("ExtrasINIError", name, ExitCodes::ExtrasINI) {}
|
CLI11_ERROR_DEF(ParseError, ExtrasINIError)
|
||||||
|
CLI11_ERROR_SIMPLE(ExtrasINIError)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Thrown when validation fails before parsing
|
/// Thrown when validation fails before parsing
|
||||||
struct InvalidError : public ParseError {
|
class InvalidError : public ParseError {
|
||||||
InvalidError(std::string name) : ParseError("InvalidError", name, ExitCodes::Invalid) {}
|
CLI11_ERROR_DEF(ParseError, InvalidError)
|
||||||
|
CLI11_ERROR_SIMPLE(InvalidError)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This is just a safety check to verify selection and parsing match
|
/// This is just a safety check to verify selection and parsing match - you should not ever see it
|
||||||
struct HorribleError : public ParseError {
|
class HorribleError : public ParseError {
|
||||||
HorribleError(std::string name)
|
CLI11_ERROR_DEF(ParseError, HorribleError)
|
||||||
: ParseError("HorribleError", "(You should never see this error) " + name, ExitCodes::Horrible) {}
|
CLI11_ERROR_SIMPLE(HorribleError)
|
||||||
};
|
};
|
||||||
|
|
||||||
// After parsing
|
// After parsing
|
||||||
|
|
||||||
/// Thrown when counting a non-existent option
|
/// Thrown when counting a non-existent option
|
||||||
struct OptionNotFound : public Error {
|
class OptionNotFound : public Error {
|
||||||
OptionNotFound(std::string name) : Error("OptionNotFound", name, ExitCodes::OptionNotFound) {}
|
CLI11_ERROR_DEF(Error, OptionNotFound)
|
||||||
|
CLI11_ERROR_SIMPLE(OptionNotFound)
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
@ -309,7 +309,7 @@ TEST(THelp, RemoveHelp) {
|
|||||||
try {
|
try {
|
||||||
app.parse(input);
|
app.parse(input);
|
||||||
} catch(const CLI::ParseError &e) {
|
} catch(const CLI::ParseError &e) {
|
||||||
EXPECT_EQ(static_cast<int>(CLI::ExitCodes::Extras), e.get_exit_code());
|
EXPECT_EQ(static_cast<int>(CLI::ExitCodes::ExtrasError), e.get_exit_code());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +328,7 @@ TEST(THelp, NoHelp) {
|
|||||||
try {
|
try {
|
||||||
app.parse(input);
|
app.parse(input);
|
||||||
} catch(const CLI::ParseError &e) {
|
} catch(const CLI::ParseError &e) {
|
||||||
EXPECT_EQ(static_cast<int>(CLI::ExitCodes::Extras), e.get_exit_code());
|
EXPECT_EQ(static_cast<int>(CLI::ExitCodes::ExtrasError), e.get_exit_code());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,14 +385,14 @@ TEST(Exit, ErrorWithoutHelp) {
|
|||||||
try {
|
try {
|
||||||
app.parse(input);
|
app.parse(input);
|
||||||
} catch(const CLI::ParseError &e) {
|
} catch(const CLI::ParseError &e) {
|
||||||
EXPECT_EQ(static_cast<int>(CLI::ExitCodes::Extras), e.get_exit_code());
|
EXPECT_EQ(static_cast<int>(CLI::ExitCodes::ExtrasError), e.get_exit_code());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Exit, ExitCodes) {
|
TEST(Exit, ExitCodes) {
|
||||||
CLI::App app;
|
CLI::App app;
|
||||||
|
|
||||||
auto i = static_cast<int>(CLI::ExitCodes::Extras);
|
auto i = static_cast<int>(CLI::ExitCodes::ExtrasError);
|
||||||
EXPECT_EQ(0, app.exit(CLI::Success()));
|
EXPECT_EQ(0, app.exit(CLI::Success()));
|
||||||
EXPECT_EQ(0, app.exit(CLI::CallForHelp()));
|
EXPECT_EQ(0, app.exit(CLI::CallForHelp()));
|
||||||
EXPECT_EQ(i, app.exit(CLI::ExtrasError("Thing")));
|
EXPECT_EQ(i, app.exit(CLI::ExtrasError("Thing")));
|
||||||
@ -432,10 +432,10 @@ TEST_F(CapturedHelp, CallForHelp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CapturedHelp, NormalError) {
|
TEST_F(CapturedHelp, NormalError) {
|
||||||
EXPECT_EQ(run(CLI::ExtrasError("Thing")), static_cast<int>(CLI::ExitCodes::Extras));
|
EXPECT_EQ(run(CLI::ExtrasError("Thing")), static_cast<int>(CLI::ExitCodes::ExtrasError));
|
||||||
EXPECT_EQ(out.str(), "");
|
EXPECT_EQ(out.str(), "");
|
||||||
EXPECT_THAT(err.str(), HasSubstr("for more information"));
|
EXPECT_THAT(err.str(), HasSubstr("for more information"));
|
||||||
EXPECT_THAT(err.str(), HasSubstr("ExtrasError"));
|
EXPECT_THAT(err.str(), Not(HasSubstr("ExtrasError")));
|
||||||
EXPECT_THAT(err.str(), HasSubstr("Thing"));
|
EXPECT_THAT(err.str(), HasSubstr("Thing"));
|
||||||
EXPECT_THAT(err.str(), Not(HasSubstr("Usage")));
|
EXPECT_THAT(err.str(), Not(HasSubstr("Usage")));
|
||||||
}
|
}
|
||||||
@ -443,7 +443,7 @@ TEST_F(CapturedHelp, NormalError) {
|
|||||||
TEST_F(CapturedHelp, RepacedError) {
|
TEST_F(CapturedHelp, RepacedError) {
|
||||||
app.set_failure_message(CLI::FailureMessage::help);
|
app.set_failure_message(CLI::FailureMessage::help);
|
||||||
|
|
||||||
EXPECT_EQ(run(CLI::ExtrasError("Thing")), static_cast<int>(CLI::ExitCodes::Extras));
|
EXPECT_EQ(run(CLI::ExtrasError("Thing")), static_cast<int>(CLI::ExitCodes::ExtrasError));
|
||||||
EXPECT_EQ(out.str(), "");
|
EXPECT_EQ(out.str(), "");
|
||||||
EXPECT_THAT(err.str(), Not(HasSubstr("for more information")));
|
EXPECT_THAT(err.str(), Not(HasSubstr("for more information")));
|
||||||
EXPECT_THAT(err.str(), HasSubstr("ERROR: ExtrasError"));
|
EXPECT_THAT(err.str(), HasSubstr("ERROR: ExtrasError"));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user