1 // Std
2 use std::convert::From;
3 use std::error::Error as StdError;
4 use std::fmt as std_fmt;
5 use std::fmt::Display;
6 use std::io::{self, Write};
7 use std::process;
8 use std::result::Result as StdResult;
9 
10 // Internal
11 use args::{AnyArg, FlagBuilder};
12 use fmt::{ColorWhen, Colorizer, ColorizerOption};
13 use suggestions;
14 
15 /// Short hand for [`Result`] type
16 /// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html
17 pub type Result<T> = StdResult<T, Error>;
18 
19 /// Command line argument parser kind of error
20 #[derive(Debug, Copy, Clone, PartialEq)]
21 pub enum ErrorKind {
22     /// Occurs when an [`Arg`] has a set of possible values,
23     /// and the user provides a value which isn't in that set.
24     ///
25     /// # Examples
26     ///
27     /// ```rust
28     /// # use clap::{App, Arg, ErrorKind};
29     /// let result = App::new("prog")
30     ///     .arg(Arg::with_name("speed")
31     ///         .possible_value("fast")
32     ///         .possible_value("slow"))
33     ///     .get_matches_from_safe(vec!["prog", "other"]);
34     /// assert!(result.is_err());
35     /// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidValue);
36     /// ```
37     /// [`Arg`]: ./struct.Arg.html
38     InvalidValue,
39 
40     /// Occurs when a user provides a flag, option, argument or subcommand which isn't defined.
41     ///
42     /// # Examples
43     ///
44     /// ```rust
45     /// # use clap::{App, Arg, ErrorKind};
46     /// let result = App::new("prog")
47     ///     .arg(Arg::from_usage("--flag 'some flag'"))
48     ///     .get_matches_from_safe(vec!["prog", "--other"]);
49     /// assert!(result.is_err());
50     /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnknownArgument);
51     /// ```
52     UnknownArgument,
53 
54     /// Occurs when the user provides an unrecognized [`SubCommand`] which meets the threshold for
55     /// being similar enough to an existing subcommand.
56     /// If it doesn't meet the threshold, or the 'suggestions' feature is disabled,
57     /// the more general [`UnknownArgument`] error is returned.
58     ///
59     /// # Examples
60     ///
61     #[cfg_attr(not(feature = "suggestions"), doc = " ```no_run")]
62     #[cfg_attr(feature = "suggestions", doc = " ```")]
63     /// # use clap::{App, Arg, ErrorKind, SubCommand};
64     /// let result = App::new("prog")
65     ///     .subcommand(SubCommand::with_name("config")
66     ///         .about("Used for configuration")
67     ///         .arg(Arg::with_name("config_file")
68     ///             .help("The configuration file to use")
69     ///             .index(1)))
70     ///     .get_matches_from_safe(vec!["prog", "confi"]);
71     /// assert!(result.is_err());
72     /// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidSubcommand);
73     /// ```
74     /// [`SubCommand`]: ./struct.SubCommand.html
75     /// [`UnknownArgument`]: ./enum.ErrorKind.html#variant.UnknownArgument
76     InvalidSubcommand,
77 
78     /// Occurs when the user provides an unrecognized [`SubCommand`] which either
79     /// doesn't meet the threshold for being similar enough to an existing subcommand,
80     /// or the 'sggestions' feature is disabled.
81     /// Otherwise the more detailed [`InvalidSubcommand`] error is returned.
82     ///
83     /// This error typically happens when passing additional subcommand names to the `help`
84     /// subcommand. Otherwise, the more general [`UnknownArgument`] error is used.
85     ///
86     /// # Examples
87     ///
88     /// ```rust
89     /// # use clap::{App, Arg, ErrorKind, SubCommand};
90     /// let result = App::new("prog")
91     ///     .subcommand(SubCommand::with_name("config")
92     ///         .about("Used for configuration")
93     ///         .arg(Arg::with_name("config_file")
94     ///             .help("The configuration file to use")
95     ///             .index(1)))
96     ///     .get_matches_from_safe(vec!["prog", "help", "nothing"]);
97     /// assert!(result.is_err());
98     /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnrecognizedSubcommand);
99     /// ```
100     /// [`SubCommand`]: ./struct.SubCommand.html
101     /// [`InvalidSubcommand`]: ./enum.ErrorKind.html#variant.InvalidSubcommand
102     /// [`UnknownArgument`]: ./enum.ErrorKind.html#variant.UnknownArgument
103     UnrecognizedSubcommand,
104 
105     /// Occurs when the user provides an empty value for an option that does not allow empty
106     /// values.
107     ///
108     /// # Examples
109     ///
110     /// ```rust
111     /// # use clap::{App, Arg, ErrorKind};
112     /// let res = App::new("prog")
113     ///     .arg(Arg::with_name("color")
114     ///          .long("color")
115     ///          .empty_values(false))
116     ///     .get_matches_from_safe(vec!["prog", "--color="]);
117     /// assert!(res.is_err());
118     /// assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue);
119     /// ```
120     EmptyValue,
121 
122     /// Occurs when the user provides a value for an argument with a custom validation and the
123     /// value fails that validation.
124     ///
125     /// # Examples
126     ///
127     /// ```rust
128     /// # use clap::{App, Arg, ErrorKind};
129     /// fn is_numeric(val: String) -> Result<(), String> {
130     ///     match val.parse::<i64>() {
131     ///         Ok(..) => Ok(()),
132     ///         Err(..) => Err(String::from("Value wasn't a number!")),
133     ///     }
134     /// }
135     ///
136     /// let result = App::new("prog")
137     ///     .arg(Arg::with_name("num")
138     ///          .validator(is_numeric))
139     ///     .get_matches_from_safe(vec!["prog", "NotANumber"]);
140     /// assert!(result.is_err());
141     /// assert_eq!(result.unwrap_err().kind, ErrorKind::ValueValidation);
142     /// ```
143     ValueValidation,
144 
145     /// Occurs when a user provides more values for an argument than were defined by setting
146     /// [`Arg::max_values`].
147     ///
148     /// # Examples
149     ///
150     /// ```rust
151     /// # use clap::{App, Arg, ErrorKind};
152     /// let result = App::new("prog")
153     ///     .arg(Arg::with_name("arg")
154     ///         .multiple(true)
155     ///         .max_values(2))
156     ///     .get_matches_from_safe(vec!["prog", "too", "many", "values"]);
157     /// assert!(result.is_err());
158     /// assert_eq!(result.unwrap_err().kind, ErrorKind::TooManyValues);
159     /// ```
160     /// [`Arg::max_values`]: ./struct.Arg.html#method.max_values
161     TooManyValues,
162 
163     /// Occurs when the user provides fewer values for an argument than were defined by setting
164     /// [`Arg::min_values`].
165     ///
166     /// # Examples
167     ///
168     /// ```rust
169     /// # use clap::{App, Arg, ErrorKind};
170     /// let result = App::new("prog")
171     ///     .arg(Arg::with_name("some_opt")
172     ///         .long("opt")
173     ///         .min_values(3))
174     ///     .get_matches_from_safe(vec!["prog", "--opt", "too", "few"]);
175     /// assert!(result.is_err());
176     /// assert_eq!(result.unwrap_err().kind, ErrorKind::TooFewValues);
177     /// ```
178     /// [`Arg::min_values`]: ./struct.Arg.html#method.min_values
179     TooFewValues,
180 
181     /// Occurs when the user provides a different number of values for an argument than what's
182     /// been defined by setting [`Arg::number_of_values`] or than was implicitly set by
183     /// [`Arg::value_names`].
184     ///
185     /// # Examples
186     ///
187     /// ```rust
188     /// # use clap::{App, Arg, ErrorKind};
189     /// let result = App::new("prog")
190     ///     .arg(Arg::with_name("some_opt")
191     ///         .long("opt")
192     ///         .takes_value(true)
193     ///         .number_of_values(2))
194     ///     .get_matches_from_safe(vec!["prog", "--opt", "wrong"]);
195     /// assert!(result.is_err());
196     /// assert_eq!(result.unwrap_err().kind, ErrorKind::WrongNumberOfValues);
197     /// ```
198     /// [`Arg::number_of_values`]
199     /// [`Arg::number_of_values`]: ./struct.Arg.html#method.number_of_values
200     /// [`Arg::value_names`]: ./struct.Arg.html#method.value_names
201     WrongNumberOfValues,
202 
203     /// Occurs when the user provides two values which conflict with each other and can't be used
204     /// together.
205     ///
206     /// # Examples
207     ///
208     /// ```rust
209     /// # use clap::{App, Arg, ErrorKind};
210     /// let result = App::new("prog")
211     ///     .arg(Arg::with_name("debug")
212     ///         .long("debug")
213     ///         .conflicts_with("color"))
214     ///     .arg(Arg::with_name("color")
215     ///         .long("color"))
216     ///     .get_matches_from_safe(vec!["prog", "--debug", "--color"]);
217     /// assert!(result.is_err());
218     /// assert_eq!(result.unwrap_err().kind, ErrorKind::ArgumentConflict);
219     /// ```
220     ArgumentConflict,
221 
222     /// Occurs when the user does not provide one or more required arguments.
223     ///
224     /// # Examples
225     ///
226     /// ```rust
227     /// # use clap::{App, Arg, ErrorKind};
228     /// let result = App::new("prog")
229     ///     .arg(Arg::with_name("debug")
230     ///         .required(true))
231     ///     .get_matches_from_safe(vec!["prog"]);
232     /// assert!(result.is_err());
233     /// assert_eq!(result.unwrap_err().kind, ErrorKind::MissingRequiredArgument);
234     /// ```
235     MissingRequiredArgument,
236 
237     /// Occurs when a subcommand is required (as defined by [`AppSettings::SubcommandRequired`]),
238     /// but the user does not provide one.
239     ///
240     /// # Examples
241     ///
242     /// ```rust
243     /// # use clap::{App, AppSettings, SubCommand, ErrorKind};
244     /// let err = App::new("prog")
245     ///     .setting(AppSettings::SubcommandRequired)
246     ///     .subcommand(SubCommand::with_name("test"))
247     ///     .get_matches_from_safe(vec![
248     ///         "myprog",
249     ///     ]);
250     /// assert!(err.is_err());
251     /// assert_eq!(err.unwrap_err().kind, ErrorKind::MissingSubcommand);
252     /// # ;
253     /// ```
254     /// [`AppSettings::SubcommandRequired`]: ./enum.AppSettings.html#variant.SubcommandRequired
255     MissingSubcommand,
256 
257     /// Occurs when either an argument or [`SubCommand`] is required, as defined by
258     /// [`AppSettings::ArgRequiredElseHelp`], but the user did not provide one.
259     ///
260     /// # Examples
261     ///
262     /// ```rust
263     /// # use clap::{App, Arg, AppSettings, ErrorKind, SubCommand};
264     /// let result = App::new("prog")
265     ///     .setting(AppSettings::ArgRequiredElseHelp)
266     ///     .subcommand(SubCommand::with_name("config")
267     ///         .about("Used for configuration")
268     ///         .arg(Arg::with_name("config_file")
269     ///             .help("The configuration file to use")))
270     ///     .get_matches_from_safe(vec!["prog"]);
271     /// assert!(result.is_err());
272     /// assert_eq!(result.unwrap_err().kind, ErrorKind::MissingArgumentOrSubcommand);
273     /// ```
274     /// [`SubCommand`]: ./struct.SubCommand.html
275     /// [`AppSettings::ArgRequiredElseHelp`]: ./enum.AppSettings.html#variant.ArgRequiredElseHelp
276     MissingArgumentOrSubcommand,
277 
278     /// Occurs when the user provides multiple values to an argument which doesn't allow that.
279     ///
280     /// # Examples
281     ///
282     /// ```rust
283     /// # use clap::{App, Arg, ErrorKind};
284     /// let result = App::new("prog")
285     ///     .arg(Arg::with_name("debug")
286     ///         .long("debug")
287     ///         .multiple(false))
288     ///     .get_matches_from_safe(vec!["prog", "--debug", "--debug"]);
289     /// assert!(result.is_err());
290     /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnexpectedMultipleUsage);
291     /// ```
292     UnexpectedMultipleUsage,
293 
294     /// Occurs when the user provides a value containing invalid UTF-8 for an argument and
295     /// [`AppSettings::StrictUtf8`] is set.
296     ///
297     /// # Platform Speicific
298     ///
299     /// Non-Windows platforms only (such as Linux, Unix, OSX, etc.)
300     ///
301     /// # Examples
302     ///
303     #[cfg_attr(not(unix), doc = " ```ignore")]
304     #[cfg_attr(unix, doc = " ```")]
305     /// # use clap::{App, Arg, ErrorKind, AppSettings};
306     /// # use std::os::unix::ffi::OsStringExt;
307     /// # use std::ffi::OsString;
308     /// let result = App::new("prog")
309     ///     .setting(AppSettings::StrictUtf8)
310     ///     .arg(Arg::with_name("utf8")
311     ///         .short("u")
312     ///         .takes_value(true))
313     ///     .get_matches_from_safe(vec![OsString::from("myprog"),
314     ///                                 OsString::from("-u"),
315     ///                                 OsString::from_vec(vec![0xE9])]);
316     /// assert!(result.is_err());
317     /// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidUtf8);
318     /// ```
319     /// [`AppSettings::StrictUtf8`]: ./enum.AppSettings.html#variant.StrictUtf8
320     InvalidUtf8,
321 
322     /// Not a true "error" as it means `--help` or similar was used.
323     /// The help message will be sent to `stdout`.
324     ///
325     /// **Note**: If the help is displayed due to an error (such as missing subcommands) it will
326     /// be sent to `stderr` instead of `stdout`.
327     ///
328     /// # Examples
329     ///
330     /// ```rust
331     /// # use clap::{App, Arg, ErrorKind};
332     /// let result = App::new("prog")
333     ///     .get_matches_from_safe(vec!["prog", "--help"]);
334     /// assert!(result.is_err());
335     /// assert_eq!(result.unwrap_err().kind, ErrorKind::HelpDisplayed);
336     /// ```
337     HelpDisplayed,
338 
339     /// Not a true "error" as it means `--version` or similar was used.
340     /// The message will be sent to `stdout`.
341     ///
342     /// # Examples
343     ///
344     /// ```rust
345     /// # use clap::{App, Arg, ErrorKind};
346     /// let result = App::new("prog")
347     ///     .get_matches_from_safe(vec!["prog", "--version"]);
348     /// assert!(result.is_err());
349     /// assert_eq!(result.unwrap_err().kind, ErrorKind::VersionDisplayed);
350     /// ```
351     VersionDisplayed,
352 
353     /// Occurs when using the [`value_t!`] and [`values_t!`] macros to convert an argument value
354     /// into type `T`, but the argument you requested wasn't used. I.e. you asked for an argument
355     /// with name `config` to be converted, but `config` wasn't used by the user.
356     /// [`value_t!`]: ./macro.value_t!.html
357     /// [`values_t!`]: ./macro.values_t!.html
358     ArgumentNotFound,
359 
360     /// Represents an [I/O error].
361     /// Can occur when writing to `stderr` or `stdout` or reading a configuration file.
362     /// [I/O error]: https://doc.rust-lang.org/std/io/struct.Error.html
363     Io,
364 
365     /// Represents a [Format error] (which is a part of [`Display`]).
366     /// Typically caused by writing to `stderr` or `stdout`.
367     /// [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
368     /// [Format error]: https://doc.rust-lang.org/std/fmt/struct.Error.html
369     Format,
370 }
371 
372 /// Command Line Argument Parser Error
373 #[derive(Debug)]
374 pub struct Error {
375     /// Formated error message
376     pub message: String,
377     /// The type of error
378     pub kind: ErrorKind,
379     /// Any additional information passed along, such as the argument name that caused the error
380     pub info: Option<Vec<String>>,
381 }
382 
383 impl Error {
384     /// Should the message be written to `stdout` or not
use_stderr(&self) -> bool385     pub fn use_stderr(&self) -> bool {
386         match self.kind {
387             ErrorKind::HelpDisplayed | ErrorKind::VersionDisplayed => false,
388             _ => true,
389         }
390     }
391 
392     /// Prints the error to `stderr` and exits with a status of `1`
exit(&self) -> !393     pub fn exit(&self) -> ! {
394         if self.use_stderr() {
395             wlnerr!("{}", self.message);
396             process::exit(1);
397         }
398         let out = io::stdout();
399         writeln!(&mut out.lock(), "{}", self.message).expect("Error writing Error to stdout");
400         process::exit(0);
401     }
402 
403     #[doc(hidden)]
write_to<W: Write>(&self, w: &mut W) -> io::Result<()>404     pub fn write_to<W: Write>(&self, w: &mut W) -> io::Result<()> { write!(w, "{}", self.message) }
405 
406     #[doc(hidden)]
argument_conflict<'a, 'b, A, O, U>( arg: &A, other: Option<O>, usage: U, color: ColorWhen, ) -> Self where A: AnyArg<'a, 'b> + Display, O: Into<String>, U: Display,407     pub fn argument_conflict<'a, 'b, A, O, U>(
408         arg: &A,
409         other: Option<O>,
410         usage: U,
411         color: ColorWhen,
412     ) -> Self
413     where
414         A: AnyArg<'a, 'b> + Display,
415         O: Into<String>,
416         U: Display,
417     {
418         let mut v = vec![arg.name().to_owned()];
419         let c = Colorizer::new(ColorizerOption {
420             use_stderr: true,
421             when: color,
422         });
423         Error {
424             message: format!(
425                 "{} The argument '{}' cannot be used with {}\n\n\
426                  {}\n\n\
427                  For more information try {}",
428                 c.error("error:"),
429                 c.warning(&*arg.to_string()),
430                 match other {
431                     Some(name) => {
432                         let n = name.into();
433                         v.push(n.clone());
434                         c.warning(format!("'{}'", n))
435                     }
436                     None => c.none("one or more of the other specified arguments".to_owned()),
437                 },
438                 usage,
439                 c.good("--help")
440             ),
441             kind: ErrorKind::ArgumentConflict,
442             info: Some(v),
443         }
444     }
445 
446     #[doc(hidden)]
empty_value<'a, 'b, A, U>(arg: &A, usage: U, color: ColorWhen) -> Self where A: AnyArg<'a, 'b> + Display, U: Display,447     pub fn empty_value<'a, 'b, A, U>(arg: &A, usage: U, color: ColorWhen) -> Self
448     where
449         A: AnyArg<'a, 'b> + Display,
450         U: Display,
451     {
452         let c = Colorizer::new(ColorizerOption {
453             use_stderr: true,
454             when: color,
455         });
456         Error {
457             message: format!(
458                 "{} The argument '{}' requires a value but none was supplied\
459                  \n\n\
460                  {}\n\n\
461                  For more information try {}",
462                 c.error("error:"),
463                 c.warning(arg.to_string()),
464                 usage,
465                 c.good("--help")
466             ),
467             kind: ErrorKind::EmptyValue,
468             info: Some(vec![arg.name().to_owned()]),
469         }
470     }
471 
472     #[doc(hidden)]
invalid_value<'a, 'b, B, G, A, U>( bad_val: B, good_vals: &[G], arg: &A, usage: U, color: ColorWhen, ) -> Self where B: AsRef<str>, G: AsRef<str> + Display, A: AnyArg<'a, 'b> + Display, U: Display,473     pub fn invalid_value<'a, 'b, B, G, A, U>(
474         bad_val: B,
475         good_vals: &[G],
476         arg: &A,
477         usage: U,
478         color: ColorWhen,
479     ) -> Self
480     where
481         B: AsRef<str>,
482         G: AsRef<str> + Display,
483         A: AnyArg<'a, 'b> + Display,
484         U: Display,
485     {
486         let c = Colorizer::new(ColorizerOption {
487             use_stderr: true,
488             when: color,
489         });
490         let suffix = suggestions::did_you_mean_value_suffix(bad_val.as_ref(), good_vals.iter());
491 
492         let mut sorted = vec![];
493         for v in good_vals {
494             let val = format!("{}", c.good(v));
495             sorted.push(val);
496         }
497         sorted.sort();
498         let valid_values = sorted.join(", ");
499         Error {
500             message: format!(
501                 "{} '{}' isn't a valid value for '{}'\n\t\
502                  [values: {}]\n\
503                  {}\n\n\
504                  {}\n\n\
505                  For more information try {}",
506                 c.error("error:"),
507                 c.warning(bad_val.as_ref()),
508                 c.warning(arg.to_string()),
509                 valid_values,
510                 suffix.0,
511                 usage,
512                 c.good("--help")
513             ),
514             kind: ErrorKind::InvalidValue,
515             info: Some(vec![arg.name().to_owned(), bad_val.as_ref().to_owned()]),
516         }
517     }
518 
519     #[doc(hidden)]
invalid_subcommand<S, D, N, U>( subcmd: S, did_you_mean: D, name: N, usage: U, color: ColorWhen, ) -> Self where S: Into<String>, D: AsRef<str> + Display, N: Display, U: Display,520     pub fn invalid_subcommand<S, D, N, U>(
521         subcmd: S,
522         did_you_mean: D,
523         name: N,
524         usage: U,
525         color: ColorWhen,
526     ) -> Self
527     where
528         S: Into<String>,
529         D: AsRef<str> + Display,
530         N: Display,
531         U: Display,
532     {
533         let s = subcmd.into();
534         let c = Colorizer::new(ColorizerOption {
535             use_stderr: true,
536             when: color,
537         });
538         Error {
539             message: format!(
540                 "{} The subcommand '{}' wasn't recognized\n\t\
541                  Did you mean '{}'?\n\n\
542                  If you believe you received this message in error, try \
543                  re-running with '{} {} {}'\n\n\
544                  {}\n\n\
545                  For more information try {}",
546                 c.error("error:"),
547                 c.warning(&*s),
548                 c.good(did_you_mean.as_ref()),
549                 name,
550                 c.good("--"),
551                 &*s,
552                 usage,
553                 c.good("--help")
554             ),
555             kind: ErrorKind::InvalidSubcommand,
556             info: Some(vec![s]),
557         }
558     }
559 
560     #[doc(hidden)]
unrecognized_subcommand<S, N>(subcmd: S, name: N, color: ColorWhen) -> Self where S: Into<String>, N: Display,561     pub fn unrecognized_subcommand<S, N>(subcmd: S, name: N, color: ColorWhen) -> Self
562     where
563         S: Into<String>,
564         N: Display,
565     {
566         let s = subcmd.into();
567         let c = Colorizer::new(ColorizerOption {
568             use_stderr: true,
569             when: color,
570         });
571         Error {
572             message: format!(
573                 "{} The subcommand '{}' wasn't recognized\n\n\
574                  {}\n\t\
575                  {} help <subcommands>...\n\n\
576                  For more information try {}",
577                 c.error("error:"),
578                 c.warning(&*s),
579                 c.warning("USAGE:"),
580                 name,
581                 c.good("--help")
582             ),
583             kind: ErrorKind::UnrecognizedSubcommand,
584             info: Some(vec![s]),
585         }
586     }
587 
588     #[doc(hidden)]
missing_required_argument<R, U>(required: R, usage: U, color: ColorWhen) -> Self where R: Display, U: Display,589     pub fn missing_required_argument<R, U>(required: R, usage: U, color: ColorWhen) -> Self
590     where
591         R: Display,
592         U: Display,
593     {
594         let c = Colorizer::new(ColorizerOption {
595             use_stderr: true,
596             when: color,
597         });
598         Error {
599             message: format!(
600                 "{} The following required arguments were not provided:{}\n\n\
601                  {}\n\n\
602                  For more information try {}",
603                 c.error("error:"),
604                 required,
605                 usage,
606                 c.good("--help")
607             ),
608             kind: ErrorKind::MissingRequiredArgument,
609             info: None,
610         }
611     }
612 
613     #[doc(hidden)]
missing_subcommand<N, U>(name: N, usage: U, color: ColorWhen) -> Self where N: AsRef<str> + Display, U: Display,614     pub fn missing_subcommand<N, U>(name: N, usage: U, color: ColorWhen) -> Self
615     where
616         N: AsRef<str> + Display,
617         U: Display,
618     {
619         let c = Colorizer::new(ColorizerOption {
620             use_stderr: true,
621             when: color,
622         });
623         Error {
624             message: format!(
625                 "{} '{}' requires a subcommand, but one was not provided\n\n\
626                  {}\n\n\
627                  For more information try {}",
628                 c.error("error:"),
629                 c.warning(name),
630                 usage,
631                 c.good("--help")
632             ),
633             kind: ErrorKind::MissingSubcommand,
634             info: None,
635         }
636     }
637 
638 
639     #[doc(hidden)]
invalid_utf8<U>(usage: U, color: ColorWhen) -> Self where U: Display,640     pub fn invalid_utf8<U>(usage: U, color: ColorWhen) -> Self
641     where
642         U: Display,
643     {
644         let c = Colorizer::new(ColorizerOption {
645             use_stderr: true,
646             when: color,
647         });
648         Error {
649             message: format!(
650                 "{} Invalid UTF-8 was detected in one or more arguments\n\n\
651                  {}\n\n\
652                  For more information try {}",
653                 c.error("error:"),
654                 usage,
655                 c.good("--help")
656             ),
657             kind: ErrorKind::InvalidUtf8,
658             info: None,
659         }
660     }
661 
662     #[doc(hidden)]
too_many_values<'a, 'b, V, A, U>(val: V, arg: &A, usage: U, color: ColorWhen) -> Self where V: AsRef<str> + Display + ToOwned, A: AnyArg<'a, 'b> + Display, U: Display,663     pub fn too_many_values<'a, 'b, V, A, U>(val: V, arg: &A, usage: U, color: ColorWhen) -> Self
664     where
665         V: AsRef<str> + Display + ToOwned,
666         A: AnyArg<'a, 'b> + Display,
667         U: Display,
668     {
669         let v = val.as_ref();
670         let c = Colorizer::new(ColorizerOption {
671             use_stderr: true,
672             when: color,
673         });
674         Error {
675             message: format!(
676                 "{} The value '{}' was provided to '{}', but it wasn't expecting \
677                  any more values\n\n\
678                  {}\n\n\
679                  For more information try {}",
680                 c.error("error:"),
681                 c.warning(v),
682                 c.warning(arg.to_string()),
683                 usage,
684                 c.good("--help")
685             ),
686             kind: ErrorKind::TooManyValues,
687             info: Some(vec![arg.name().to_owned(), v.to_owned()]),
688         }
689     }
690 
691     #[doc(hidden)]
too_few_values<'a, 'b, A, U>( arg: &A, min_vals: u64, curr_vals: usize, usage: U, color: ColorWhen, ) -> Self where A: AnyArg<'a, 'b> + Display, U: Display,692     pub fn too_few_values<'a, 'b, A, U>(
693         arg: &A,
694         min_vals: u64,
695         curr_vals: usize,
696         usage: U,
697         color: ColorWhen,
698     ) -> Self
699     where
700         A: AnyArg<'a, 'b> + Display,
701         U: Display,
702     {
703         let c = Colorizer::new(ColorizerOption {
704             use_stderr: true,
705             when: color,
706         });
707         Error {
708             message: format!(
709                 "{} The argument '{}' requires at least {} values, but only {} w{} \
710                  provided\n\n\
711                  {}\n\n\
712                  For more information try {}",
713                 c.error("error:"),
714                 c.warning(arg.to_string()),
715                 c.warning(min_vals.to_string()),
716                 c.warning(curr_vals.to_string()),
717                 if curr_vals > 1 { "ere" } else { "as" },
718                 usage,
719                 c.good("--help")
720             ),
721             kind: ErrorKind::TooFewValues,
722             info: Some(vec![arg.name().to_owned()]),
723         }
724     }
725 
726     #[doc(hidden)]
value_validation<'a, 'b, A>(arg: Option<&A>, err: String, color: ColorWhen) -> Self where A: AnyArg<'a, 'b> + Display,727     pub fn value_validation<'a, 'b, A>(arg: Option<&A>, err: String, color: ColorWhen) -> Self
728     where
729         A: AnyArg<'a, 'b> + Display,
730     {
731         let c = Colorizer::new(ColorizerOption {
732             use_stderr: true,
733             when: color,
734         });
735         Error {
736             message: format!(
737                 "{} Invalid value{}: {}",
738                 c.error("error:"),
739                 if let Some(a) = arg {
740                     format!(" for '{}'", c.warning(a.to_string()))
741                 } else {
742                     "".to_string()
743                 },
744                 err
745             ),
746             kind: ErrorKind::ValueValidation,
747             info: None,
748         }
749     }
750 
751     #[doc(hidden)]
value_validation_auto(err: String) -> Self752     pub fn value_validation_auto(err: String) -> Self {
753         let n: Option<&FlagBuilder> = None;
754         Error::value_validation(n, err, ColorWhen::Auto)
755     }
756 
757     #[doc(hidden)]
wrong_number_of_values<'a, 'b, A, S, U>( arg: &A, num_vals: u64, curr_vals: usize, suffix: S, usage: U, color: ColorWhen, ) -> Self where A: AnyArg<'a, 'b> + Display, S: Display, U: Display,758     pub fn wrong_number_of_values<'a, 'b, A, S, U>(
759         arg: &A,
760         num_vals: u64,
761         curr_vals: usize,
762         suffix: S,
763         usage: U,
764         color: ColorWhen,
765     ) -> Self
766     where
767         A: AnyArg<'a, 'b> + Display,
768         S: Display,
769         U: Display,
770     {
771         let c = Colorizer::new(ColorizerOption {
772             use_stderr: true,
773             when: color,
774         });
775         Error {
776             message: format!(
777                 "{} The argument '{}' requires {} values, but {} w{} \
778                  provided\n\n\
779                  {}\n\n\
780                  For more information try {}",
781                 c.error("error:"),
782                 c.warning(arg.to_string()),
783                 c.warning(num_vals.to_string()),
784                 c.warning(curr_vals.to_string()),
785                 suffix,
786                 usage,
787                 c.good("--help")
788             ),
789             kind: ErrorKind::WrongNumberOfValues,
790             info: Some(vec![arg.name().to_owned()]),
791         }
792     }
793 
794     #[doc(hidden)]
unexpected_multiple_usage<'a, 'b, A, U>(arg: &A, usage: U, color: ColorWhen) -> Self where A: AnyArg<'a, 'b> + Display, U: Display,795     pub fn unexpected_multiple_usage<'a, 'b, A, U>(arg: &A, usage: U, color: ColorWhen) -> Self
796     where
797         A: AnyArg<'a, 'b> + Display,
798         U: Display,
799     {
800         let c = Colorizer::new(ColorizerOption {
801             use_stderr: true,
802             when: color,
803         });
804         Error {
805             message: format!(
806                 "{} The argument '{}' was provided more than once, but cannot \
807                  be used multiple times\n\n\
808                  {}\n\n\
809                  For more information try {}",
810                 c.error("error:"),
811                 c.warning(arg.to_string()),
812                 usage,
813                 c.good("--help")
814             ),
815             kind: ErrorKind::UnexpectedMultipleUsage,
816             info: Some(vec![arg.name().to_owned()]),
817         }
818     }
819 
820     #[doc(hidden)]
unknown_argument<A, U>(arg: A, did_you_mean: &str, usage: U, color: ColorWhen) -> Self where A: Into<String>, U: Display,821     pub fn unknown_argument<A, U>(arg: A, did_you_mean: &str, usage: U, color: ColorWhen) -> Self
822     where
823         A: Into<String>,
824         U: Display,
825     {
826         let a = arg.into();
827         let c = Colorizer::new(ColorizerOption {
828             use_stderr: true,
829             when: color,
830         });
831         Error {
832             message: format!(
833                 "{} Found argument '{}' which wasn't expected, or isn't valid in \
834                  this context{}\n\
835                  {}\n\n\
836                  For more information try {}",
837                 c.error("error:"),
838                 c.warning(&*a),
839                 if did_you_mean.is_empty() {
840                     "\n".to_owned()
841                 } else {
842                     format!("{}\n", did_you_mean)
843                 },
844                 usage,
845                 c.good("--help")
846             ),
847             kind: ErrorKind::UnknownArgument,
848             info: Some(vec![a]),
849         }
850     }
851 
852     #[doc(hidden)]
io_error(e: &Error, color: ColorWhen) -> Self853     pub fn io_error(e: &Error, color: ColorWhen) -> Self {
854         let c = Colorizer::new(ColorizerOption {
855             use_stderr: true,
856             when: color,
857         });
858         Error {
859             message: format!("{} {}", c.error("error:"), e.description()),
860             kind: ErrorKind::Io,
861             info: None,
862         }
863     }
864 
865     #[doc(hidden)]
argument_not_found_auto<A>(arg: A) -> Self where A: Into<String>,866     pub fn argument_not_found_auto<A>(arg: A) -> Self
867     where
868         A: Into<String>,
869     {
870         let a = arg.into();
871         let c = Colorizer::new(ColorizerOption {
872             use_stderr: true,
873             when: ColorWhen::Auto,
874         });
875         Error {
876             message: format!(
877                 "{} The argument '{}' wasn't found",
878                 c.error("error:"),
879                 a.clone()
880             ),
881             kind: ErrorKind::ArgumentNotFound,
882             info: Some(vec![a]),
883         }
884     }
885 
886     /// Create an error with a custom description.
887     ///
888     /// This can be used in combination with `Error::exit` to exit your program
889     /// with a custom error message.
with_description(description: &str, kind: ErrorKind) -> Self890     pub fn with_description(description: &str, kind: ErrorKind) -> Self {
891         let c = Colorizer::new(ColorizerOption {
892             use_stderr: true,
893             when: ColorWhen::Auto,
894         });
895         Error {
896             message: format!("{} {}", c.error("error:"), description),
897             kind: kind,
898             info: None,
899         }
900     }
901 }
902 
903 impl StdError for Error {
description(&self) -> &str904     fn description(&self) -> &str { &*self.message }
905 }
906 
907 impl Display for Error {
fmt(&self, f: &mut std_fmt::Formatter) -> std_fmt::Result908     fn fmt(&self, f: &mut std_fmt::Formatter) -> std_fmt::Result { writeln!(f, "{}", self.message) }
909 }
910 
911 impl From<io::Error> for Error {
from(e: io::Error) -> Self912     fn from(e: io::Error) -> Self { Error::with_description(e.description(), ErrorKind::Io) }
913 }
914 
915 impl From<std_fmt::Error> for Error {
from(e: std_fmt::Error) -> Self916     fn from(e: std_fmt::Error) -> Self {
917         Error::with_description(e.description(), ErrorKind::Format)
918     }
919 }
920