Commit 4dac11c025cf0782b298e2ba461c956d2c2e6ffe

Authored by Henry Fredrick Schreiner
Committed by Henry Schreiner
1 parent c1fb53f0

Finishing addition of ->configurable()

include/CLI/App.hpp
... ... @@ -1209,7 +1209,7 @@ class App {
1209 1209  
1210 1210 if(!op->get_configurable())
1211 1211 throw INIError::NotConfigurable(current.fullname);
1212   -
  1212 +
1213 1213 if(op->results_.empty()) {
1214 1214 // Flag parsing
1215 1215 if(op->get_expected() == 0) {
... ...
include/CLI/Error.hpp
... ... @@ -86,30 +86,32 @@ class IncorrectConstruction : public ConstructionError {
86 86 CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction)
87 87 CLI11_ERROR_SIMPLE(IncorrectConstruction)
88 88 static IncorrectConstruction PositionalFlag(std::string name) {
89   - return IncorrectConstruction(name + ": Flags cannot be positional");}
  89 + return IncorrectConstruction(name + ": Flags cannot be positional");
  90 + }
90 91 static IncorrectConstruction Set0Opt(std::string name) {
91   - return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead");}
  92 + return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead");
  93 + }
92 94 static IncorrectConstruction ChangeNotVector(std::string name) {
93   - return IncorrectConstruction(name + ": You can only change the expected arguments for vectors");}
  95 + return IncorrectConstruction(name + ": You can only change the expected arguments for vectors");
  96 + }
94 97 static IncorrectConstruction AfterMultiOpt(std::string name) {
95   - return IncorrectConstruction(name + ": You can't change expected arguments after you've changed the multi option policy!");}
  98 + return IncorrectConstruction(
  99 + name + ": You can't change expected arguments after you've changed the multi option policy!");
  100 + }
96 101 static IncorrectConstruction MissingOption(std::string name) {
97   - return IncorrectConstruction("Option " + name + " is not defined");}
  102 + return IncorrectConstruction("Option " + name + " is not defined");
  103 + }
98 104 static IncorrectConstruction MultiOptionPolicy(std::string name) {
99   - return IncorrectConstruction(name + ": multi_option_policy only works for flags and single value options");}
100   -
  105 + return IncorrectConstruction(name + ": multi_option_policy only works for flags and single value options");
  106 + }
101 107 };
102 108  
103 109 /// Thrown on construction of a bad name
104 110 class BadNameString : public ConstructionError {
105 111 CLI11_ERROR_DEF(ConstructionError, BadNameString)
106 112 CLI11_ERROR_SIMPLE(BadNameString)
107   - static BadNameString OneCharName(std::string name) {
108   - return BadNameString("Invalid one char name: " + name);
109   - }
110   - static BadNameString BadLongName(std::string name) {
111   - return BadNameString("Bad long name: " + name);
112   - }
  113 + static BadNameString OneCharName(std::string name) { return BadNameString("Invalid one char name: " + name); }
  114 + static BadNameString BadLongName(std::string name) { return BadNameString("Bad long name: " + name); }
113 115 static BadNameString DashesOnly(std::string name) {
114 116 return BadNameString("Must have a name, not just dashes: " + name);
115 117 }
... ... @@ -162,7 +164,7 @@ class RuntimeError : public ParseError {
162 164 class FileError : public ParseError {
163 165 CLI11_ERROR_DEF(ParseError, FileError)
164 166 CLI11_ERROR_SIMPLE(FileError)
165   - static FileError Missing(std::string name) {return FileError(name + " was not readable (missing?)");}
  167 + static FileError Missing(std::string name) { return FileError(name + " was not readable (missing?)"); }
166 168 };
167 169  
168 170 /// 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 {
174 176 ConversionError(std::string name, std::vector<std::string> results)
175 177 : ConversionError("Could not convert: " + name + " = " + detail::join(results)) {}
176 178 static ConversionError TooManyInputsFlag(std::string name) {
177   - return ConversionError(name + ": too many inputs for a flag");}
  179 + return ConversionError(name + ": too many inputs for a flag");
  180 + }
178 181 static ConversionError TrueFalse(std::string name) {
179   - return ConversionError(name + ": Should be true/false or a number");}
  182 + return ConversionError(name + ": Should be true/false or a number");
  183 + }
