• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::{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 
315 impl ErrorKind {
316     /// End-user description of the error case, where relevant
as_str(self) -> Option<&'static str>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 
344 impl std::fmt::Display for ErrorKind {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result345     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
346         self.as_str().unwrap_or_default().fmt(f)
347     }
348 }
349