CLI11 2.4.1
Loading...
Searching...
No Matches
Error.hpp
Go to the documentation of this file.
1// Copyright (c) 2017-2024, University of Cincinnati, developed by Henry Schreiner
2// under NSF AWARD 1414736 and by the respective contributors.
3// All rights reserved.
4//
5// SPDX-License-Identifier: BSD-3-Clause
6
7#pragma once
8
9// [CLI11:public_includes:set]
10#include <exception>
11#include <stdexcept>
12#include <string>
13#include <utility>
14#include <vector>
15// [CLI11:public_includes:end]
16
17// CLI library includes
18#include "Macros.hpp"
19#include "StringTools.hpp"
20
21namespace CLI {
22// [CLI11:error_hpp:verbatim]
23
24// Use one of these on all error classes.
25// These are temporary and are undef'd at the end of this file.
26#define CLI11_ERROR_DEF(parent, name) \
27 protected: \
28 name(std::string ename, std::string msg, int exit_code) : parent(std::move(ename), std::move(msg), exit_code) {} \
29 name(std::string ename, std::string msg, ExitCodes exit_code) \
30 : parent(std::move(ename), std::move(msg), exit_code) {} \
31 \
32 public: \
33 name(std::string msg, ExitCodes exit_code) : parent(#name, std::move(msg), exit_code) {} \
34 name(std::string msg, int exit_code) : parent(#name, std::move(msg), exit_code) {}
35
36// This is added after the one above if a class is used directly and builds its own message
37#define CLI11_ERROR_SIMPLE(name) \
38 explicit name(std::string msg) : name(#name, msg, ExitCodes::name) {}
39
61
62// Error definitions
63
69
71class Error : public std::runtime_error {
72 int actual_exit_code;
73 std::string error_name{"Error"};
74
75 public:
76 CLI11_NODISCARD int get_exit_code() const { return actual_exit_code; }
77
78 CLI11_NODISCARD std::string get_name() const { return error_name; }
79
80 Error(std::string name, std::string msg, int exit_code = static_cast<int>(ExitCodes::BaseClass))
81 : runtime_error(msg), actual_exit_code(exit_code), error_name(std::move(name)) {}
82
83 Error(std::string name, std::string msg, ExitCodes exit_code) : Error(name, msg, static_cast<int>(exit_code)) {}
84};
85
86// Note: Using Error::Error constructors does not work on GCC 4.7
87
92
97 static IncorrectConstruction PositionalFlag(std::string name) {
98 return IncorrectConstruction(name + ": Flags cannot be positional");
99 }
100 static IncorrectConstruction Set0Opt(std::string name) {
101 return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead");
102 }
103 static IncorrectConstruction SetFlag(std::string name) {
104 return IncorrectConstruction(name + ": Cannot set an expected number for flags");
105 }
106 static IncorrectConstruction ChangeNotVector(std::string name) {
107 return IncorrectConstruction(name + ": You can only change the expected arguments for vectors");
108 }
109 static IncorrectConstruction AfterMultiOpt(std::string name) {
111 name + ": You can't change expected arguments after you've changed the multi option policy!");
112 }
113 static IncorrectConstruction MissingOption(std::string name) {
114 return IncorrectConstruction("Option " + name + " is not defined");
115 }
116 static IncorrectConstruction MultiOptionPolicy(std::string name) {
117 return IncorrectConstruction(name + ": multi_option_policy only works for flags and exact value options");
118 }
119};
120
125 static BadNameString OneCharName(std::string name) { return BadNameString("Invalid one char name: " + name); }
126 static BadNameString MissingDash(std::string name) {
127 return BadNameString("Long names strings require 2 dashes " + name);
128 }
129 static BadNameString BadLongName(std::string name) { return BadNameString("Bad long name: " + name); }
130 static BadNameString BadPositionalName(std::string name) {
131 return BadNameString("Invalid positional Name: " + name);
132 }
133 static BadNameString DashesOnly(std::string name) {
134 return BadNameString("Must have a name, not just dashes: " + name);
135 }
136 static BadNameString MultiPositionalNames(std::string name) {
137 return BadNameString("Only one positional name allowed, remove: " + name);
138 }
139};
140
144 explicit OptionAlreadyAdded(std::string name)
145 : OptionAlreadyAdded(name + " is already added", ExitCodes::OptionAlreadyAdded) {}
146 static OptionAlreadyAdded Requires(std::string name, std::string other) {
147 return {name + " requires " + other, ExitCodes::OptionAlreadyAdded};
148 }
149 static OptionAlreadyAdded Excludes(std::string name, std::string other) {
150 return {name + " excludes " + other, ExitCodes::OptionAlreadyAdded};
151 }
152};
153
154// Parsing errors
155
157class ParseError : public Error {
159};
160
161// Not really "errors"
162
164class Success : public ParseError {
166 Success() : Success("Successfully completed, should be caught and quit", ExitCodes::Success) {}
167};
168
170class CallForHelp : public Success {
172 CallForHelp() : CallForHelp("This should be caught in your main function, see examples", ExitCodes::Success) {}
173};
174
176class CallForAllHelp : public Success {
179 : CallForAllHelp("This should be caught in your main function, see examples", ExitCodes::Success) {}
180};
181
183class CallForVersion : public Success {
186 : CallForVersion("This should be caught in your main function, see examples", ExitCodes::Success) {}
187};
188
190class RuntimeError : public ParseError {
192 explicit RuntimeError(int exit_code = 1) : RuntimeError("Runtime error", exit_code) {}
193};
194
196class FileError : public ParseError {
199 static FileError Missing(std::string name) { return FileError(name + " was not readable (missing?)"); }
200};
201
206 ConversionError(std::string member, std::string name)
207 : ConversionError("The value " + member + " is not an allowed value for " + name) {}
208 ConversionError(std::string name, std::vector<std::string> results)
209 : ConversionError("Could not convert: " + name + " = " + detail::join(results)) {}
210 static ConversionError TooManyInputsFlag(std::string name) {
211 return ConversionError(name + ": too many inputs for a flag");
212 }
213 static ConversionError TrueFalse(std::string name) {
214 return ConversionError(name + ": Should be true/false or a number");
215 }
216};
217
222 explicit ValidationError(std::string name, std::string msg) : ValidationError(name + ": " + msg) {}
223};
224
226class RequiredError : public ParseError {
228 explicit RequiredError(std::string name) : RequiredError(name + " is required", ExitCodes::RequiredError) {}
229 static RequiredError Subcommand(std::size_t min_subcom) {
230 if(min_subcom == 1) {
231 return RequiredError("A subcommand");
232 }
233 return {"Requires at least " + std::to_string(min_subcom) + " subcommands", ExitCodes::RequiredError};
234 }
235 static RequiredError
236 Option(std::size_t min_option, std::size_t max_option, std::size_t used, const std::string &option_list) {
237 if((min_option == 1) && (max_option == 1) && (used == 0))
238 return RequiredError("Exactly 1 option from [" + option_list + "]");
239 if((min_option == 1) && (max_option == 1) && (used > 1)) {
240 return {"Exactly 1 option from [" + option_list + "] is required and " + std::to_string(used) +
241 " were given",
243 }
244 if((min_option == 1) && (used == 0))
245 return RequiredError("At least 1 option from [" + option_list + "]");
246 if(used < min_option) {
247 return {"Requires at least " + std::to_string(min_option) + " options used and only " +
248 std::to_string(used) + "were given from [" + option_list + "]",
250 }
251 if(max_option == 1)
252 return {"Requires at most 1 options be given from [" + option_list + "]", ExitCodes::RequiredError};
253
254 return {"Requires at most " + std::to_string(max_option) + " options be used and " + std::to_string(used) +
255 "were given from [" + option_list + "]",
257 }
258};
259
264 ArgumentMismatch(std::string name, int expected, std::size_t received)
265 : ArgumentMismatch(expected > 0 ? ("Expected exactly " + std::to_string(expected) + " arguments to " + name +
266 ", got " + std::to_string(received))
267 : ("Expected at least " + std::to_string(-expected) + " arguments to " + name +
268 ", got " + std::to_string(received)),
270
271 static ArgumentMismatch AtLeast(std::string name, int num, std::size_t received) {
272 return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required but received " +
273 std::to_string(received));
274 }
275 static ArgumentMismatch AtMost(std::string name, int num, std::size_t received) {
276 return ArgumentMismatch(name + ": At Most " + std::to_string(num) + " required but received " +
277 std::to_string(received));
278 }
279 static ArgumentMismatch TypedAtLeast(std::string name, int num, std::string type) {
280 return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing");
281 }
282 static ArgumentMismatch FlagOverride(std::string name) {
283 return ArgumentMismatch(name + " was given a disallowed flag override");
284 }
285 static ArgumentMismatch PartialType(std::string name, int num, std::string type) {
286 return ArgumentMismatch(name + ": " + type + " only partially specified: " + std::to_string(num) +
287 " required for each element");
288 }
289};
290
292class RequiresError : public ParseError {
294 RequiresError(std::string curname, std::string subname)
295 : RequiresError(curname + " requires " + subname, ExitCodes::RequiresError) {}
296};
297
299class ExcludesError : public ParseError {
301 ExcludesError(std::string curname, std::string subname)
302 : ExcludesError(curname + " excludes " + subname, ExitCodes::ExcludesError) {}
303};
304
306class ExtrasError : public ParseError {
308 explicit ExtrasError(std::vector<std::string> args)
309 : ExtrasError((args.size() > 1 ? "The following arguments were not expected: "
310 : "The following argument was not expected: ") +
311 detail::rjoin(args, " "),
313 ExtrasError(const std::string &name, std::vector<std::string> args)
314 : ExtrasError(name,
315 (args.size() > 1 ? "The following arguments were not expected: "
316 : "The following argument was not expected: ") +
317 detail::rjoin(args, " "),
319};
320
322class ConfigError : public ParseError {
325 static ConfigError Extras(std::string item) { return ConfigError("INI was not able to parse " + item); }
326 static ConfigError NotConfigurable(std::string item) {
327 return ConfigError(item + ": This option is not allowed in a configuration file");
328 }
329};
330
332class InvalidError : public ParseError {
334 explicit InvalidError(std::string name)
335 : InvalidError(name + ": Too many positional arguments with unlimited expected args", ExitCodes::InvalidError) {
336 }
337};
338
345
346// After parsing
347
349class OptionNotFound : public Error {
351 explicit OptionNotFound(std::string name) : OptionNotFound(name + " not found", ExitCodes::OptionNotFound) {}
352};
353
354#undef CLI11_ERROR_DEF
355#undef CLI11_ERROR_SIMPLE
356
358
359// [CLI11:error_hpp:end]
360} // namespace CLI
#define CLI11_ERROR_SIMPLE(name)
Definition Error.hpp:37
#define CLI11_ERROR_DEF(parent, name)
Definition Error.hpp:26
#define CLI11_NODISCARD
Definition Macros.hpp:47
Thrown when the wrong number of arguments has been received.
Definition Error.hpp:261
Thrown on construction of a bad name.
Definition Error.hpp:122
Usually something like –help-all on command line.
Definition Error.hpp:176
-h or –help on command line
Definition Error.hpp:170
-v or –version on command line
Definition Error.hpp:183
Thrown when extra values are found in an INI file.
Definition Error.hpp:322
Construction errors (not in parsing)
Definition Error.hpp:89
Thrown when conversion call back fails, such as when an int fails to coerce to a string.
Definition Error.hpp:203
All errors derive from this one.
Definition Error.hpp:71
CLI11_NODISCARD int get_exit_code() const
Definition Error.hpp:76
Error(std::string name, std::string msg, ExitCodes exit_code)
Definition Error.hpp:83
CLI11_NODISCARD std::string get_name() const
Definition Error.hpp:78
Error(std::string name, std::string msg, int exit_code=static_cast< int >(ExitCodes::BaseClass))
Definition Error.hpp:80
Thrown when an excludes option is present.
Definition Error.hpp:299
Thrown when too many positionals or options are found.
Definition Error.hpp:306
Thrown when parsing an INI file and it is missing.
Definition Error.hpp:196
Definition Error.hpp:341
Thrown when an option is set to conflicting values (non-vector and multi args, for example)
Definition Error.hpp:94
Thrown when validation fails before parsing.
Definition Error.hpp:332
Thrown when an option already exists.
Definition Error.hpp:142
Thrown when counting a non-existent option.
Definition Error.hpp:349
Definition Option.hpp:229
Anything that can error in Parse.
Definition Error.hpp:157
Thrown when a required option is missing.
Definition Error.hpp:226
Thrown when a requires option is missing.
Definition Error.hpp:292
Does not output a diagnostic in CLI11_PARSE, but allows main() to return with a specific error code.
Definition Error.hpp:190
This is a successful completion on parsing, supposed to exit.
Definition Error.hpp:164
Thrown when validation of results fails.
Definition Error.hpp:219
std::string join(const T &v, std::string delim=",")
Simple function to join a string.
Definition StringTools.hpp:51
std::string rjoin(const T &v, std::string delim=",")
Join a string in reverse order.
Definition StringTools.hpp:84
Definition App.hpp:34
ExitCodes
Definition Error.hpp:42
MultiOptionPolicy
Enumeration of the multiOption Policy selection.
Definition Option.hpp:38