1 // Std
2 use std::{
3 borrow::Cow,
4 convert::From,
5 error,
6 fmt::{self, Debug, Display, Formatter},
7 io::{self, BufRead},
8 result::Result as StdResult,
9 };
10
11 // Internal
12 use crate::{
13 build::Arg,
14 output::fmt::Colorizer,
15 parse::features::suggestions,
16 util::{color::ColorChoice, safe_exit, SUCCESS_CODE, USAGE_CODE},
17 App, AppSettings,
18 };
19
20 /// Short hand for [`Result`] type
21 ///
22 /// [`Result`]: std::result::Result
23 pub type Result<T> = StdResult<T, Error>;
24
25 /// Command line argument parser kind of error
26 #[derive(Debug, Copy, Clone, PartialEq)]
27 #[non_exhaustive]
28 pub enum ErrorKind {
29 /// Occurs when an [`Arg`] has a set of possible values,
30 /// and the user provides a value which isn't in that set.
31 ///
32 /// # Examples
33 ///
34 /// ```rust
35 /// # use clap::{App, Arg, ErrorKind};
36 /// let result = App::new("prog")
37 /// .arg(Arg::new("speed")
38 /// .possible_value("fast")
39 /// .possible_value("slow"))
40 /// .try_get_matches_from(vec!["prog", "other"]);
41 /// assert!(result.is_err());
42 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue);
43 /// ```
44 InvalidValue,
45
46 /// Occurs when a user provides a flag, option, argument or subcommand which isn't defined.
47 ///
48 /// # Examples
49 ///
50 /// ```rust
51 /// # use clap::{App, arg, ErrorKind};
52 /// let result = App::new("prog")
53 /// .arg(arg!(--flag "some flag"))
54 /// .try_get_matches_from(vec!["prog", "--other"]);
55 /// assert!(result.is_err());
56 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::UnknownArgument);
57 /// ```
58 UnknownArgument,
59
60 /// Occurs when the user provides an unrecognized [`Subcommand`] which meets the threshold for
61 /// being similar enough to an existing subcommand.
62 /// If it doesn't meet the threshold, or the 'suggestions' feature is disabled,
63 /// the more general [`UnknownArgument`] error is returned.
64 ///
65 /// # Examples
66 ///
67 #[cfg_attr(not(feature = "suggestions"), doc = " ```no_run")]
68 #[cfg_attr(feature = "suggestions", doc = " ```")]
69 /// # use clap::{App, Arg, ErrorKind, };
70 /// let result = App::new("prog")
71 /// .subcommand(App::new("config")
72 /// .about("Used for configuration")
73 /// .arg(Arg::new("config_file")
74 /// .help("The configuration file to use")
75 /// .index(1)))
76 /// .try_get_matches_from(vec!["prog", "confi"]);
77 /// assert!(result.is_err());
78 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidSubcommand);
79 /// ```
80 ///
81 /// [`Subcommand`]: crate::Subcommand
82 /// [`UnknownArgument`]: ErrorKind::UnknownArgument
83 InvalidSubcommand,
84
85 /// Occurs when the user provides an unrecognized [`Subcommand`] which either
86 /// doesn't meet the threshold for being similar enough to an existing subcommand,
87 /// or the 'suggestions' feature is disabled.
88 /// Otherwise the more detailed [`InvalidSubcommand`] error is returned.
89 ///
90 /// This error typically happens when passing additional subcommand names to the `help`
91 /// subcommand. Otherwise, the more general [`UnknownArgument`] error is used.
92 ///
93 /// # Examples
94 ///
95 /// ```rust
96 /// # use clap::{App, Arg, ErrorKind, };
97 /// let result = App::new("prog")
98 /// .subcommand(App::new("config")
99 /// .about("Used for configuration")
100 /// .arg(Arg::new("config_file")
101 /// .help("The configuration file to use")
102 /// .index(1)))
103 /// .try_get_matches_from(vec!["prog", "help", "nothing"]);
104 /// assert!(result.is_err());
105 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::UnrecognizedSubcommand);
106 /// ```
107 ///
108 /// [`Subcommand`]: crate::Subcommand
109 /// [`InvalidSubcommand`]: ErrorKind::InvalidSubcommand
110 /// [`UnknownArgument`]: ErrorKind::UnknownArgument
111 UnrecognizedSubcommand,
112
113 /// Occurs when the user provides an empty value for an option that does not allow empty
114 /// values.
115 ///
116 /// # Examples
117 ///
118 /// ```rust
119 /// # use clap::{App, Arg, ErrorKind};
120 /// let res = App::new("prog")
121 /// .arg(Arg::new("color")
122 /// .takes_value(true)
123 /// .forbid_empty_values(true)
124 /// .long("color"))
125 /// .try_get_matches_from(vec!["prog", "--color="]);
126 /// assert!(res.is_err());
127 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::EmptyValue);
128 /// ```
129 EmptyValue,
130
131 /// Occurs when the user doesn't use equals for an option that requires equal
132 /// sign to provide values.
133 ///
134 /// ```rust
135 /// # use clap::{App, Arg, ErrorKind};
136 /// let res = App::new("prog")
137 /// .arg(Arg::new("color")
138 /// .takes_value(true)
139 /// .require_equals(true)
140 /// .long("color"))
141 /// .try_get_matches_from(vec!["prog", "--color", "red"]);
142 /// assert!(res.is_err());
143 /// assert_eq!(res.unwrap_err().kind(), ErrorKind::NoEquals);
144 /// ```
145 NoEquals,
146
147 /// Occurs when the user provides a value for an argument with a custom validation and the
148 /// value fails that validation.
149 ///
150 /// # Examples
151 ///
152 /// ```rust
153 /// # use clap::{App, Arg, ErrorKind};
154 /// fn is_numeric(val: &str) -> Result<(), String> {
155 /// match val.parse::<i64>() {
156 /// Ok(..) => Ok(()),
157 /// Err(..) => Err(String::from("Value wasn't a number!")),
158 /// }
159 /// }
160 ///
161 /// let result = App::new("prog")
162 /// .arg(Arg::new("num")
163 /// .validator(is_numeric))
164 /// .try_get_matches_from(vec!["prog", "NotANumber"]);
165 /// assert!(result.is_err());
166 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::ValueValidation);
167 /// ```
168 ValueValidation,
169
170 /// Occurs when a user provides more values for an argument than were defined by setting
171 /// [`Arg::max_values`].
172 ///
173 /// # Examples
174 ///
175 /// ```rust
176 /// # use clap::{App, Arg, ErrorKind};
177 /// let result = App::new("prog")
178 /// .arg(Arg::new("arg")
179 /// .max_values(2))
180 /// .try_get_matches_from(vec!["prog", "too", "many", "values"]);
181 /// assert!(result.is_err());
182 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyValues);
183 /// ```
184 /// [`Arg::max_values`]: Arg::max_values()
185 TooManyValues,
186
187 /// Occurs when the user provides fewer values for an argument than were defined by setting
188 /// [`Arg::min_values`].
189 ///
190 /// # Examples
191 ///
192 /// ```rust
193 /// # use clap::{App, Arg, ErrorKind};
194 /// let result = App::new("prog")
195 /// .arg(Arg::new("some_opt")
196 /// .long("opt")
197 /// .min_values(3))
198 /// .try_get_matches_from(vec!["prog", "--opt", "too", "few"]);
199 /// assert!(result.is_err());
200 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooFewValues);
201 /// ```
202 /// [`Arg::min_values`]: Arg::min_values()
203 TooFewValues,
204
205 /// Occurs when a user provides more occurrences for an argument than were defined by setting
206 /// [`Arg::max_occurrences`].
207 ///
208 /// # Examples
209 ///
210 /// ```rust
211 /// # use clap::{App, Arg, ErrorKind};
212 /// let result = App::new("prog")
213 /// .arg(Arg::new("verbosity")
214 /// .short('v')
215 /// .max_occurrences(2))
216 /// .try_get_matches_from(vec!["prog", "-vvv"]);
217 /// assert!(result.is_err());
218 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyOccurrences);
219 /// ```
220 /// [`Arg::max_occurrences`]: Arg::max_occurrences()
221 TooManyOccurrences,
222
223 /// Occurs when the user provides a different number of values for an argument than what's
224 /// been defined by setting [`Arg::number_of_values`] or than was implicitly set by
225 /// [`Arg::value_names`].
226 ///
227 /// # Examples
228 ///
229 /// ```rust
230 /// # use clap::{App, Arg, ErrorKind};
231 /// let result = App::new("prog")
232 /// .arg(Arg::new("some_opt")
233 /// .long("opt")
234 /// .takes_value(true)
235 /// .number_of_values(2))
236 /// .try_get_matches_from(vec!["prog", "--opt", "wrong"]);
237 /// assert!(result.is_err());
238 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::WrongNumberOfValues);
239 /// ```
240 ///
241 /// [`Arg::number_of_values`]: Arg::number_of_values()
242 /// [`Arg::value_names`]: Arg::value_names()
243 WrongNumberOfValues,
244
245 /// Occurs when the user provides two values which conflict with each other and can't be used
246 /// together.
247 ///
248 /// # Examples
249 ///
250 /// ```rust
251 /// # use clap::{App, Arg, ErrorKind};
252 /// let result = App::new("prog")
253 /// .arg(Arg::new("debug")
254 /// .long("debug")
255 /// .conflicts_with("color"))
256 /// .arg(Arg::new("color")
257 /// .long("color"))
258 /// .try_get_matches_from(vec!["prog", "--debug", "--color"]);
259 /// assert!(result.is_err());
260 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict);
261 /// ```
262 ArgumentConflict,
263
264 /// Occurs when the user does not provide one or more required arguments.
265 ///
266 /// # Examples
267 ///
268 /// ```rust
269 /// # use clap::{App, Arg, ErrorKind};
270 /// let result = App::new("prog")
271 /// .arg(Arg::new("debug")
272 /// .required(true))
273 /// .try_get_matches_from(vec!["prog"]);
274 /// assert!(result.is_err());
275 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
276 /// ```
277 MissingRequiredArgument,
278
279 /// Occurs when a subcommand is required (as defined by [`AppSettings::SubcommandRequired`]),
280 /// but the user does not provide one.
281 ///
282 /// # Examples
283 ///
284 /// ```rust
285 /// # use clap::{App, AppSettings, ErrorKind};
286 /// let err = App::new("prog")
287 /// .setting(AppSettings::SubcommandRequired)
288 /// .subcommand(App::new("test"))
289 /// .try_get_matches_from(vec![
290 /// "myprog",
291 /// ]);
292 /// assert!(err.is_err());
293 /// assert_eq!(err.unwrap_err().kind(), ErrorKind::MissingSubcommand);
294 /// # ;
295 /// ```
296 ///
297 /// [`AppSettings::SubcommandRequired`]: crate::AppSettings::SubcommandRequired
298 MissingSubcommand,
299
300 /// Occurs when the user provides multiple values to an argument which doesn't allow that.
301 ///
302 /// # Examples
303 ///
304 /// ```rust
305 /// # use clap::{App, Arg, ErrorKind};
306 /// let result = App::new("prog")
307 /// .arg(Arg::new("debug")
308 /// .long("debug")
309 /// .multiple_occurrences(false))
310 /// .try_get_matches_from(vec!["prog", "--debug", "--debug"]);
311 /// assert!(result.is_err());
312 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::UnexpectedMultipleUsage);
313 /// ```
314 UnexpectedMultipleUsage,
315
316 /// Occurs when the user provides a value containing invalid UTF-8.
317 ///
318 /// To allow arbitrary data
319 /// - Set [`Arg::allow_invalid_utf8`] for argument values
320 /// - Set [`AppSettings::AllowInvalidUtf8ForExternalSubcommands`] for external-subcommand
321 /// values
322 ///
323 /// # Platform Specific
324 ///
325 /// Non-Windows platforms only (such as Linux, Unix, OSX, etc.)
326 ///
327 /// # Examples
328 ///
329 #[cfg_attr(not(unix), doc = " ```ignore")]
330 #[cfg_attr(unix, doc = " ```")]
331 /// # use clap::{App, Arg, ErrorKind, AppSettings};
332 /// # use std::os::unix::ffi::OsStringExt;
333 /// # use std::ffi::OsString;
334 /// let result = App::new("prog")
335 /// .arg(Arg::new("utf8")
336 /// .short('u')
337 /// .takes_value(true))
338 /// .try_get_matches_from(vec![OsString::from("myprog"),
339 /// OsString::from("-u"),
340 /// OsString::from_vec(vec![0xE9])]);
341 /// assert!(result.is_err());
342 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidUtf8);
343 /// ```
344 ///
345 /// [`Arg::allow_invalid_utf8`]: crate::Arg::allow_invalid_utf8
346 /// [`AppSettings::AllowInvalidUtf8ForExternalSubcommands`]: crate::AppSettings::AllowInvalidUtf8ForExternalSubcommands
347 InvalidUtf8,
348
349 /// Not a true "error" as it means `--help` or similar was used.
350 /// The help message will be sent to `stdout`.
351 ///
352 /// **Note**: If the help is displayed due to an error (such as missing subcommands) it will
353 /// be sent to `stderr` instead of `stdout`.
354 ///
355 /// # Examples
356 ///
357 /// ```rust
358 /// # use clap::{App, Arg, ErrorKind};
359 /// let result = App::new("prog")
360 /// .try_get_matches_from(vec!["prog", "--help"]);
361 /// assert!(result.is_err());
362 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelp);
363 /// ```
364 DisplayHelp,
365
366 /// Occurs when either an argument or a [`Subcommand`] is required, as defined by
367 /// [`AppSettings::ArgRequiredElseHelp`] and
368 /// [`AppSettings::SubcommandRequiredElseHelp`], but the user did not provide
369 /// one.
370 ///
371 /// # Examples
372 ///
373 /// ```rust
374 /// # use clap::{App, Arg, AppSettings, ErrorKind, };
375 /// let result = App::new("prog")
376 /// .setting(AppSettings::ArgRequiredElseHelp)
377 /// .subcommand(App::new("config")
378 /// .about("Used for configuration")
379 /// .arg(Arg::new("config_file")
380 /// .help("The configuration file to use")))
381 /// .try_get_matches_from(vec!["prog"]);
382 /// assert!(result.is_err());
383 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand);
384 /// ```
385 ///
386 /// [`Subcommand`]: crate::Subcommand
387 /// [`AppSettings::ArgRequiredElseHelp`]: crate::AppSettings::ArgRequiredElseHelp
388 /// [`AppSettings::SubcommandRequiredElseHelp`]: crate::AppSettings::SubcommandRequiredElseHelp
389 DisplayHelpOnMissingArgumentOrSubcommand,
390
391 /// Not a true "error" as it means `--version` or similar was used.
392 /// The message will be sent to `stdout`.
393 ///
394 /// # Examples
395 ///
396 /// ```rust
397 /// # use clap::{App, Arg, ErrorKind};
398 /// let result = App::new("prog")
399 /// .version("3.0")
400 /// .try_get_matches_from(vec!["prog", "--version"]);
401 /// assert!(result.is_err());
402 /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayVersion);
403 /// ```
404 DisplayVersion,
405
406 /// Occurs when using the [`ArgMatches::value_of_t`] and friends to convert an argument value
407 /// into type `T`, but the argument you requested wasn't used. I.e. you asked for an argument
408 /// with name `config` to be converted, but `config` wasn't used by the user.
409 ///
410 /// [`ArgMatches::value_of_t`]: crate::ArgMatches::value_of_t()
411 ArgumentNotFound,
412
413 /// Represents an [I/O error].
414 /// Can occur when writing to `stderr` or `stdout` or reading a configuration file.
415 ///
416 /// [I/O error]: std::io::Error
417 Io,
418
419 /// Represents a [Format error] (which is a part of [`Display`]).
420 /// Typically caused by writing to `stderr` or `stdout`.
421 ///
422 /// [`Display`]: std::fmt::Display
423 /// [Format error]: std::fmt::Error
424 Format,
425 }
426
427 /// Command Line Argument Parser Error
428 ///
429 /// See [`App::error`] to create an error.
430 ///
431 /// [`App::error`]: crate::App::error
432 #[derive(Debug)]
433 pub struct Error {
434 /// Formatted error message, enhancing the cause message with extra information
435 message: Message,
436 /// The type of error
437 pub kind: ErrorKind,
438 /// Additional information depending on the error kind, like values and argument names.
439 /// Useful when you want to render an error of your own.
440 pub info: Vec<String>,
441 source: Option<Box<dyn error::Error + Send + Sync>>,
442 wait_on_exit: bool,
443 backtrace: Option<Backtrace>,
444 }
445
446 impl Error {
447 /// Create an unformatted error
448 ///
449 /// This is for you need to pass the error up to
450 /// a place that has access to the `App` at which point you can call [`Error::format`].
451 ///
452 /// Prefer [`App::error`] for generating errors.
453 ///
454 /// [`App::error`]: crate::App::error
raw(kind: ErrorKind, message: impl std::fmt::Display) -> Self455 pub fn raw(kind: ErrorKind, message: impl std::fmt::Display) -> Self {
456 Self::new(message.to_string(), kind, false)
457 }
458
459 /// Format the existing message with the App's context
460 #[must_use]
format(mut self, app: &mut App) -> Self461 pub fn format(mut self, app: &mut App) -> Self {
462 app._build();
463 let usage = app.render_usage();
464 self.message.format(app, usage);
465 self.wait_on_exit = app.settings.is_set(AppSettings::WaitOnError);
466 self
467 }
468
469 /// Type of error for programmatic processing
kind(&self) -> ErrorKind470 pub fn kind(&self) -> ErrorKind {
471 self.kind
472 }
473
474 /// Should the message be written to `stdout` or not?
475 #[inline]
use_stderr(&self) -> bool476 pub fn use_stderr(&self) -> bool {
477 !matches!(
478 self.kind(),
479 ErrorKind::DisplayHelp | ErrorKind::DisplayVersion
480 )
481 }
482
483 /// Prints the error and exits.
484 ///
485 /// Depending on the error kind, this either prints to `stderr` and exits with a status of `2`
486 /// or prints to `stdout` and exits with a status of `0`.
exit(&self) -> !487 pub fn exit(&self) -> ! {
488 if self.use_stderr() {
489 // Swallow broken pipe errors
490 let _ = self.print();
491
492 if self.wait_on_exit {
493 wlnerr!("\nPress [ENTER] / [RETURN] to continue...");
494 let mut s = String::new();
495 let i = io::stdin();
496 i.lock().read_line(&mut s).unwrap();
497 }
498
499 safe_exit(USAGE_CODE);
500 }
501
502 // Swallow broken pipe errors
503 let _ = self.print();
504 safe_exit(SUCCESS_CODE)
505 }
506
507 /// Prints formatted and colored error to `stdout` or `stderr` according to its error kind
508 ///
509 /// # Example
510 /// ```no_run
511 /// use clap::App;
512 ///
513 /// match App::new("App").try_get_matches() {
514 /// Ok(matches) => {
515 /// // do_something
516 /// },
517 /// Err(err) => {
518 /// err.print().expect("Error writing Error");
519 /// // do_something
520 /// },
521 /// };
522 /// ```
print(&self) -> io::Result<()>523 pub fn print(&self) -> io::Result<()> {
524 self.message.formatted().print()
525 }
526
527 /// Deprecated, replaced with [`App::error`]
528 ///
529 /// [`App::error`]: crate::App::error
530 #[deprecated(since = "3.0.0", note = "Replaced with `App::error`")]
with_description(description: String, kind: ErrorKind) -> Self531 pub fn with_description(description: String, kind: ErrorKind) -> Self {
532 Error::raw(kind, description)
533 }
534
new(message: impl Into<Message>, kind: ErrorKind, wait_on_exit: bool) -> Self535 pub(crate) fn new(message: impl Into<Message>, kind: ErrorKind, wait_on_exit: bool) -> Self {
536 Self {
537 message: message.into(),
538 kind,
539 info: vec![],
540 source: None,
541 wait_on_exit,
542 backtrace: Backtrace::new(),
543 }
544 }
545
546 #[inline(never)]
for_app( app: &App, colorizer: Colorizer, kind: ErrorKind, info: Vec<String>, ) -> Self547 pub(crate) fn for_app(
548 app: &App,
549 colorizer: Colorizer,
550 kind: ErrorKind,
551 info: Vec<String>,
552 ) -> Self {
553 Self::new(
554 colorizer,
555 kind,
556 app.settings.is_set(AppSettings::WaitOnError),
557 )
558 .set_info(info)
559 }
560
set_info(mut self, info: Vec<String>) -> Self561 pub(crate) fn set_info(mut self, info: Vec<String>) -> Self {
562 self.info = info;
563 self
564 }
565
set_source(mut self, source: Box<dyn error::Error + Send + Sync>) -> Self566 pub(crate) fn set_source(mut self, source: Box<dyn error::Error + Send + Sync>) -> Self {
567 self.source = Some(source);
568 self
569 }
570
argument_conflict( app: &App, arg: &Arg, others: Vec<String>, usage: String, ) -> Self571 pub(crate) fn argument_conflict(
572 app: &App,
573 arg: &Arg,
574 others: Vec<String>,
575 usage: String,
576 ) -> Self {
577 let mut c = Colorizer::new(true, app.get_color());
578 let arg = arg.to_string();
579
580 start_error(&mut c, "The argument '");
581 c.warning(arg);
582 c.none("' cannot be used with");
583
584 match others.len() {
585 0 => {
586 c.none(" one or more of the other specified arguments");
587 }
588 1 => {
589 c.none(" '");
590 c.warning(&*others[0]);
591 c.none("'");
592 }
593 _ => {
594 c.none(":");
595 for v in &others {
596 c.none("\n ");
597 c.warning(&**v);
598 }
599 }
600 }
601
602 put_usage(&mut c, usage);
603 try_help(app, &mut c);
604
605 Self::for_app(app, c, ErrorKind::ArgumentConflict, others)
606 }
607
empty_value(app: &App, arg: &Arg, usage: String) -> Self608 pub(crate) fn empty_value(app: &App, arg: &Arg, usage: String) -> Self {
609 let mut c = Colorizer::new(true, app.get_color());
610 let arg = arg.to_string();
611
612 start_error(&mut c, "The argument '");
613 c.warning(&*arg);
614 c.none("' requires a value but none was supplied");
615 put_usage(&mut c, usage);
616 try_help(app, &mut c);
617
618 Self::for_app(app, c, ErrorKind::EmptyValue, vec![arg])
619 }
620
no_equals(app: &App, arg: String, usage: String) -> Self621 pub(crate) fn no_equals(app: &App, arg: String, usage: String) -> Self {
622 let mut c = Colorizer::new(true, app.get_color());
623
624 start_error(&mut c, "Equal sign is needed when assigning values to '");
625 c.warning(&*arg);
626 c.none("'.");
627
628 put_usage(&mut c, usage);
629 try_help(app, &mut c);
630
631 Self::for_app(app, c, ErrorKind::NoEquals, vec![arg])
632 }
633
invalid_value( app: &App, bad_val: String, good_vals: &[&str], arg: &Arg, usage: String, ) -> Self634 pub(crate) fn invalid_value(
635 app: &App,
636 bad_val: String,
637 good_vals: &[&str],
638 arg: &Arg,
639 usage: String,
640 ) -> Self {
641 let mut c = Colorizer::new(true, app.get_color());
642 let suffix = suggestions::did_you_mean(&bad_val, good_vals.iter()).pop();
643 let arg = arg.to_string();
644
645 let mut sorted: Vec<String> = good_vals
646 .iter()
647 .map(|&v| {
648 if v.contains(char::is_whitespace) {
649 format!("{:?}", v)
650 } else {
651 v.to_owned()
652 }
653 })
654 .collect();
655 sorted.sort();
656
657 start_error(&mut c, "");
658 c.warning(format!("{:?}", bad_val));
659 c.none(" isn't a valid value for '");
660 c.warning(&*arg);
661 c.none("'\n\t[possible values: ");
662
663 if let Some((last, elements)) = sorted.split_last() {
664 for v in elements {
665 c.good(v);
666 c.none(", ");
667 }
668
669 c.good(last);
670 }
671
672 c.none("]");
673
674 if let Some(val) = suffix {
675 c.none("\n\n\tDid you mean ");
676 c.good(format!("{:?}", val));
677 c.none("?");
678 }
679
680 put_usage(&mut c, usage);
681 try_help(app, &mut c);
682
683 let mut info = vec![arg, bad_val];
684 info.extend(sorted);
685
686 Self::for_app(app, c, ErrorKind::InvalidValue, info)
687 }
688
invalid_subcommand( app: &App, subcmd: String, did_you_mean: String, name: String, usage: String, ) -> Self689 pub(crate) fn invalid_subcommand(
690 app: &App,
691 subcmd: String,
692 did_you_mean: String,
693 name: String,
694 usage: String,
695 ) -> Self {
696 let mut c = Colorizer::new(true, app.get_color());
697
698 start_error(&mut c, "The subcommand '");
699 c.warning(&*subcmd);
700 c.none("' wasn't recognized\n\n\tDid you mean ");
701 c.good(did_you_mean);
702 c.none("");
703 c.none(format!(
704 "?\n\nIf you believe you received this message in error, try re-running with '{} ",
705 name
706 ));
707 c.good("--");
708 c.none(format!(" {}'", subcmd));
709 put_usage(&mut c, usage);
710 try_help(app, &mut c);
711
712 Self::for_app(app, c, ErrorKind::InvalidSubcommand, vec![subcmd])
713 }
714
unrecognized_subcommand(app: &App, subcmd: String, name: String) -> Self715 pub(crate) fn unrecognized_subcommand(app: &App, subcmd: String, name: String) -> Self {
716 let mut c = Colorizer::new(true, app.get_color());
717
718 start_error(&mut c, " The subcommand '");
719 c.warning(&*subcmd);
720 c.none("' wasn't recognized\n\n");
721 c.warning("USAGE:");
722 c.none(format!("\n {} <subcommands>", name));
723 try_help(app, &mut c);
724
725 Self::for_app(app, c, ErrorKind::UnrecognizedSubcommand, vec![subcmd])
726 }
727
missing_required_argument( app: &App, required: Vec<String>, usage: String, ) -> Self728 pub(crate) fn missing_required_argument(
729 app: &App,
730 required: Vec<String>,
731 usage: String,
732 ) -> Self {
733 let mut c = Colorizer::new(true, app.get_color());
734
735 start_error(
736 &mut c,
737 "The following required arguments were not provided:",
738 );
739
740 for v in &required {
741 c.none("\n ");
742 c.good(&**v);
743 }
744
745 put_usage(&mut c, usage);
746 try_help(app, &mut c);
747
748 Self::for_app(app, c, ErrorKind::MissingRequiredArgument, required)
749 }
750
missing_subcommand(app: &App, name: String, usage: String) -> Self751 pub(crate) fn missing_subcommand(app: &App, name: String, usage: String) -> Self {
752 let mut c = Colorizer::new(true, app.get_color());
753
754 start_error(&mut c, "'");
755 c.warning(name);
756 c.none("' requires a subcommand, but one was not provided");
757 put_usage(&mut c, usage);
758 try_help(app, &mut c);
759
760 Self::for_app(app, c, ErrorKind::MissingSubcommand, vec![])
761 }
762
invalid_utf8(app: &App, usage: String) -> Self763 pub(crate) fn invalid_utf8(app: &App, usage: String) -> Self {
764 let mut c = Colorizer::new(true, app.get_color());
765
766 start_error(
767 &mut c,
768 "Invalid UTF-8 was detected in one or more arguments",
769 );
770 put_usage(&mut c, usage);
771 try_help(app, &mut c);
772
773 Self::for_app(app, c, ErrorKind::InvalidUtf8, vec![])
774 }
775
too_many_occurrences( app: &App, arg: &Arg, max_occurs: usize, curr_occurs: usize, usage: String, ) -> Self776 pub(crate) fn too_many_occurrences(
777 app: &App,
778 arg: &Arg,
779 max_occurs: usize,
780 curr_occurs: usize,
781 usage: String,
782 ) -> Self {
783 let mut c = Colorizer::new(true, app.get_color());
784 let were_provided = Error::singular_or_plural(curr_occurs);
785 let arg = arg.to_string();
786 let max_occurs = max_occurs.to_string();
787 let curr_occurs = curr_occurs.to_string();
788
789 start_error(&mut c, "The argument '");
790 c.warning(&*arg);
791 c.none("' allows at most ");
792 c.warning(&*max_occurs);
793 c.none(" occurrences, but ");
794 c.warning(&*curr_occurs);
795 c.none(were_provided);
796 put_usage(&mut c, usage);
797 try_help(app, &mut c);
798
799 Self::for_app(
800 app,
801 c,
802 ErrorKind::TooManyOccurrences,
803 vec![arg, curr_occurs, max_occurs],
804 )
805 }
806
too_many_values(app: &App, val: String, arg: String, usage: String) -> Self807 pub(crate) fn too_many_values(app: &App, val: String, arg: String, usage: String) -> Self {
808 let mut c = Colorizer::new(true, app.get_color());
809
810 start_error(&mut c, "The value '");
811 c.warning(&*val);
812 c.none("' was provided to '");
813 c.warning(&*arg);
814 c.none("' but it wasn't expecting any more values");
815 put_usage(&mut c, usage);
816 try_help(app, &mut c);
817
818 Self::for_app(app, c, ErrorKind::TooManyValues, vec![arg, val])
819 }
820
too_few_values( app: &App, arg: &Arg, min_vals: usize, curr_vals: usize, usage: String, ) -> Self821 pub(crate) fn too_few_values(
822 app: &App,
823 arg: &Arg,
824 min_vals: usize,
825 curr_vals: usize,
826 usage: String,
827 ) -> Self {
828 let mut c = Colorizer::new(true, app.get_color());
829 let were_provided = Error::singular_or_plural(curr_vals);
830 let arg = arg.to_string();
831 let min_vals = min_vals.to_string();
832 let curr_vals = curr_vals.to_string();
833
834 start_error(&mut c, "The argument '");
835 c.warning(&*arg);
836 c.none("' requires at least ");
837 c.warning(&*min_vals);
838 c.none(" values, but only ");
839 c.warning(&*curr_vals);
840 c.none(were_provided);
841 put_usage(&mut c, usage);
842 try_help(app, &mut c);
843
844 Self::for_app(
845 app,
846 c,
847 ErrorKind::TooFewValues,
848 vec![arg, curr_vals, min_vals],
849 )
850 }
851
value_validation( app: &App, arg: String, val: String, err: Box<dyn error::Error + Send + Sync>, ) -> Self852 pub(crate) fn value_validation(
853 app: &App,
854 arg: String,
855 val: String,
856 err: Box<dyn error::Error + Send + Sync>,
857 ) -> Self {
858 let mut err = Self::value_validation_with_color(
859 arg,
860 val,
861 err,
862 app.get_color(),
863 app.settings.is_set(AppSettings::WaitOnError),
864 );
865 match &mut err.message {
866 Message::Raw(_) => {
867 unreachable!("`value_validation_with_color` only deals in formatted errors")
868 }
869 Message::Formatted(c) => try_help(app, c),
870 }
871 err
872 }
873
value_validation_without_app( arg: String, val: String, err: Box<dyn error::Error + Send + Sync>, ) -> Self874 pub(crate) fn value_validation_without_app(
875 arg: String,
876 val: String,
877 err: Box<dyn error::Error + Send + Sync>,
878 ) -> Self {
879 let mut err = Self::value_validation_with_color(arg, val, err, ColorChoice::Never, false);
880 match &mut err.message {
881 Message::Raw(_) => {
882 unreachable!("`value_validation_with_color` only deals in formatted errors")
883 }
884 Message::Formatted(c) => {
885 c.none("\n");
886 }
887 }
888 err
889 }
890
value_validation_with_color( arg: String, val: String, err: Box<dyn error::Error + Send + Sync>, color: ColorChoice, wait_on_exit: bool, ) -> Self891 fn value_validation_with_color(
892 arg: String,
893 val: String,
894 err: Box<dyn error::Error + Send + Sync>,
895 color: ColorChoice,
896 wait_on_exit: bool,
897 ) -> Self {
898 let mut c = Colorizer::new(true, color);
899
900 start_error(&mut c, "Invalid value");
901
902 c.none(" for '");
903 c.warning(&*arg);
904 c.none("'");
905
906 c.none(format!(": {}", err));
907
908 Self::new(c, ErrorKind::ValueValidation, wait_on_exit)
909 .set_info(vec![arg, val, err.to_string()])
910 .set_source(err)
911 }
912
wrong_number_of_values( app: &App, arg: &Arg, num_vals: usize, curr_vals: usize, usage: String, ) -> Self913 pub(crate) fn wrong_number_of_values(
914 app: &App,
915 arg: &Arg,
916 num_vals: usize,
917 curr_vals: usize,
918 usage: String,
919 ) -> Self {
920 let mut c = Colorizer::new(true, app.get_color());
921 let were_provided = Error::singular_or_plural(curr_vals);
922 let arg = arg.to_string();
923 let num_vals = num_vals.to_string();
924 let curr_vals = curr_vals.to_string();
925
926 start_error(&mut c, "The argument '");
927 c.warning(&*arg);
928 c.none("' requires ");
929 c.warning(&*num_vals);
930 c.none(" values, but ");
931 c.warning(&*curr_vals);
932 c.none(were_provided);
933 put_usage(&mut c, usage);
934 try_help(app, &mut c);
935
936 Self::for_app(
937 app,
938 c,
939 ErrorKind::WrongNumberOfValues,
940 vec![arg, curr_vals, num_vals],
941 )
942 }
943
unexpected_multiple_usage(app: &App, arg: &Arg, usage: String) -> Self944 pub(crate) fn unexpected_multiple_usage(app: &App, arg: &Arg, usage: String) -> Self {
945 let mut c = Colorizer::new(true, app.get_color());
946 let arg = arg.to_string();
947
948 start_error(&mut c, "The argument '");
949 c.warning(&*arg);
950 c.none("' was provided more than once, but cannot be used multiple times");
951 put_usage(&mut c, usage);
952 try_help(app, &mut c);
953
954 Self::for_app(app, c, ErrorKind::UnexpectedMultipleUsage, vec![arg])
955 }
956
unknown_argument( app: &App, arg: String, did_you_mean: Option<(String, Option<String>)>, usage: String, ) -> Self957 pub(crate) fn unknown_argument(
958 app: &App,
959 arg: String,
960 did_you_mean: Option<(String, Option<String>)>,
961 usage: String,
962 ) -> Self {
963 let mut c = Colorizer::new(true, app.get_color());
964
965 start_error(&mut c, "Found argument '");
966 c.warning(&*arg);
967 c.none("' which wasn't expected, or isn't valid in this context");
968
969 if let Some((flag, subcmd)) = did_you_mean {
970 let flag = format!("--{}", flag);
971 c.none("\n\n\tDid you mean ");
972
973 if let Some(subcmd) = subcmd {
974 c.none("to put '");
975 c.good(flag);
976 c.none("' after the subcommand '");
977 c.good(subcmd);
978 c.none("'?");
979 } else {
980 c.none("'");
981 c.good(flag);
982 c.none("'?");
983 }
984 }
985
986 // If the user wants to supply things like `--a-flag` or `-b` as a value,
987 // suggest `--` for disambiguation.
988 if arg.starts_with('-') {
989 c.none(format!(
990 "\n\n\tIf you tried to supply `{}` as a value rather than a flag, use `-- {}`",
991 arg, arg
992 ));
993 }
994
995 put_usage(&mut c, usage);
996 try_help(app, &mut c);
997
998 Self::for_app(app, c, ErrorKind::UnknownArgument, vec![arg])
999 }
1000
unnecessary_double_dash(app: &App, arg: String, usage: String) -> Self1001 pub(crate) fn unnecessary_double_dash(app: &App, arg: String, usage: String) -> Self {
1002 let mut c = Colorizer::new(true, app.get_color());
1003
1004 start_error(&mut c, "Found argument '");
1005 c.warning(&*arg);
1006 c.none("' which wasn't expected, or isn't valid in this context");
1007
1008 c.none(format!(
1009 "\n\n\tIf you tried to supply `{}` as a subcommand, remove the '--' before it.",
1010 arg
1011 ));
1012 put_usage(&mut c, usage);
1013 try_help(app, &mut c);
1014
1015 Self::for_app(app, c, ErrorKind::UnknownArgument, vec![arg])
1016 }
1017
argument_not_found_auto(arg: String) -> Self1018 pub(crate) fn argument_not_found_auto(arg: String) -> Self {
1019 let mut c = Colorizer::new(true, ColorChoice::Never);
1020
1021 start_error(&mut c, "The argument '");
1022 c.warning(&*arg);
1023 c.none("' wasn't found\n");
1024
1025 Self::new(c, ErrorKind::ArgumentNotFound, false).set_info(vec![arg])
1026 }
1027
1028 /// Returns the singular or plural form on the verb to be based on the argument's value.
singular_or_plural(n: usize) -> &'static str1029 fn singular_or_plural(n: usize) -> &'static str {
1030 if n > 1 {
1031 " were provided"
1032 } else {
1033 " was provided"
1034 }
1035 }
1036 }
1037
1038 impl From<io::Error> for Error {
from(e: io::Error) -> Self1039 fn from(e: io::Error) -> Self {
1040 Error::raw(ErrorKind::Io, e)
1041 }
1042 }
1043
1044 impl From<fmt::Error> for Error {
from(e: fmt::Error) -> Self1045 fn from(e: fmt::Error) -> Self {
1046 Error::raw(ErrorKind::Format, e)
1047 }
1048 }
1049
1050 impl error::Error for Error {
1051 #[allow(trivial_casts)]
source(&self) -> Option<&(dyn error::Error + 'static)>1052 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
1053 self.source.as_ref().map(|e| e.as_ref() as _)
1054 }
1055 }
1056
1057 impl Display for Error {
fmt(&self, f: &mut Formatter) -> fmt::Result1058 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1059 // Assuming `self.message` already has a trailing newline, from `try_help` or similar
1060 write!(f, "{}", self.message.formatted())?;
1061 if let Some(backtrace) = self.backtrace.as_ref() {
1062 writeln!(f)?;
1063 writeln!(f, "Backtrace:")?;
1064 writeln!(f, "{}", backtrace)?;
1065 }
1066 Ok(())
1067 }
1068 }
1069
start_error(c: &mut Colorizer, msg: impl Into<String>)1070 fn start_error(c: &mut Colorizer, msg: impl Into<String>) {
1071 c.error("error:");
1072 c.none(" ");
1073 c.none(msg);
1074 }
1075
put_usage(c: &mut Colorizer, usage: impl Into<String>)1076 fn put_usage(c: &mut Colorizer, usage: impl Into<String>) {
1077 c.none("\n\n");
1078 c.none(usage);
1079 }
1080
try_help(app: &App, c: &mut Colorizer)1081 fn try_help(app: &App, c: &mut Colorizer) {
1082 if !app.settings.is_set(AppSettings::DisableHelpFlag) {
1083 c.none("\n\nFor more information try ");
1084 c.good("--help");
1085 c.none("\n");
1086 } else if app.has_subcommands() && !app.settings.is_set(AppSettings::DisableHelpSubcommand) {
1087 c.none("\n\nFor more information try ");
1088 c.good("help");
1089 c.none("\n");
1090 } else {
1091 c.none("\n");
1092 }
1093 }
1094
1095 #[derive(Clone, Debug)]
1096 pub(crate) enum Message {
1097 Raw(String),
1098 Formatted(Colorizer),
1099 }
1100
1101 impl Message {
format(&mut self, app: &App, usage: String)1102 fn format(&mut self, app: &App, usage: String) {
1103 match self {
1104 Message::Raw(s) => {
1105 let mut c = Colorizer::new(true, app.get_color());
1106
1107 let mut message = String::new();
1108 std::mem::swap(s, &mut message);
1109 start_error(&mut c, message);
1110 put_usage(&mut c, usage);
1111 try_help(app, &mut c);
1112 *self = Self::Formatted(c);
1113 }
1114 Message::Formatted(_) => {}
1115 }
1116 }
1117
formatted(&self) -> Cow<Colorizer>1118 fn formatted(&self) -> Cow<Colorizer> {
1119 match self {
1120 Message::Raw(s) => {
1121 let mut c = Colorizer::new(true, ColorChoice::Never);
1122 start_error(&mut c, s);
1123 Cow::Owned(c)
1124 }
1125 Message::Formatted(c) => Cow::Borrowed(c),
1126 }
1127 }
1128 }
1129
1130 impl From<String> for Message {
from(inner: String) -> Self1131 fn from(inner: String) -> Self {
1132 Self::Raw(inner)
1133 }
1134 }
1135
1136 impl From<Colorizer> for Message {
from(inner: Colorizer) -> Self1137 fn from(inner: Colorizer) -> Self {
1138 Self::Formatted(inner)
1139 }
1140 }
1141
1142 #[cfg(feature = "debug")]
1143 #[derive(Debug)]
1144 struct Backtrace(backtrace::Backtrace);
1145
1146 #[cfg(feature = "debug")]
1147 impl Backtrace {
new() -> Option<Self>1148 fn new() -> Option<Self> {
1149 Some(Self(backtrace::Backtrace::new()))
1150 }
1151 }
1152
1153 #[cfg(feature = "debug")]
1154 impl Display for Backtrace {
fmt(&self, f: &mut Formatter) -> fmt::Result1155 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1156 // `backtrace::Backtrace` uses `Debug` instead of `Display`
1157 write!(f, "{:?}", self.0)
1158 }
1159 }
1160
1161 #[cfg(not(feature = "debug"))]
1162 #[derive(Debug)]
1163 struct Backtrace;
1164
1165 #[cfg(not(feature = "debug"))]
1166 impl Backtrace {
new() -> Option<Self>1167 fn new() -> Option<Self> {
1168 None
1169 }
1170 }
1171
1172 #[cfg(not(feature = "debug"))]
1173 impl Display for Backtrace {
fmt(&self, _: &mut Formatter) -> fmt::Result1174 fn fmt(&self, _: &mut Formatter) -> fmt::Result {
1175 Ok(())
1176 }
1177 }
1178
1179 #[cfg(test)]
1180 mod tests {
1181 /// Check `clap::Error` impls Send and Sync.
1182 mod clap_error_impl_send_sync {
1183 use crate::Error;
1184 trait Foo: std::error::Error + Send + Sync + 'static {}
1185 impl Foo for Error {}
1186 }
1187 }
1188