180 184 };
181 185  
182 186 /// Thrown when validation of results fails
... ... @@ -189,15 +193,14 @@ class ValidationError : public ParseError {
189 193 /// Thrown when a required option is missing
190 194 class RequiredError : public ParseError {
191 195 CLI11_ERROR_DEF(ParseError, RequiredError)
192   - RequiredError(std::string name) : RequiredError(name + " is required") {}
  196 + RequiredError(std::string name) : RequiredError(name + " is required", ExitCodes::RequiredError) {}
193 197 static RequiredError Subcommand(size_t min_subcom) {
194 198 if(min_subcom == 1)
195 199 return RequiredError("A subcommand");
196 200 else
197   - return RequiredError("Requires at least " + std::to_string(min_subcom) + " subcommands", ExitCodes::RequiredError);
  201 + return RequiredError("Requires at least " + std::to_string(min_subcom) + " subcommands",
  202 + ExitCodes::RequiredError);
198 203 }
199   -
200   -
201 204 };
202 205  
203 206 /// Thrown when the wrong number of arguments has been received
... ... @@ -210,13 +213,13 @@ class ArgumentMismatch : public ParseError {
210 213 : ("Expected at least " + std::to_string(-expected) + " arguments to " + name +
211 214 ", got " + std::to_string(recieved)),
212 215 ExitCodes::ArgumentMismatch) {}
213   -
  216 +
214 217 static ArgumentMismatch AtLeast(std::string name, int num) {
215   - return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required");}
  218 + return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required");
  219 + }
216 220 static ArgumentMismatch TypedAtLeast(std::string name, int num, std::string type) {
217   - return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing");}
218   -
219   -
  221 + return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing");
  222 + }
220 223 };
221 224  
222 225 /// Thrown when a requires option is missing
... ... @@ -247,9 +250,10 @@ class ExtrasError : public ParseError {
247 250 class INIError : public ParseError {
248 251 CLI11_ERROR_DEF(ParseError, INIError)
249 252 CLI11_ERROR_SIMPLE(INIError)
250   - static INIError Extras(std::string item) {return INIError("INI was not able to parse " + item);}
251   - static INIError NotConfigurable(std::string item) {return INIError(item + ": This option is not allowed in a configuration file");}
252   -
  253 + static INIError Extras(std::string item) { return INIError("INI was not able to parse " + item); }
  254 + static INIError NotConfigurable(std::string item) {
  255 + return INIError(item + ": This option is not allowed in a configuration file");
  256 + }
253 257 };
254 258  
255 259 /// Thrown when validation fails before parsing
... ...
include/CLI/Option.hpp
... ... @@ -43,15 +43,15 @@ template &lt;typename CRTP&gt; class OptionBase {
43 43  
44 44 /// Allow this option to be given in a configuration file
45 45 bool configurable_{true};
46   -
  46 +
47 47 /// Policy for multiple arguments when `expected_ == 1` (can be set on bool flags, too)
48 48 MultiOptionPolicy multi_option_policy_{MultiOptionPolicy::Throw};
49   -
50 49  
51 50 template <typename T> void copy_to(T *other) const {
52 51 other->group(group_);
53 52 other->required(required_);
54 53 other->ignore_case(ignore_case_);
  54 + other->configurable(configurable_);
55 55 other->multi_option_policy(multi_option_policy_);
56 56 }
57 57  
... ... @@ -84,7 +84,7 @@ template &lt;typename CRTP&gt; class OptionBase {
84 84  
85 85 /// The status of ignore case
86 86 bool get_ignore_case() const { return ignore_case_; }
87   -
  87 +
88 88 /// The status of configurable
89 89 bool get_configurable() const { return configurable_; }
90 90  
... ... @@ -113,7 +113,7 @@ template &lt;typename CRTP&gt; class OptionBase {
113 113 self->multi_option_policy(MultiOptionPolicy::Join);
114 114 return self;
115 115 }
116   -
  116 +
117 117 /// Allow in a configuration file
118 118 CRTP *configurable(bool value = true) {
119 119 configurable_ = value;
... ...
tests/CreationTest.cpp
... ... @@ -303,12 +303,14 @@ TEST_F(TApp, OptionFromDefaultsSubcommands) {
303 303 EXPECT_FALSE(app.option_defaults()->get_required());
304 304 EXPECT_EQ(app.option_defaults()->get_multi_option_policy(), CLI::MultiOptionPolicy::Throw);
305 305 EXPECT_FALSE(app.option_defaults()->get_ignore_case());
  306 + EXPECT_TRUE(app.option_defaults()->get_configurable());
306 307 EXPECT_EQ(app.option_defaults()->get_group(), "Options");
307 308  
308 309 app.option_defaults()
309 310 ->required()
310 311 ->multi_option_policy(CLI::MultiOptionPolicy::TakeLast)
311 312 ->ignore_case()
  313 + ->configurable(false)
312 314 ->group("Something");
313 315  
314 316 auto app2 = app.add_subcommand("app2");
... ... @@ -316,6 +318,7 @@ TEST_F(TApp, OptionFromDefaultsSubcommands) {
316 318 EXPECT_TRUE(app2->option_defaults()->get_required());
317 319 EXPECT_EQ(app2->option_defaults()->get_multi_option_policy(), CLI::MultiOptionPolicy::TakeLast);
318 320 EXPECT_TRUE(app2->option_defaults()->get_ignore_case());
  321 + EXPECT_FALSE(app2->option_defaults()->get_configurable());
319 322 EXPECT_EQ(app2->option_defaults()->get_group(), "Something");
320 323 }
321 324  
... ...
tests/IniTest.cpp
... ... @@ -379,6 +379,41 @@ TEST_F(TApp, IniFailure) {
379 379 EXPECT_THROW(run(), CLI::INIError);
380 380 }
381 381  
  382 +TEST_F(TApp, IniConfigurable) {
  383 +
  384 + TempFile tmpini{"TestIniTmp.ini"};
  385 +
  386 + app.add_config("--config", tmpini);
  387 + bool value;
  388 + app.add_flag("--val", value)->configurable(true);
  389 +
  390 + {
  391 + std::ofstream out{tmpini};
  392 + out << "[default]" << std::endl;
  393 + out << "val=1" << std::endl;
  394 + }
  395 +
  396 + EXPECT_NO_THROW(run());
  397 + EXPECT_TRUE(value);
  398 +}
  399 +
  400 +TEST_F(TApp, IniNotConfigurable) {
  401 +
  402 + TempFile tmpini{"TestIniTmp.ini"};
  403 +
  404 + app.add_config("--config", tmpini);
  405 + bool value;
  406 + app.add_flag("--val", value)->configurable(false);
  407 +
  408 + {
  409 + std::ofstream out{tmpini};
  410 + out << "[default]" << std::endl;
  411 + out << "val=1" << std::endl;
  412 + }
  413 +
  414 + EXPECT_THROW(run(), CLI::INIError);
  415 +}
  416 +
382 417 TEST_F(TApp, IniSubFailure) {
383 418  
384 419 TempFile tmpini{"TestIniTmp.ini"};
... ...