1
0
mirror of https://github.com/CLIUtils/CLI11.git synced 2025-05-02 13:43:52 +00:00

Finishing addition of ->configurable()

This commit is contained in:
Henry Fredrick Schreiner 2017-11-28 15:50:45 -05:00 committed by Henry Schreiner
parent c1fb53f00d
commit 4dac11c025
5 changed files with 75 additions and 33 deletions

View File

@ -1209,7 +1209,7 @@ class App {
if(!op->get_configurable())
throw INIError::NotConfigurable(current.fullname);
if(op->results_.empty()) {
// Flag parsing
if(op->get_expected() == 0) {

View File

@ -86,30 +86,32 @@ class IncorrectConstruction : public ConstructionError {
CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction)
CLI11_ERROR_SIMPLE(IncorrectConstruction)
static IncorrectConstruction PositionalFlag(std::string name) {
return IncorrectConstruction(name + ": Flags cannot be positional");}
return IncorrectConstruction(name + ": Flags cannot be positional");
}
static IncorrectConstruction Set0Opt(std::string name) {
return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead");}
return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead");
}
static IncorrectConstruction ChangeNotVector(std::string name) {
return IncorrectConstruction(name + ": You can only change the expected arguments for vectors");}
return IncorrectConstruction(name + ": You can only change the expected arguments for vectors");
}
static IncorrectConstruction AfterMultiOpt(std::string name) {
return IncorrectConstruction(name + ": You can't change expected arguments after you've changed the multi option policy!");}
return IncorrectConstruction(
name + ": You can't change expected arguments after you've changed the multi option policy!");
}
static IncorrectConstruction MissingOption(std::string name) {
return IncorrectConstruction("Option " + name + " is not defined");}
return IncorrectConstruction("Option " + name + " is not defined");
}
static IncorrectConstruction MultiOptionPolicy(std::string name) {
return IncorrectConstruction(name + ": multi_option_policy only works for flags and single value options");}
return IncorrectConstruction(name + ": multi_option_policy only works for flags and single value options");
}
};
/// Thrown on construction of a bad name
class BadNameString : public ConstructionError {
CLI11_ERROR_DEF(ConstructionError, BadNameString)
CLI11_ERROR_SIMPLE(BadNameString)
static BadNameString OneCharName(std::string name) {
return BadNameString("Invalid one char name: " + name);
}
static BadNameString BadLongName(std::string name) {
return BadNameString("Bad long name: " + name);
}
static BadNameString OneCharName(std::string name) { return BadNameString("Invalid one char name: " + name); }
static BadNameString BadLongName(std::string name) { return BadNameString("Bad long name: " + name); }
static BadNameString DashesOnly(std::string name) {
return BadNameString("Must have a name, not just dashes: " + name);
}
@ -162,7 +164,7 @@ class RuntimeError : public ParseError {
class FileError : public ParseError {
CLI11_ERROR_DEF(ParseError, FileError)
CLI11_ERROR_SIMPLE(FileError)
static FileError Missing(std::string name) {return FileError(name + " was not readable (missing?)");}
static FileError Missing(std::string name) { return FileError(name + " was not readable (missing?)"); }
};
/// Thrown when conversion call back fails, such as when an int fails to coerce to a string
@ -174,9 +176,11 @@ class ConversionError : public ParseError {
ConversionError(std::string name, std::vector<std::string> results)
: ConversionError("Could not convert: " + name + " = " + detail::join(results)) {}
static ConversionError TooManyInputsFlag(std::string name) {
return ConversionError(name + ": too many inputs for a flag");}
return ConversionError(name + ": too many inputs for a flag");
}
static ConversionError TrueFalse(std::string name) {
return ConversionError(name + ": Should be true/false or a number");}
return ConversionError(name + ": Should be true/false or a number");
}
};
/// Thrown when validation of results fails
@ -189,15 +193,14 @@ class ValidationError : public ParseError {
/// Thrown when a required option is missing
class RequiredError : public ParseError {
CLI11_ERROR_DEF(ParseError, RequiredError)
RequiredError(std::string name) : RequiredError(name + " is required") {}
RequiredError(std::string name) : RequiredError(name + " is required", ExitCodes::RequiredError) {}
static RequiredError Subcommand(size_t min_subcom) {
if(min_subcom == 1)
return RequiredError("A subcommand");
else
return RequiredError("Requires at least " + std::to_string(min_subcom) + " subcommands", ExitCodes::RequiredError);
return RequiredError("Requires at least " + std::to_string(min_subcom) + " subcommands",
ExitCodes::RequiredError);
}
};
/// Thrown when the wrong number of arguments has been received
@ -210,13 +213,13 @@ class ArgumentMismatch : public ParseError {
: ("Expected at least " + std::to_string(-expected) + " arguments to " + name +
", got " + std::to_string(recieved)),
ExitCodes::ArgumentMismatch) {}
static ArgumentMismatch AtLeast(std::string name, int num) {
return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required");}
return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required");
}
static ArgumentMismatch TypedAtLeast(std::string name, int num, std::string type) {
return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing");}
return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing");
}
};
/// Thrown when a requires option is missing
@ -247,9 +250,10 @@ class ExtrasError : public ParseError {
class INIError : public ParseError {
CLI11_ERROR_DEF(ParseError, INIError)
CLI11_ERROR_SIMPLE(INIError)
static INIError Extras(std::string item) {return INIError("INI was not able to parse " + item);}
static INIError NotConfigurable(std::string item) {return INIError(item + ": This option is not allowed in a configuration file");}
static INIError Extras(std::string item) { return INIError("INI was not able to parse " + item); }
static INIError NotConfigurable(std::string item) {
return INIError(item + ": This option is not allowed in a configuration file");
}
};
/// Thrown when validation fails before parsing

View File

@ -43,15 +43,15 @@ template <typename CRTP> class OptionBase {
/// Allow this option to be given in a configuration file
bool configurable_{true};
/// Policy for multiple arguments when `expected_ == 1` (can be set on bool flags, too)
MultiOptionPolicy multi_option_policy_{MultiOptionPolicy::Throw};
template <typename T> void copy_to(T *other) const {
other->group(group_);
other->required(required_);
other->ignore_case(ignore_case_);
other->configurable(configurable_);
other->multi_option_policy(multi_option_policy_);
}
@ -84,7 +84,7 @@ template <typename CRTP> class OptionBase {
/// The status of ignore case
bool get_ignore_case() const { return ignore_case_; }
/// The status of configurable
bool get_configurable() const { return configurable_; }
@ -113,7 +113,7 @@ template <typename CRTP> class OptionBase {
self->multi_option_policy(MultiOptionPolicy::Join);
return self;
}
/// Allow in a configuration file
CRTP *configurable(bool value = true) {
configurable_ = value;

View File

@ -303,12 +303,14 @@ TEST_F(TApp, OptionFromDefaultsSubcommands) {
EXPECT_FALSE(app.option_defaults()->get_required());
EXPECT_EQ(app.option_defaults()->get_multi_option_policy(), CLI::MultiOptionPolicy::Throw);
EXPECT_FALSE(app.option_defaults()->get_ignore_case());
EXPECT_TRUE(app.option_defaults()->get_configurable());
EXPECT_EQ(app.option_defaults()->get_group(), "Options");
app.option_defaults()
->required()
->multi_option_policy(CLI::MultiOptionPolicy::TakeLast)
->ignore_case()
->configurable(false)
->group("Something");
auto app2 = app.add_subcommand("app2");
@ -316,6 +318,7 @@ TEST_F(TApp, OptionFromDefaultsSubcommands) {
EXPECT_TRUE(app2->option_defaults()->get_required());
EXPECT_EQ(app2->option_defaults()->get_multi_option_policy(), CLI::MultiOptionPolicy::TakeLast);
EXPECT_TRUE(app2->option_defaults()->get_ignore_case());
EXPECT_FALSE(app2->option_defaults()->get_configurable());
EXPECT_EQ(app2->option_defaults()->get_group(), "Something");
}

View File

@ -379,6 +379,41 @@ TEST_F(TApp, IniFailure) {
EXPECT_THROW(run(), CLI::INIError);
}
TEST_F(TApp, IniConfigurable) {
TempFile tmpini{"TestIniTmp.ini"};
app.add_config("--config", tmpini);
bool value;
app.add_flag("--val", value)->configurable(true);
{
std::ofstream out{tmpini};
out << "[default]" << std::endl;
out << "val=1" << std::endl;
}
EXPECT_NO_THROW(run());
EXPECT_TRUE(value);
}
TEST_F(TApp, IniNotConfigurable) {
TempFile tmpini{"TestIniTmp.ini"};
app.add_config("--config", tmpini);
bool value;
app.add_flag("--val", value)->configurable(false);
{
std::ofstream out{tmpini};
out << "[default]" << std::endl;
out << "val=1" << std::endl;
}
EXPECT_THROW(run(), CLI::INIError);
}
TEST_F(TApp, IniSubFailure) {
TempFile tmpini{"TestIniTmp.ini"};