mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-05-01 21:23:52 +00:00
Adding ArgumentMismatch, changable improvement
This commit is contained in:
parent
afd4e32809
commit
4d5bff2393
@ -274,8 +274,6 @@ class App {
|
||||
|
||||
std::string simple_name = CLI::detail::split(name, ',').at(0);
|
||||
CLI::callback_t fun = [&variable, simple_name](CLI::results_t res) {
|
||||
if(res.size() != 1)
|
||||
throw ConversionError("Only one " + simple_name + " allowed");
|
||||
return detail::lexical_cast(res[0], variable);
|
||||
};
|
||||
|
||||
@ -293,8 +291,6 @@ class App {
|
||||
|
||||
std::string simple_name = CLI::detail::split(name, ',').at(0);
|
||||
CLI::callback_t fun = [&variable, simple_name](CLI::results_t res) {
|
||||
if(res.size() != 1)
|
||||
throw ConversionError("Only one " + simple_name + " allowed");
|
||||
return detail::lexical_cast(res[0], variable);
|
||||
};
|
||||
|
||||
@ -325,7 +321,7 @@ class App {
|
||||
};
|
||||
|
||||
Option *opt = add_option(name, fun, description, false);
|
||||
opt->set_custom_option(detail::type_name<T>(), -1, true);
|
||||
opt->set_custom_option(detail::type_name<T>(), -1);
|
||||
return opt;
|
||||
}
|
||||
|
||||
@ -347,7 +343,7 @@ class App {
|
||||
};
|
||||
|
||||
Option *opt = add_option(name, fun, description, defaulted);
|
||||
opt->set_custom_option(detail::type_name<T>(), -1, true);
|
||||
opt->set_custom_option(detail::type_name<T>(), -1);
|
||||
if(defaulted)
|
||||
opt->set_default_str("[" + detail::join(variable) + "]");
|
||||
return opt;
|
||||
@ -454,9 +450,6 @@ class App {
|
||||
|
||||
std::string simple_name = CLI::detail::split(name, ',').at(0);
|
||||
CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
|
||||
if(res.size() != 1) {
|
||||
throw ConversionError("Only one " + simple_name + " allowed");
|
||||
}
|
||||
bool retval = detail::lexical_cast(res[0], member);
|
||||
if(!retval)
|
||||
throw ConversionError("The value " + res[0] + "is not an allowed value for " + simple_name);
|
||||
@ -480,9 +473,6 @@ class App {
|
||||
|
||||
std::string simple_name = CLI::detail::split(name, ',').at(0);
|
||||
CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
|
||||
if(res.size() != 1) {
|
||||
throw ConversionError("Only one " + simple_name + " allowed");
|
||||
}
|
||||
bool retval = detail::lexical_cast(res[0], member);
|
||||
if(!retval)
|
||||
throw ConversionError("The value " + res[0] + "is not an allowed value for " + simple_name);
|
||||
@ -509,9 +499,6 @@ class App {
|
||||
|
||||
std::string simple_name = CLI::detail::split(name, ',').at(0);
|
||||
CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
|
||||
if(res.size() != 1) {
|
||||
throw ConversionError("Only one " + simple_name + " allowed");
|
||||
}
|
||||
member = detail::to_lower(res[0]);
|
||||
auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
|
||||
return detail::to_lower(val) == member;
|
||||
@ -541,9 +528,6 @@ class App {
|
||||
|
||||
std::string simple_name = CLI::detail::split(name, ',').at(0);
|
||||
CLI::callback_t fun = [&member, options, simple_name](CLI::results_t res) {
|
||||
if(res.size() != 1) {
|
||||
throw ConversionError("Only one " + simple_name + " allowed");
|
||||
}
|
||||
member = detail::to_lower(res[0]);
|
||||
auto iter = std::find_if(std::begin(options), std::end(options), [&member](std::string val) {
|
||||
return detail::to_lower(val) == member;
|
||||
|
@ -43,6 +43,7 @@ enum class ExitCodes {
|
||||
InvalidError,
|
||||
HorribleError,
|
||||
OptionNotFound,
|
||||
ArgumentMismatch,
|
||||
BaseClass = 127
|
||||
};
|
||||
|
||||
@ -146,6 +147,17 @@ class RequiredError : public ParseError {
|
||||
CLI11_ERROR_SIMPLE(RequiredError)
|
||||
};
|
||||
|
||||
/// Thrown when the wrong number of arguments has been recieved
|
||||
class ArgumentMismatch : ParseError {
|
||||
CLI11_ERROR_DEF(ParseError, ArgumentMismatch)
|
||||
ArgumentMismatch(std::string name, int expected, size_t recieved)
|
||||
: ArgumentMismatch(expected > 0 ? ("Expected exactly " + std::to_string(expected) + " arguments to " + name +
|
||||
", got " + std::to_string(recieved))
|
||||
: ("Expected at least " + std::to_string(-expected) + " arguments to " + name +
|
||||
", got " + std::to_string(recieved)),
|
||||
ExitCodes::ArgumentMismatch) {}
|
||||
};
|
||||
|
||||
/// Thrown when a requires option is missing
|
||||
class RequiresError : public ParseError {
|
||||
CLI11_ERROR_DEF(ParseError, RequiresError)
|
||||
|
@ -207,14 +207,15 @@ class Option : public OptionBase<Option> {
|
||||
|
||||
/// Set the number of expected arguments (Flags bypass this)
|
||||
Option *expected(int value) {
|
||||
if(value == 0)
|
||||
if(expected_ == value)
|
||||
return this;
|
||||
else if(value == 0)
|
||||
throw IncorrectConstruction("Cannot set 0 expected, use a flag instead");
|
||||
else if(expected_ == 0)
|
||||
throw IncorrectConstruction("Cannot make a flag take arguments!");
|
||||
else if(!changeable_)
|
||||
throw IncorrectConstruction("You can only change the expected arguments for vectors");
|
||||
else if(last_)
|
||||
throw IncorrectConstruction("You can't change expected arguments after you've set take_last!");
|
||||
|
||||
expected_ = value;
|
||||
return this;
|
||||
}
|
||||
@ -447,7 +448,11 @@ class Option : public OptionBase<Option> {
|
||||
results_t partial_result = {results_.back()};
|
||||
local_result = !callback_(partial_result);
|
||||
} else {
|
||||
local_result = !callback_(results_);
|
||||
if((expected_ > 0 && results_.size() != static_cast<size_t>(expected_)) ||
|
||||
(expected_ < 0 && results_.size() < static_cast<size_t>(-expected_)))
|
||||
throw ArgumentMismatch(single_name(), expected_, results_.size());
|
||||
else
|
||||
local_result = !callback_(results_);
|
||||
}
|
||||
|
||||
if(local_result)
|
||||
@ -527,13 +532,13 @@ class Option : public OptionBase<Option> {
|
||||
/// @name Custom options
|
||||
///@{
|
||||
|
||||
/// Set a custom option, typestring, expected, and changeable
|
||||
void set_custom_option(std::string typeval, int expected = 1, bool changeable = false) {
|
||||
/// Set a custom option, typestring, expected; locks changeable unless expected is -1
|
||||
void set_custom_option(std::string typeval, int expected = 1) {
|
||||
typeval_ = typeval;
|
||||
expected_ = expected;
|
||||
if(expected == 0)
|
||||
required_ = false;
|
||||
changeable_ = changeable;
|
||||
changeable_ = expected < 0;
|
||||
}
|
||||
|
||||
/// Set the default value string representation
|
||||
|
@ -119,7 +119,7 @@ TEST_F(TApp, DualOptions) {
|
||||
EXPECT_EQ(ans, vstr);
|
||||
|
||||
args = {"--string=one", "--string=two"};
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
EXPECT_THROW(run(), CLI::ArgumentMismatch);
|
||||
}
|
||||
|
||||
TEST_F(TApp, LotsOfFlags) {
|
||||
@ -737,7 +737,7 @@ TEST_F(TApp, FailSet) {
|
||||
app.add_set("-q,--quick", choice, {1, 2, 3});
|
||||
|
||||
args = {"--quick", "3", "--quick=2"};
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
EXPECT_THROW(run(), CLI::ArgumentMismatch);
|
||||
|
||||
app.reset();
|
||||
|
||||
@ -770,7 +770,7 @@ TEST_F(TApp, InSetIgnoreCase) {
|
||||
|
||||
app.reset();
|
||||
args = {"--quick=one", "--quick=two"};
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
EXPECT_THROW(run(), CLI::ArgumentMismatch);
|
||||
}
|
||||
|
||||
TEST_F(TApp, VectorFixedString) {
|
||||
@ -1145,27 +1145,24 @@ TEST_F(TApp, CheckSubcomFail) {
|
||||
EXPECT_THROW(CLI::detail::AppFriend::parse_subcommand(&app, args), CLI::HorribleError);
|
||||
}
|
||||
|
||||
// Added to test defaults on dual method
|
||||
TEST_F(TApp, OptionWithDefaults) {
|
||||
int someint = 2;
|
||||
app.add_option("-a", someint, "", true);
|
||||
|
||||
args = {"-a1", "-a2"};
|
||||
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
EXPECT_THROW(run(), CLI::ArgumentMismatch);
|
||||
}
|
||||
|
||||
// Added to test defaults on dual method
|
||||
TEST_F(TApp, SetWithDefaults) {
|
||||
int someint = 2;
|
||||
app.add_set("-a", someint, {1, 2, 3, 4}, "", true);
|
||||
|
||||
args = {"-a1", "-a2"};
|
||||
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
EXPECT_THROW(run(), CLI::ArgumentMismatch);
|
||||
}
|
||||
|
||||
// Added to test defaults on dual method
|
||||
TEST_F(TApp, SetWithDefaultsConversion) {
|
||||
int someint = 2;
|
||||
app.add_set("-a", someint, {1, 2, 3, 4}, "", true);
|
||||
@ -1175,14 +1172,13 @@ TEST_F(TApp, SetWithDefaultsConversion) {
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
}
|
||||
|
||||
// Added to test defaults on dual method
|
||||
TEST_F(TApp, SetWithDefaultsIC) {
|
||||
std::string someint = "ho";
|
||||
app.add_set_ignore_case("-a", someint, {"Hi", "Ho"}, "", true);
|
||||
|
||||
args = {"-aHi", "-aHo"};
|
||||
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
EXPECT_THROW(run(), CLI::ArgumentMismatch);
|
||||
}
|
||||
|
||||
// Added to test ->transform
|
||||
|
Loading…
x
Reference in New Issue
Block a user