1 | /// Command line argument parser kind of error |
2 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
3 | #[non_exhaustive ] |
4 | pub enum ErrorKind { |
5 | /// Occurs when an [`Arg`][crate::Arg] has a set of possible values, |
6 | /// and the user provides a value which isn't in that set. |
7 | /// |
8 | /// # Examples |
9 | /// |
10 | /// ```rust |
11 | /// # use clap_builder as clap; |
12 | /// # use clap::{Command, Arg, error::ErrorKind}; |
13 | /// let result = Command::new("prog" ) |
14 | /// .arg(Arg::new("speed" ) |
15 | /// .value_parser(["fast" , "slow" ])) |
16 | /// .try_get_matches_from(vec!["prog" , "other" ]); |
17 | /// assert!(result.is_err()); |
18 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); |
19 | /// ``` |
20 | InvalidValue, |
21 | |
22 | /// Occurs when a user provides a flag, option, argument or subcommand which isn't defined. |
23 | /// |
24 | /// # Examples |
25 | /// |
26 | /// ```rust |
27 | /// # use clap_builder as clap; |
28 | /// # use clap::{Command, arg, error::ErrorKind}; |
29 | /// let result = Command::new("prog" ) |
30 | /// .arg(arg!(--flag "some flag" )) |
31 | /// .try_get_matches_from(vec!["prog" , "--other" ]); |
32 | /// assert!(result.is_err()); |
33 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::UnknownArgument); |
34 | /// ``` |
35 | UnknownArgument, |
36 | |
37 | /// Occurs when the user provides an unrecognized [`Subcommand`] which meets the threshold for |
38 | /// being similar enough to an existing subcommand. |
39 | /// If it doesn't meet the threshold, or the 'suggestions' feature is disabled, |
40 | /// the more general [`UnknownArgument`] error is returned. |
41 | /// |
42 | /// # Examples |
43 | /// |
44 | /// ```rust |
45 | /// # #[cfg (feature = "suggestions" )] { |
46 | /// # use clap_builder as clap; |
47 | /// # use clap::{Command, Arg, error::ErrorKind, }; |
48 | /// let result = Command::new("prog" ) |
49 | /// .subcommand(Command::new("config" ) |
50 | /// .about("Used for configuration" ) |
51 | /// .arg(Arg::new("config_file" ) |
52 | /// .help("The configuration file to use" ))) |
53 | /// .try_get_matches_from(vec!["prog" , "confi" ]); |
54 | /// assert!(result.is_err()); |
55 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidSubcommand); |
56 | /// # } |
57 | /// ``` |
58 | /// |
59 | /// [`Subcommand`]: crate::Subcommand |
60 | /// [`UnknownArgument`]: ErrorKind::UnknownArgument |
61 | InvalidSubcommand, |
62 | |
63 | /// Occurs when the user doesn't use equals for an option that requires equal |
64 | /// sign to provide values. |
65 | /// |
66 | /// ```rust |
67 | /// # use clap_builder as clap; |
68 | /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; |
69 | /// let res = Command::new("prog" ) |
70 | /// .arg(Arg::new("color" ) |
71 | /// .action(ArgAction::Set) |
72 | /// .require_equals(true) |
73 | /// .long("color" )) |
74 | /// .try_get_matches_from(vec!["prog" , "--color" , "red" ]); |
75 | /// assert!(res.is_err()); |
76 | /// assert_eq!(res.unwrap_err().kind(), ErrorKind::NoEquals); |
77 | /// ``` |
78 | NoEquals, |
79 | |
80 | /// Occurs when the user provides a value for an argument with a custom validation and the |
81 | /// value fails that validation. |
82 | /// |
83 | /// # Examples |
84 | /// |
85 | /// ```rust |
86 | /// # use clap_builder as clap; |
87 | /// # use clap::{Command, Arg, error::ErrorKind, value_parser}; |
88 | /// fn is_numeric(val: &str) -> Result<(), String> { |
89 | /// match val.parse::<i64>() { |
90 | /// Ok(..) => Ok(()), |
91 | /// Err(..) => Err(String::from("value wasn't a number!" )), |
92 | /// } |
93 | /// } |
94 | /// |
95 | /// let result = Command::new("prog" ) |
96 | /// .arg(Arg::new("num" ) |
97 | /// .value_parser(value_parser!(u8))) |
98 | /// .try_get_matches_from(vec!["prog" , "NotANumber" ]); |
99 | /// assert!(result.is_err()); |
100 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::ValueValidation); |
101 | /// ``` |
102 | ValueValidation, |
103 | |
104 | /// Occurs when a user provides more values for an argument than were defined by setting |
105 | /// [`Arg::num_args`]. |
106 | /// |
107 | /// # Examples |
108 | /// |
109 | /// ```rust |
110 | /// # use clap_builder as clap; |
111 | /// # use clap::{Command, Arg, error::ErrorKind}; |
112 | /// let result = Command::new("prog" ) |
113 | /// .arg(Arg::new("arg" ) |
114 | /// .num_args(1..=2)) |
115 | /// .try_get_matches_from(vec!["prog" , "too" , "many" , "values" ]); |
116 | /// assert!(result.is_err()); |
117 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyValues); |
118 | /// ``` |
119 | /// [`Arg::num_args`]: crate::Arg::num_args() |
120 | TooManyValues, |
121 | |
122 | /// Occurs when the user provides fewer values for an argument than were defined by setting |
123 | /// [`Arg::num_args`]. |
124 | /// |
125 | /// # Examples |
126 | /// |
127 | /// ```rust |
128 | /// # use clap_builder as clap; |
129 | /// # use clap::{Command, Arg, error::ErrorKind}; |
130 | /// let result = Command::new("prog" ) |
131 | /// .arg(Arg::new("some_opt" ) |
132 | /// .long("opt" ) |
133 | /// .num_args(3..)) |
134 | /// .try_get_matches_from(vec!["prog" , "--opt" , "too" , "few" ]); |
135 | /// assert!(result.is_err()); |
136 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooFewValues); |
137 | /// ``` |
138 | /// [`Arg::num_args`]: crate::Arg::num_args() |
139 | TooFewValues, |
140 | |
141 | /// Occurs when the user provides a different number of values for an argument than what's |
142 | /// been defined by setting [`Arg::num_args`] or than was implicitly set by |
143 | /// [`Arg::value_names`]. |
144 | /// |
145 | /// # Examples |
146 | /// |
147 | /// ```rust |
148 | /// # use clap_builder as clap; |
149 | /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; |
150 | /// let result = Command::new("prog" ) |
151 | /// .arg(Arg::new("some_opt" ) |
152 | /// .long("opt" ) |
153 | /// .action(ArgAction::Set) |
154 | /// .num_args(2)) |
155 | /// .try_get_matches_from(vec!["prog" , "--opt" , "wrong" ]); |
156 | /// assert!(result.is_err()); |
157 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::WrongNumberOfValues); |
158 | /// ``` |
159 | /// |
160 | /// [`Arg::num_args`]: crate::Arg::num_args() |
161 | /// [`Arg::value_names`]: crate::Arg::value_names() |
162 | WrongNumberOfValues, |
163 | |
164 | /// Occurs when the user provides two values which conflict with each other and can't be used |
165 | /// together. |
166 | /// |
167 | /// # Examples |
168 | /// |
169 | /// ```rust |
170 | /// # use clap_builder as clap; |
171 | /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; |
172 | /// let result = Command::new("prog" ) |
173 | /// .arg(Arg::new("debug" ) |
174 | /// .long("debug" ) |
175 | /// .action(ArgAction::SetTrue) |
176 | /// .conflicts_with("color" )) |
177 | /// .arg(Arg::new("color" ) |
178 | /// .long("color" ) |
179 | /// .action(ArgAction::SetTrue)) |
180 | /// .try_get_matches_from(vec!["prog" , "--debug" , "--color" ]); |
181 | /// assert!(result.is_err()); |
182 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict); |
183 | /// ``` |
184 | ArgumentConflict, |
185 | |
186 | /// Occurs when the user does not provide one or more required arguments. |
187 | /// |
188 | /// # Examples |
189 | /// |
190 | /// ```rust |
191 | /// # use clap_builder as clap; |
192 | /// # use clap::{Command, Arg, error::ErrorKind}; |
193 | /// let result = Command::new("prog" ) |
194 | /// .arg(Arg::new("debug" ) |
195 | /// .required(true)) |
196 | /// .try_get_matches_from(vec!["prog" ]); |
197 | /// assert!(result.is_err()); |
198 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); |
199 | /// ``` |
200 | MissingRequiredArgument, |
201 | |
202 | /// Occurs when a subcommand is required (as defined by [`Command::subcommand_required`]), |
203 | /// but the user does not provide one. |
204 | /// |
205 | /// # Examples |
206 | /// |
207 | /// ```rust |
208 | /// # use clap_builder as clap; |
209 | /// # use clap::{Command, error::ErrorKind}; |
210 | /// let err = Command::new("prog" ) |
211 | /// .subcommand_required(true) |
212 | /// .subcommand(Command::new("test" )) |
213 | /// .try_get_matches_from(vec![ |
214 | /// "myprog" , |
215 | /// ]); |
216 | /// assert!(err.is_err()); |
217 | /// assert_eq!(err.unwrap_err().kind(), ErrorKind::MissingSubcommand); |
218 | /// # ; |
219 | /// ``` |
220 | /// |
221 | /// [`Command::subcommand_required`]: crate::Command::subcommand_required |
222 | MissingSubcommand, |
223 | |
224 | /// Occurs when the user provides a value containing invalid UTF-8. |
225 | /// |
226 | /// To allow arbitrary data |
227 | /// - Set [`Arg::value_parser(value_parser!(OsString))`] for argument values |
228 | /// - Set [`Command::external_subcommand_value_parser`] for external-subcommand |
229 | /// values |
230 | /// |
231 | /// # Platform Specific |
232 | /// |
233 | /// Non-Windows platforms only (such as Linux, Unix, OSX, etc.) |
234 | /// |
235 | /// # Examples |
236 | /// |
237 | /// ```rust |
238 | /// # #[cfg (unix)] { |
239 | /// # use clap_builder as clap; |
240 | /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; |
241 | /// # use std::os::unix::ffi::OsStringExt; |
242 | /// # use std::ffi::OsString; |
243 | /// let result = Command::new("prog" ) |
244 | /// .arg(Arg::new("utf8" ) |
245 | /// .short('u' ) |
246 | /// .action(ArgAction::Set)) |
247 | /// .try_get_matches_from(vec![OsString::from("myprog" ), |
248 | /// OsString::from("-u" ), |
249 | /// OsString::from_vec(vec![0xE9])]); |
250 | /// assert!(result.is_err()); |
251 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidUtf8); |
252 | /// # } |
253 | /// ``` |
254 | /// |
255 | /// [`Arg::allow_invalid_utf8`]: crate::Arg::allow_invalid_utf8 |
256 | /// [`Command::external_subcommand_value_parser`]: crate::Command::external_subcommand_value_parser |
257 | InvalidUtf8, |
258 | |
259 | /// Not a true "error" as it means `--help` or similar was used. |
260 | /// The help message will be sent to `stdout`. |
261 | /// |
262 | /// **Note**: If the help is displayed due to an error (such as missing subcommands) it will |
263 | /// be sent to `stderr` instead of `stdout`. |
264 | /// |
265 | /// # Examples |
266 | /// |
267 | /// ```rust |
268 | /// # #[cfg (feature = "help" )] { |
269 | /// # use clap_builder as clap; |
270 | /// # use clap::{Command, Arg, error::ErrorKind}; |
271 | /// let result = Command::new("prog" ) |
272 | /// .try_get_matches_from(vec!["prog" , "--help" ]); |
273 | /// assert!(result.is_err()); |
274 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelp); |
275 | /// # } |
276 | /// ``` |
277 | DisplayHelp, |
278 | |
279 | /// Occurs when either an argument or a [`Subcommand`] is required, as defined by |
280 | /// [`Command::arg_required_else_help`] , but the user did not provide |
281 | /// one. |
282 | /// |
283 | /// # Examples |
284 | /// |
285 | /// ```rust |
286 | /// # use clap_builder as clap; |
287 | /// # use clap::{Command, Arg, error::ErrorKind, }; |
288 | /// let result = Command::new("prog" ) |
289 | /// .arg_required_else_help(true) |
290 | /// .subcommand(Command::new("config" ) |
291 | /// .about("Used for configuration" ) |
292 | /// .arg(Arg::new("config_file" ) |
293 | /// .help("The configuration file to use" ))) |
294 | /// .try_get_matches_from(vec!["prog" ]); |
295 | /// assert!(result.is_err()); |
296 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand); |
297 | /// ``` |
298 | /// |
299 | /// [`Subcommand`]: crate::Subcommand |
300 | /// [`Command::arg_required_else_help`]: crate::Command::arg_required_else_help |
301 | DisplayHelpOnMissingArgumentOrSubcommand, |
302 | |
303 | /// Not a true "error" as it means `--version` or similar was used. |
304 | /// The message will be sent to `stdout`. |
305 | /// |
306 | /// # Examples |
307 | /// |
308 | /// ```rust |
309 | /// # use clap_builder as clap; |
310 | /// # use clap::{Command, Arg, error::ErrorKind}; |
311 | /// let result = Command::new("prog" ) |
312 | /// .version("3.0" ) |
313 | /// .try_get_matches_from(vec!["prog" , "--version" ]); |
314 | /// assert!(result.is_err()); |
315 | /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayVersion); |
316 | /// ``` |
317 | DisplayVersion, |
318 | |
319 | /// Represents an [I/O error]. |
320 | /// Can occur when writing to `stderr` or `stdout` or reading a configuration file. |
321 | /// |
322 | /// [I/O error]: std::io::Error |
323 | Io, |
324 | |
325 | /// Represents a [Format error] (which is a part of [`Display`]). |
326 | /// Typically caused by writing to `stderr` or `stdout`. |
327 | /// |
328 | /// [`Display`]: std::fmt::Display |
329 | /// [Format error]: std::fmt::Error |
330 | Format, |
331 | } |
332 | |
333 | impl ErrorKind { |
334 | /// End-user description of the error case, where relevant |
335 | pub fn as_str(self) -> Option<&'static str> { |
336 | match self { |
337 | Self::InvalidValue => Some("one of the values isn't valid for an argument" ), |
338 | Self::UnknownArgument => Some("unexpected argument found" ), |
339 | Self::InvalidSubcommand => Some("unrecognized subcommand" ), |
340 | Self::NoEquals => Some("equal is needed when assigning values to one of the arguments" ), |
341 | Self::ValueValidation => Some("invalid value for one of the arguments" ), |
342 | Self::TooManyValues => Some("unexpected value for an argument found" ), |
343 | Self::TooFewValues => Some("more values required for an argument" ), |
344 | Self::WrongNumberOfValues => Some("too many or too few values for an argument" ), |
345 | Self::ArgumentConflict => { |
346 | Some("an argument cannot be used with one or more of the other specified arguments" ) |
347 | } |
348 | Self::MissingRequiredArgument => { |
349 | Some("one or more required arguments were not provided" ) |
350 | } |
351 | Self::MissingSubcommand => Some("a subcommand is required but one was not provided" ), |
352 | Self::InvalidUtf8 => Some("invalid UTF-8 was detected in one or more arguments" ), |
353 | Self::DisplayHelp => None, |
354 | Self::DisplayHelpOnMissingArgumentOrSubcommand => None, |
355 | Self::DisplayVersion => None, |
356 | Self::Io => None, |
357 | Self::Format => None, |
358 | } |
359 | } |
360 | } |
361 | |
362 | impl std::fmt::Display for ErrorKind { |
363 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
364 | self.as_str().unwrap_or_default().fmt(f) |
365 | } |
366 | } |
367 | |