Commit c1fb53f00d75ff5ef32dbfa7f73268f04ef78a9c

Authored by Henry Fredrick Schreiner
Committed by Henry Schreiner
1 parent 04e01d2b

Moving error messages definitions to Error.h

include/CLI/App.hpp
@@ -369,7 +369,7 @@ class App { @@ -369,7 +369,7 @@ class App {
369 369
370 Option *opt = add_option(name, fun, description, false); 370 Option *opt = add_option(name, fun, description, false);
371 if(opt->get_positional()) 371 if(opt->get_positional())
372 - throw IncorrectConstruction("Flags cannot be positional"); 372 + throw IncorrectConstruction::PositionalFlag(name);
373 opt->set_custom_option("", 0); 373 opt->set_custom_option("", 0);
374 return opt; 374 return opt;
375 } 375 }
@@ -389,7 +389,7 @@ class App { @@ -389,7 +389,7 @@ class App {
389 389
390 Option *opt = add_option(name, fun, description, false); 390 Option *opt = add_option(name, fun, description, false);
391 if(opt->get_positional()) 391 if(opt->get_positional())
392 - throw IncorrectConstruction("Flags cannot be positional"); 392 + throw IncorrectConstruction::PositionalFlag(name);
393 opt->set_custom_option("", 0); 393 opt->set_custom_option("", 0);
394 return opt; 394 return opt;
395 } 395 }
@@ -409,7 +409,7 @@ class App { @@ -409,7 +409,7 @@ class App {
409 409
410 Option *opt = add_option(name, fun, description, false); 410 Option *opt = add_option(name, fun, description, false);
411 if(opt->get_positional()) 411 if(opt->get_positional())
412 - throw IncorrectConstruction("Flags cannot be positional"); 412 + throw IncorrectConstruction::PositionalFlag(name);
413 opt->set_custom_option("", 0); 413 opt->set_custom_option("", 0);
414 opt->multi_option_policy(CLI::MultiOptionPolicy::TakeLast); 414 opt->multi_option_policy(CLI::MultiOptionPolicy::TakeLast);
415 return opt; 415 return opt;
@@ -428,7 +428,7 @@ class App { @@ -428,7 +428,7 @@ class App {
428 428
429 Option *opt = add_option(name, fun, description, false); 429 Option *opt = add_option(name, fun, description, false);
430 if(opt->get_positional()) 430 if(opt->get_positional())
431 - throw IncorrectConstruction("Flags cannot be positional"); 431 + throw IncorrectConstruction::PositionalFlag(name);
432 opt->set_custom_option("", 0); 432 opt->set_custom_option("", 0);
433 return opt; 433 return opt;
434 } 434 }
@@ -1100,7 +1100,7 @@ class App { @@ -1100,7 +1100,7 @@ class App {
1100 std::vector<detail::ini_ret_t> values = detail::parse_ini(config_name_); 1100 std::vector<detail::ini_ret_t> values = detail::parse_ini(config_name_);
1101 while(!values.empty()) { 1101 while(!values.empty()) {
1102 if(!_parse_ini(values)) { 1102 if(!_parse_ini(values)) {
1103 - throw ExtrasINIError(values.back().fullname); 1103 + throw INIError::Extras(values.back().fullname);
1104 } 1104 }
1105 } 1105 }
1106 } catch(const FileError &) { 1106 } catch(const FileError &) {
@@ -1149,8 +1149,7 @@ class App { @@ -1149,8 +1149,7 @@ class App {
1149 if(opt->get_required() || opt->count() != 0) { 1149 if(opt->get_required() || opt->count() != 0) {
1150 // Make sure enough -N arguments parsed (+N is already handled in parsing function) 1150 // Make sure enough -N arguments parsed (+N is already handled in parsing function)
1151 if(opt->get_expected() < 0 && opt->count() < static_cast<size_t>(-opt->get_expected())) 1151 if(opt->get_expected() < 0 && opt->count() < static_cast<size_t>(-opt->get_expected()))
1152 - throw ArgumentMismatch(opt->single_name() + ": At least " + std::to_string(-opt->get_expected()) +  
1153 - " required"); 1152 + throw ArgumentMismatch::AtLeast(opt->single_name(), -opt->get_expected());
1154 1153
1155 // Required but empty 1154 // Required but empty
1156 if(opt->get_required() && opt->count() == 0) 1155 if(opt->get_required() && opt->count() == 0)
@@ -1167,10 +1166,8 @@ class App { @@ -1167,10 +1166,8 @@ class App {
1167 } 1166 }
1168 1167
1169 auto selected_subcommands = get_subcommands(); 1168 auto selected_subcommands = get_subcommands();
1170 - if(require_subcommand_min_ > 0 && selected_subcommands.empty())  
1171 - throw RequiredError("Subcommand required");  
1172 - else if(require_subcommand_min_ > selected_subcommands.size())  
1173 - throw RequiredError("Requires at least " + std::to_string(require_subcommand_min_) + " subcommands"); 1169 + if(require_subcommand_min_ > selected_subcommands.size())
  1170 + throw RequiredError::Subcommand(require_subcommand_min_);
1174 1171
1175 // Convert missing (pairs) to extras (string only) 1172 // Convert missing (pairs) to extras (string only)
1176 if(!(allow_extras_ || prefix_command_)) { 1173 if(!(allow_extras_ || prefix_command_)) {
@@ -1210,6 +1207,9 @@ class App { @@ -1210,6 +1207,9 @@ class App {
1210 // Let's not go crazy with pointer syntax 1207 // Let's not go crazy with pointer syntax
1211 Option_p &op = *op_ptr; 1208 Option_p &op = *op_ptr;
1212 1209
  1210 + if(!op->get_configurable())
  1211 + throw INIError::NotConfigurable(current.fullname);
  1212 +
1213 if(op->results_.empty()) { 1213 if(op->results_.empty()) {
1214 // Flag parsing 1214 // Flag parsing
1215 if(op->get_expected() == 0) { 1215 if(op->get_expected() == 0) {
@@ -1226,10 +1226,10 @@ class App { @@ -1226,10 +1226,10 @@ class App {
1226 for(size_t i = 0; i < ui; i++) 1226 for(size_t i = 0; i < ui; i++)
1227 op->results_.emplace_back(""); 1227 op->results_.emplace_back("");
1228 } catch(const std::invalid_argument &) { 1228 } catch(const std::invalid_argument &) {
1229 - throw ConversionError(current.fullname + ": Should be true/false or a number"); 1229 + throw ConversionError::TrueFalse(current.fullname);
1230 } 1230 }
1231 } else 1231 } else
1232 - throw ConversionError(current.fullname + ": too many inputs for a flag"); 1232 + throw ConversionError::TooManyInputsFlag(current.fullname);
1233 } else { 1233 } else {
1234 op->results_ = current.inputs; 1234 op->results_ = current.inputs;
1235 op->run_callback(); 1235 op->run_callback();
@@ -1424,8 +1424,7 @@ class App { @@ -1424,8 +1424,7 @@ class App {
1424 } 1424 }
1425 1425
1426 if(num > 0) { 1426 if(num > 0) {
1427 - throw ArgumentMismatch(op->single_name() + ": " + std::to_string(num) + " required " +  
1428 - op->get_type_name() + " missing"); 1427 + throw ArgumentMismatch::TypedAtLeast(op->single_name(), num, op->get_type_name());
1429 } 1428 }
1430 } 1429 }
1431 1430
include/CLI/Error.hpp
@@ -35,14 +35,14 @@ enum class ExitCodes { @@ -35,14 +35,14 @@ enum class ExitCodes {
35 IncorrectConstruction = 100, 35 IncorrectConstruction = 100,
36 BadNameString, 36 BadNameString,
37 OptionAlreadyAdded, 37 OptionAlreadyAdded,
38 - File, 38 + FileError,
39 ConversionError, 39 ConversionError,
40 ValidationError, 40 ValidationError,
41 RequiredError, 41 RequiredError,
42 RequiresError, 42 RequiresError,
43 ExcludesError, 43 ExcludesError,
44 ExtrasError, 44 ExtrasError,
45 - ExtrasINIError, 45 + INIError,
46 InvalidError, 46 InvalidError,
47 HorribleError, 47 HorribleError,
48 OptionNotFound, 48 OptionNotFound,
@@ -85,18 +85,50 @@ class ConstructionError : public Error { @@ -85,18 +85,50 @@ class ConstructionError : public Error {
85 class IncorrectConstruction : public ConstructionError { 85 class IncorrectConstruction : public ConstructionError {
86 CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction) 86 CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction)
87 CLI11_ERROR_SIMPLE(IncorrectConstruction) 87 CLI11_ERROR_SIMPLE(IncorrectConstruction)
  88 + static IncorrectConstruction PositionalFlag(std::string name) {
  89 + return IncorrectConstruction(name + ": Flags cannot be positional");}
  90 + static IncorrectConstruction Set0Opt(std::string name) {
  91 + return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead");}
  92 + static IncorrectConstruction ChangeNotVector(std::string name) {
  93 + return IncorrectConstruction(name + ": You can only change the expected arguments for vectors");}
  94 + static IncorrectConstruction AfterMultiOpt(std::string name) {
  95 + return IncorrectConstruction(name + ": You can't change expected arguments after you've changed the multi option policy!");}
  96 + static IncorrectConstruction MissingOption(std::string name) {
  97 + return IncorrectConstruction("Option " + name + " is not defined");}
  98 + static IncorrectConstruction MultiOptionPolicy(std::string name) {
  99 + return IncorrectConstruction(name + ": multi_option_policy only works for flags and single value options");}
  100 +
88 }; 101 };
89 102
90 /// Thrown on construction of a bad name 103 /// Thrown on construction of a bad name
91 class BadNameString : public ConstructionError { 104 class BadNameString : public ConstructionError {
92 CLI11_ERROR_DEF(ConstructionError, BadNameString) 105 CLI11_ERROR_DEF(ConstructionError, BadNameString)
93 CLI11_ERROR_SIMPLE(BadNameString) 106 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 DashesOnly(std::string name) {
  114 + return BadNameString("Must have a name, not just dashes: " + name);
  115 + }
  116 + static BadNameString MultiPositionalNames(std::string name) {
  117 + return BadNameString("Only one positional name allowed, remove: " + name);
  118 + }
94 }; 119 };
95 120
96 /// Thrown when an option already exists 121 /// Thrown when an option already exists
97 class OptionAlreadyAdded : public ConstructionError { 122 class OptionAlreadyAdded : public ConstructionError {
98 CLI11_ERROR_DEF(ConstructionError, OptionAlreadyAdded) 123 CLI11_ERROR_DEF(ConstructionError, OptionAlreadyAdded)
99 - CLI11_ERROR_SIMPLE(OptionAlreadyAdded) 124 + OptionAlreadyAdded(std::string name)
  125 + : OptionAlreadyAdded(name + " is already added", ExitCodes::OptionAlreadyAdded) {}
  126 + static OptionAlreadyAdded Requires(std::string name, std::string other) {
  127 + return OptionAlreadyAdded(name + " requires " + other, ExitCodes::OptionAlreadyAdded);
  128 + }
  129 + static OptionAlreadyAdded Excludes(std::string name, std::string other) {
  130 + return OptionAlreadyAdded(name + " excludes " + other, ExitCodes::OptionAlreadyAdded);
  131 + }
100 }; 132 };
101 133
102 // Parsing errors 134 // Parsing errors
@@ -129,7 +161,8 @@ class RuntimeError : public ParseError { @@ -129,7 +161,8 @@ class RuntimeError : public ParseError {
129 /// Thrown when parsing an INI file and it is missing 161 /// Thrown when parsing an INI file and it is missing
130 class FileError : public ParseError { 162 class FileError : public ParseError {
131 CLI11_ERROR_DEF(ParseError, FileError) 163 CLI11_ERROR_DEF(ParseError, FileError)
132 - FileError(std::string name) : FileError(name + " was not readable (missing?)", ExitCodes::File) {} 164 + CLI11_ERROR_SIMPLE(FileError)
  165 + static FileError Missing(std::string name) {return FileError(name + " was not readable (missing?)");}
133 }; 166 };
134 167
135 /// Thrown when conversion call back fails, such as when an int fails to coerce to a string 168 /// Thrown when conversion call back fails, such as when an int fails to coerce to a string
@@ -138,6 +171,12 @@ class ConversionError : public ParseError { @@ -138,6 +171,12 @@ class ConversionError : public ParseError {
138 CLI11_ERROR_SIMPLE(ConversionError) 171 CLI11_ERROR_SIMPLE(ConversionError)
139 ConversionError(std::string member, std::string name) 172 ConversionError(std::string member, std::string name)
140 : ConversionError("The value " + member + "is not an allowed value for " + name) {} 173 : ConversionError("The value " + member + "is not an allowed value for " + name) {}
  174 + ConversionError(std::string name, std::vector<std::string> results)
  175 + : ConversionError("Could not convert: " + name + " = " + detail::join(results)) {}
  176 + static ConversionError TooManyInputsFlag(std::string name) {
  177 + return ConversionError(name + ": too many inputs for a flag");}
  178 + static ConversionError TrueFalse(std::string name) {
  179 + return ConversionError(name + ": Should be true/false or a number");}
141 }; 180 };
142 181
143 /// Thrown when validation of results fails 182 /// Thrown when validation of results fails
@@ -150,7 +189,15 @@ class ValidationError : public ParseError { @@ -150,7 +189,15 @@ class ValidationError : public ParseError {
150 /// Thrown when a required option is missing 189 /// Thrown when a required option is missing
151 class RequiredError : public ParseError { 190 class RequiredError : public ParseError {
152 CLI11_ERROR_DEF(ParseError, RequiredError) 191 CLI11_ERROR_DEF(ParseError, RequiredError)
153 - CLI11_ERROR_SIMPLE(RequiredError) 192 + RequiredError(std::string name) : RequiredError(name + " is required") {}
  193 + static RequiredError Subcommand(size_t min_subcom) {
  194 + if(min_subcom == 1)
  195 + return RequiredError("A subcommand");
  196 + else
  197 + return RequiredError("Requires at least " + std::to_string(min_subcom) + " subcommands", ExitCodes::RequiredError);
  198 + }
  199 +
  200 +
154 }; 201 };
155 202
156 /// Thrown when the wrong number of arguments has been received 203 /// Thrown when the wrong number of arguments has been received
@@ -163,6 +210,13 @@ class ArgumentMismatch : public ParseError { @@ -163,6 +210,13 @@ class ArgumentMismatch : public ParseError {
163 : ("Expected at least " + std::to_string(-expected) + " arguments to " + name + 210 : ("Expected at least " + std::to_string(-expected) + " arguments to " + name +
164 ", got " + std::to_string(recieved)), 211 ", got " + std::to_string(recieved)),
165 ExitCodes::ArgumentMismatch) {} 212 ExitCodes::ArgumentMismatch) {}
  213 +
  214 + static ArgumentMismatch AtLeast(std::string name, int num) {
  215 + return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required");}
  216 + static ArgumentMismatch TypedAtLeast(std::string name, int num, std::string type) {
  217 + return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing");}
  218 +
  219 +
166 }; 220 };
167 221
168 /// Thrown when a requires option is missing 222 /// Thrown when a requires option is missing
@@ -190,9 +244,12 @@ class ExtrasError : public ParseError { @@ -190,9 +244,12 @@ class ExtrasError : public ParseError {
190 }; 244 };
191 245
192 /// Thrown when extra values are found in an INI file 246 /// Thrown when extra values are found in an INI file
193 -class ExtrasINIError : public ParseError {  
194 - CLI11_ERROR_DEF(ParseError, ExtrasINIError)  
195 - ExtrasINIError(std::string item) : ExtrasINIError("INI was not able to parse " + item, ExitCodes::ExtrasINIError) {} 247 +class INIError : public ParseError {
  248 + CLI11_ERROR_DEF(ParseError, INIError)
  249 + 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 +
196 }; 253 };
197 254
198 /// Thrown when validation fails before parsing 255 /// Thrown when validation fails before parsing
@@ -204,6 +261,7 @@ class InvalidError : public ParseError { @@ -204,6 +261,7 @@ class InvalidError : public ParseError {
204 }; 261 };
205 262
206 /// This is just a safety check to verify selection and parsing match - you should not ever see it 263 /// This is just a safety check to verify selection and parsing match - you should not ever see it
  264 +/// Strings are directly added to this error, but again, it should never be seen.
207 class HorribleError : public ParseError { 265 class HorribleError : public ParseError {
208 CLI11_ERROR_DEF(ParseError, HorribleError) 266 CLI11_ERROR_DEF(ParseError, HorribleError)
209 CLI11_ERROR_SIMPLE(HorribleError) 267 CLI11_ERROR_SIMPLE(HorribleError)
include/CLI/Ini.hpp
@@ -106,7 +106,7 @@ inline std::vector&lt;ini_ret_t&gt; parse_ini(const std::string &amp;name) { @@ -106,7 +106,7 @@ inline std::vector&lt;ini_ret_t&gt; parse_ini(const std::string &amp;name) {
106 106
107 std::ifstream input{name}; 107 std::ifstream input{name};
108 if(!input.good()) 108 if(!input.good())
109 - throw FileError(name); 109 + throw FileError::Missing(name);
110 110
111 return parse_ini(input); 111 return parse_ini(input);
112 } 112 }
include/CLI/Option.hpp
@@ -41,8 +41,12 @@ template &lt;typename CRTP&gt; class OptionBase { @@ -41,8 +41,12 @@ template &lt;typename CRTP&gt; class OptionBase {
41 /// Ignore the case when matching (option, not value) 41 /// Ignore the case when matching (option, not value)
42 bool ignore_case_{false}; 42 bool ignore_case_{false};
43 43
  44 + /// Allow this option to be given in a configuration file
  45 + bool configurable_{true};
  46 +
44 /// Policy for multiple arguments when `expected_ == 1` (can be set on bool flags, too) 47 /// Policy for multiple arguments when `expected_ == 1` (can be set on bool flags, too)
45 MultiOptionPolicy multi_option_policy_{MultiOptionPolicy::Throw}; 48 MultiOptionPolicy multi_option_policy_{MultiOptionPolicy::Throw};
  49 +
46 50
47 template <typename T> void copy_to(T *other) const { 51 template <typename T> void copy_to(T *other) const {
48 other->group(group_); 52 other->group(group_);
@@ -80,6 +84,9 @@ template &lt;typename CRTP&gt; class OptionBase { @@ -80,6 +84,9 @@ template &lt;typename CRTP&gt; class OptionBase {
80 84
81 /// The status of ignore case 85 /// The status of ignore case
82 bool get_ignore_case() const { return ignore_case_; } 86 bool get_ignore_case() const { return ignore_case_; }
  87 +
  88 + /// The status of configurable
  89 + bool get_configurable() const { return configurable_; }
83 90
84 /// The status of the multi option policy 91 /// The status of the multi option policy
85 MultiOptionPolicy get_multi_option_policy() const { return multi_option_policy_; } 92 MultiOptionPolicy get_multi_option_policy() const { return multi_option_policy_; }
@@ -106,6 +113,12 @@ template &lt;typename CRTP&gt; class OptionBase { @@ -106,6 +113,12 @@ template &lt;typename CRTP&gt; class OptionBase {
106 self->multi_option_policy(MultiOptionPolicy::Join); 113 self->multi_option_policy(MultiOptionPolicy::Join);
107 return self; 114 return self;
108 } 115 }
  116 +
  117 + /// Allow in a configuration file
  118 + CRTP *configurable(bool value = true) {
  119 + configurable_ = value;
  120 + return static_cast<CRTP *>(this);
  121 + }
109 }; 122 };
110 123
111 class OptionDefaults : public OptionBase<OptionDefaults> { 124 class OptionDefaults : public OptionBase<OptionDefaults> {
@@ -235,12 +248,11 @@ class Option : public OptionBase&lt;Option&gt; { @@ -235,12 +248,11 @@ class Option : public OptionBase&lt;Option&gt; {
235 if(expected_ == value) 248 if(expected_ == value)
236 return this; 249 return this;
237 else if(value == 0) 250 else if(value == 0)
238 - throw IncorrectConstruction("Cannot set 0 expected, use a flag instead"); 251 + throw IncorrectConstruction::Set0Opt(single_name());
239 else if(!changeable_) 252 else if(!changeable_)
240 - throw IncorrectConstruction("You can only change the expected arguments for vectors"); 253 + throw IncorrectConstruction::ChangeNotVector(single_name());
241 else if(value != 1 && multi_option_policy_ != MultiOptionPolicy::Throw) 254 else if(value != 1 && multi_option_policy_ != MultiOptionPolicy::Throw)
242 - throw IncorrectConstruction(  
243 - "You can't change expected arguments after you've changed the multi option policy!"); 255 + throw IncorrectConstruction::AfterMultiOpt(single_name());
244 256
245 expected_ = value; 257 expected_ = value;
246 return this; 258 return this;
@@ -269,7 +281,7 @@ class Option : public OptionBase&lt;Option&gt; { @@ -269,7 +281,7 @@ class Option : public OptionBase&lt;Option&gt; {
269 Option *requires(Option *opt) { 281 Option *requires(Option *opt) {
270 auto tup = requires_.insert(opt); 282 auto tup = requires_.insert(opt);
271 if(!tup.second) 283 if(!tup.second)
272 - throw OptionAlreadyAdded(get_name() + " requires " + opt->get_name()); 284 + throw OptionAlreadyAdded::Requires(get_name(), opt->get_name());
273 return this; 285 return this;
274 } 286 }
275 287
@@ -278,7 +290,7 @@ class Option : public OptionBase&lt;Option&gt; { @@ -278,7 +290,7 @@ class Option : public OptionBase&lt;Option&gt; {
278 for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_) 290 for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
279 if(opt.get() != this && opt->check_name(opt_name)) 291 if(opt.get() != this && opt->check_name(opt_name))
280 return requires(opt.get()); 292 return requires(opt.get());
281 - throw IncorrectConstruction("Option " + opt_name + " is not defined"); 293 + throw IncorrectConstruction::MissingOption(opt_name);
282 } 294 }
283 295
284 /// Any number supported, any mix of string and Opt 296 /// Any number supported, any mix of string and Opt
@@ -291,7 +303,7 @@ class Option : public OptionBase&lt;Option&gt; { @@ -291,7 +303,7 @@ class Option : public OptionBase&lt;Option&gt; {
291 Option *excludes(Option *opt) { 303 Option *excludes(Option *opt) {
292 auto tup = excludes_.insert(opt); 304 auto tup = excludes_.insert(opt);
293 if(!tup.second) 305 if(!tup.second)
294 - throw OptionAlreadyAdded(get_name() + " excludes " + opt->get_name()); 306 + throw OptionAlreadyAdded::Excludes(get_name(), opt->get_name());
295 return this; 307 return this;
296 } 308 }
297 309
@@ -300,7 +312,7 @@ class Option : public OptionBase&lt;Option&gt; { @@ -300,7 +312,7 @@ class Option : public OptionBase&lt;Option&gt; {
300 for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_) 312 for(const Option_p &opt : dynamic_cast<T *>(parent_)->options_)
301 if(opt.get() != this && opt->check_name(opt_name)) 313 if(opt.get() != this && opt->check_name(opt_name))
302 return excludes(opt.get()); 314 return excludes(opt.get());
303 - throw IncorrectConstruction("Option " + opt_name + " is not defined"); 315 + throw IncorrectConstruction::MissingOption(opt_name);
304 } 316 }
305 /// Any number supported, any mix of string and Opt 317 /// Any number supported, any mix of string and Opt
306 template <typename A, typename B, typename... ARG> Option *excludes(A opt, B opt1, ARG... args) { 318 template <typename A, typename B, typename... ARG> Option *excludes(A opt, B opt1, ARG... args) {
@@ -324,7 +336,7 @@ class Option : public OptionBase&lt;Option&gt; { @@ -324,7 +336,7 @@ class Option : public OptionBase&lt;Option&gt; {
324 336
325 for(const Option_p &opt : parent->options_) 337 for(const Option_p &opt : parent->options_)
326 if(opt.get() != this && *opt == *this) 338 if(opt.get() != this && *opt == *this)
327 - throw OptionAlreadyAdded(opt->get_name() + " is already added"); 339 + throw OptionAlreadyAdded(opt->get_name());
328 340
329 return this; 341 return this;
330 } 342 }
@@ -332,7 +344,7 @@ class Option : public OptionBase&lt;Option&gt; { @@ -332,7 +344,7 @@ class Option : public OptionBase&lt;Option&gt; {
332 /// Take the last argument if given multiple times 344 /// Take the last argument if given multiple times
333 Option *multi_option_policy(MultiOptionPolicy value = MultiOptionPolicy::Throw) { 345 Option *multi_option_policy(MultiOptionPolicy value = MultiOptionPolicy::Throw) {
334 if(get_expected() != 0 && get_expected() != 1) 346 if(get_expected() != 0 && get_expected() != 1)
335 - throw IncorrectConstruction("multi_option_policy only works for flags and single value options!"); 347 + throw IncorrectConstruction::MultiOptionPolicy(single_name());
336 multi_option_policy_ = value; 348 multi_option_policy_ = value;
337 return this; 349 return this;
338 } 350 }
@@ -480,7 +492,7 @@ class Option : public OptionBase&lt;Option&gt; { @@ -480,7 +492,7 @@ class Option : public OptionBase&lt;Option&gt; {
480 } 492 }
481 493
482 if(local_result) 494 if(local_result)
483 - throw ConversionError("Could not convert: " + get_name() + "=" + detail::join(results_)); 495 + throw ConversionError(get_name(), results_);
484 } 496 }
485 497
486 /// If options share any of the same names, they are equal (not counting positional) 498 /// If options share any of the same names, they are equal (not counting positional)
include/CLI/Split.hpp
@@ -66,18 +66,18 @@ get_names(const std::vector&lt;std::string&gt; &amp;input) { @@ -66,18 +66,18 @@ get_names(const std::vector&lt;std::string&gt; &amp;input) {
66 if(name.length() == 2 && valid_first_char(name[1])) 66 if(name.length() == 2 && valid_first_char(name[1]))
67 short_names.emplace_back(1, name[1]); 67 short_names.emplace_back(1, name[1]);
68 else 68 else
69 - throw BadNameString("Invalid one char name: " + name); 69 + throw BadNameString::OneCharName(name);
70 } else if(name.length() > 2 && name.substr(0, 2) == "--") { 70 } else if(name.length() > 2 && name.substr(0, 2) == "--") {
71 name = name.substr(2); 71 name = name.substr(2);
72 if(valid_name_string(name)) 72 if(valid_name_string(name))
73 long_names.push_back(name); 73 long_names.push_back(name);
74 else 74 else
75 - throw BadNameString("Bad long name: " + name); 75 + throw BadNameString::BadLongName(name);
76 } else if(name == "-" || name == "--") { 76 } else if(name == "-" || name == "--") {
77 - throw BadNameString("Must have a name, not just dashes"); 77 + throw BadNameString::DashesOnly(name);
78 } else { 78 } else {
79 if(pos_name.length() > 0) 79 if(pos_name.length() > 0)
80 - throw BadNameString("Only one positional name allowed, remove: " + name); 80 + throw BadNameString::MultiPositionalNames(name);
81 pos_name = name; 81 pos_name = name;
82 } 82 }
83 } 83 }
tests/IniTest.cpp
@@ -376,7 +376,7 @@ TEST_F(TApp, IniFailure) { @@ -376,7 +376,7 @@ TEST_F(TApp, IniFailure) {
376 out << "val=1" << std::endl; 376 out << "val=1" << std::endl;
377 } 377 }
378 378
379 - EXPECT_THROW(run(), CLI::ExtrasINIError); 379 + EXPECT_THROW(run(), CLI::INIError);
380 } 380 }
381 381
382 TEST_F(TApp, IniSubFailure) { 382 TEST_F(TApp, IniSubFailure) {
@@ -392,7 +392,7 @@ TEST_F(TApp, IniSubFailure) { @@ -392,7 +392,7 @@ TEST_F(TApp, IniSubFailure) {
392 out << "val=1" << std::endl; 392 out << "val=1" << std::endl;
393 } 393 }
394 394
395 - EXPECT_THROW(run(), CLI::ExtrasINIError); 395 + EXPECT_THROW(run(), CLI::INIError);
396 } 396 }
397 397
398 TEST_F(TApp, IniNoSubFailure) { 398 TEST_F(TApp, IniNoSubFailure) {
@@ -407,7 +407,7 @@ TEST_F(TApp, IniNoSubFailure) { @@ -407,7 +407,7 @@ TEST_F(TApp, IniNoSubFailure) {
407 out << "val=1" << std::endl; 407 out << "val=1" << std::endl;
408 } 408 }
409 409
410 - EXPECT_THROW(run(), CLI::ExtrasINIError); 410 + EXPECT_THROW(run(), CLI::INIError);
411 } 411 }
412 412
413 TEST_F(TApp, IniFlagConvertFailure) { 413 TEST_F(TApp, IniFlagConvertFailure) {