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