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