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