| // Std |
| use std::convert::From; |
| use std::error::Error as StdError; |
| use std::fmt as std_fmt; |
| use std::fmt::Display; |
| use std::io::{self, Write}; |
| use std::process; |
| use std::result::Result as StdResult; |
| |
| // Internal |
| use args::AnyArg; |
| use fmt::{ColorWhen, Colorizer, ColorizerOption}; |
| use suggestions; |
| |
| /// Short hand for [`Result`] type |
| /// |
| /// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html |
| pub type Result<T> = StdResult<T, Error>; |
| |
| /// Command line argument parser kind of error |
| #[derive(Debug, Copy, Clone, PartialEq)] |
| pub enum ErrorKind { |
| /// Occurs when an [`Arg`] has a set of possible values, |
| /// and the user provides a value which isn't in that set. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind}; |
| /// let result = App::new("prog") |
| /// .arg(Arg::with_name("speed") |
| /// .possible_value("fast") |
| /// .possible_value("slow")) |
| /// .get_matches_from_safe(vec!["prog", "other"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidValue); |
| /// ``` |
| /// [`Arg`]: ./struct.Arg.html |
| InvalidValue, |
| |
| /// Occurs when a user provides a flag, option, argument or subcommand which isn't defined. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind}; |
| /// let result = App::new("prog") |
| /// .arg(Arg::from_usage("--flag 'some flag'")) |
| /// .get_matches_from_safe(vec!["prog", "--other"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnknownArgument); |
| /// ``` |
| UnknownArgument, |
| |
| /// Occurs when the user provides an unrecognized [`SubCommand`] which meets the threshold for |
| /// being similar enough to an existing subcommand. |
| /// If it doesn't meet the threshold, or the 'suggestions' feature is disabled, |
| /// the more general [`UnknownArgument`] error is returned. |
| /// |
| /// # Examples |
| /// |
| #[cfg_attr(not(feature = "suggestions"), doc = " ```no_run")] |
| #[cfg_attr(feature = "suggestions", doc = " ```")] |
| /// # use clap::{App, Arg, ErrorKind, SubCommand}; |
| /// let result = App::new("prog") |
| /// .subcommand(SubCommand::with_name("config") |
| /// .about("Used for configuration") |
| /// .arg(Arg::with_name("config_file") |
| /// .help("The configuration file to use") |
| /// .index(1))) |
| /// .get_matches_from_safe(vec!["prog", "confi"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidSubcommand); |
| /// ``` |
| /// [`SubCommand`]: ./struct.SubCommand.html |
| /// [`UnknownArgument`]: ./enum.ErrorKind.html#variant.UnknownArgument |
| InvalidSubcommand, |
| |
| /// Occurs when the user provides an unrecognized [`SubCommand`] which either |
| /// doesn't meet the threshold for being similar enough to an existing subcommand, |
| /// or the 'suggestions' feature is disabled. |
| /// Otherwise the more detailed [`InvalidSubcommand`] error is returned. |
| /// |
| /// This error typically happens when passing additional subcommand names to the `help` |
| /// subcommand. Otherwise, the more general [`UnknownArgument`] error is used. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind, SubCommand}; |
| /// let result = App::new("prog") |
| /// .subcommand(SubCommand::with_name("config") |
| /// .about("Used for configuration") |
| /// .arg(Arg::with_name("config_file") |
| /// .help("The configuration file to use") |
| /// .index(1))) |
| /// .get_matches_from_safe(vec!["prog", "help", "nothing"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnrecognizedSubcommand); |
| /// ``` |
| /// [`SubCommand`]: ./struct.SubCommand.html |
| /// [`InvalidSubcommand`]: ./enum.ErrorKind.html#variant.InvalidSubcommand |
| /// [`UnknownArgument`]: ./enum.ErrorKind.html#variant.UnknownArgument |
| UnrecognizedSubcommand, |
| |
| /// Occurs when the user provides an empty value for an option that does not allow empty |
| /// values. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind}; |
| /// let res = App::new("prog") |
| /// .arg(Arg::with_name("color") |
| /// .long("color") |
| /// .empty_values(false)) |
| /// .get_matches_from_safe(vec!["prog", "--color="]); |
| /// assert!(res.is_err()); |
| /// assert_eq!(res.unwrap_err().kind, ErrorKind::EmptyValue); |
| /// ``` |
| EmptyValue, |
| |
| /// Occurs when the user provides a value for an argument with a custom validation and the |
| /// value fails that validation. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind}; |
| /// fn is_numeric(val: String) -> Result<(), String> { |
| /// match val.parse::<i64>() { |
| /// Ok(..) => Ok(()), |
| /// Err(..) => Err(String::from("Value wasn't a number!")), |
| /// } |
| /// } |
| /// |
| /// let result = App::new("prog") |
| /// .arg(Arg::with_name("num") |
| /// .validator(is_numeric)) |
| /// .get_matches_from_safe(vec!["prog", "NotANumber"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::ValueValidation); |
| /// ``` |
| ValueValidation, |
| |
| /// Occurs when a user provides more values for an argument than were defined by setting |
| /// [`Arg::max_values`]. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind}; |
| /// let result = App::new("prog") |
| /// .arg(Arg::with_name("arg") |
| /// .multiple(true) |
| /// .max_values(2)) |
| /// .get_matches_from_safe(vec!["prog", "too", "many", "values"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::TooManyValues); |
| /// ``` |
| /// [`Arg::max_values`]: ./struct.Arg.html#method.max_values |
| TooManyValues, |
| |
| /// Occurs when the user provides fewer values for an argument than were defined by setting |
| /// [`Arg::min_values`]. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind}; |
| /// let result = App::new("prog") |
| /// .arg(Arg::with_name("some_opt") |
| /// .long("opt") |
| /// .min_values(3)) |
| /// .get_matches_from_safe(vec!["prog", "--opt", "too", "few"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::TooFewValues); |
| /// ``` |
| /// [`Arg::min_values`]: ./struct.Arg.html#method.min_values |
| TooFewValues, |
| |
| /// Occurs when the user provides a different number of values for an argument than what's |
| /// been defined by setting [`Arg::number_of_values`] or than was implicitly set by |
| /// [`Arg::value_names`]. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind}; |
| /// let result = App::new("prog") |
| /// .arg(Arg::with_name("some_opt") |
| /// .long("opt") |
| /// .takes_value(true) |
| /// .number_of_values(2)) |
| /// .get_matches_from_safe(vec!["prog", "--opt", "wrong"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::WrongNumberOfValues); |
| /// ``` |
| /// |
| /// [`Arg::number_of_values`]: ./struct.Arg.html#method.number_of_values |
| /// [`Arg::value_names`]: ./struct.Arg.html#method.value_names |
| WrongNumberOfValues, |
| |
| /// Occurs when the user provides two values which conflict with each other and can't be used |
| /// together. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind}; |
| /// let result = App::new("prog") |
| /// .arg(Arg::with_name("debug") |
| /// .long("debug") |
| /// .conflicts_with("color")) |
| /// .arg(Arg::with_name("color") |
| /// .long("color")) |
| /// .get_matches_from_safe(vec!["prog", "--debug", "--color"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::ArgumentConflict); |
| /// ``` |
| ArgumentConflict, |
| |
| /// Occurs when the user does not provide one or more required arguments. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind}; |
| /// let result = App::new("prog") |
| /// .arg(Arg::with_name("debug") |
| /// .required(true)) |
| /// .get_matches_from_safe(vec!["prog"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::MissingRequiredArgument); |
| /// ``` |
| MissingRequiredArgument, |
| |
| /// Occurs when a subcommand is required (as defined by [`AppSettings::SubcommandRequired`]), |
| /// but the user does not provide one. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, AppSettings, SubCommand, ErrorKind}; |
| /// let err = App::new("prog") |
| /// .setting(AppSettings::SubcommandRequired) |
| /// .subcommand(SubCommand::with_name("test")) |
| /// .get_matches_from_safe(vec![ |
| /// "myprog", |
| /// ]); |
| /// assert!(err.is_err()); |
| /// assert_eq!(err.unwrap_err().kind, ErrorKind::MissingSubcommand); |
| /// # ; |
| /// ``` |
| /// [`AppSettings::SubcommandRequired`]: ./enum.AppSettings.html#variant.SubcommandRequired |
| MissingSubcommand, |
| |
| /// Occurs when either an argument or [`SubCommand`] is required, as defined by |
| /// [`AppSettings::ArgRequiredElseHelp`], but the user did not provide one. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, AppSettings, ErrorKind, SubCommand}; |
| /// let result = App::new("prog") |
| /// .setting(AppSettings::ArgRequiredElseHelp) |
| /// .subcommand(SubCommand::with_name("config") |
| /// .about("Used for configuration") |
| /// .arg(Arg::with_name("config_file") |
| /// .help("The configuration file to use"))) |
| /// .get_matches_from_safe(vec!["prog"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::MissingArgumentOrSubcommand); |
| /// ``` |
| /// [`SubCommand`]: ./struct.SubCommand.html |
| /// [`AppSettings::ArgRequiredElseHelp`]: ./enum.AppSettings.html#variant.ArgRequiredElseHelp |
| MissingArgumentOrSubcommand, |
| |
| /// Occurs when the user provides multiple values to an argument which doesn't allow that. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind}; |
| /// let result = App::new("prog") |
| /// .arg(Arg::with_name("debug") |
| /// .long("debug") |
| /// .multiple(false)) |
| /// .get_matches_from_safe(vec!["prog", "--debug", "--debug"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::UnexpectedMultipleUsage); |
| /// ``` |
| UnexpectedMultipleUsage, |
| |
| /// Occurs when the user provides a value containing invalid UTF-8 for an argument and |
| /// [`AppSettings::StrictUtf8`] is set. |
| /// |
| /// # Platform Specific |
| /// |
| /// Non-Windows platforms only (such as Linux, Unix, macOS, etc.) |
| /// |
| /// # Examples |
| /// |
| #[cfg_attr(not(unix), doc = " ```ignore")] |
| #[cfg_attr(unix, doc = " ```")] |
| /// # use clap::{App, Arg, ErrorKind, AppSettings}; |
| /// # use std::os::unix::ffi::OsStringExt; |
| /// # use std::ffi::OsString; |
| /// let result = App::new("prog") |
| /// .setting(AppSettings::StrictUtf8) |
| /// .arg(Arg::with_name("utf8") |
| /// .short("u") |
| /// .takes_value(true)) |
| /// .get_matches_from_safe(vec![OsString::from("myprog"), |
| /// OsString::from("-u"), |
| /// OsString::from_vec(vec![0xE9])]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::InvalidUtf8); |
| /// ``` |
| /// [`AppSettings::StrictUtf8`]: ./enum.AppSettings.html#variant.StrictUtf8 |
| InvalidUtf8, |
| |
| /// Not a true "error" as it means `--help` or similar was used. |
| /// The help message will be sent to `stdout`. |
| /// |
| /// **Note**: If the help is displayed due to an error (such as missing subcommands) it will |
| /// be sent to `stderr` instead of `stdout`. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind}; |
| /// let result = App::new("prog") |
| /// .get_matches_from_safe(vec!["prog", "--help"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::HelpDisplayed); |
| /// ``` |
| HelpDisplayed, |
| |
| /// Not a true "error" as it means `--version` or similar was used. |
| /// The message will be sent to `stdout`. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// # use clap::{App, Arg, ErrorKind}; |
| /// let result = App::new("prog") |
| /// .get_matches_from_safe(vec!["prog", "--version"]); |
| /// assert!(result.is_err()); |
| /// assert_eq!(result.unwrap_err().kind, ErrorKind::VersionDisplayed); |
| /// ``` |
| VersionDisplayed, |
| |
| /// Occurs when using the [`value_t!`] and [`values_t!`] macros to convert an argument value |
| /// into type `T`, but the argument you requested wasn't used. I.e. you asked for an argument |
| /// with name `config` to be converted, but `config` wasn't used by the user. |
| /// [`value_t!`]: ./macro.value_t!.html |
| /// [`values_t!`]: ./macro.values_t!.html |
| ArgumentNotFound, |
| |
| /// Represents an [I/O error]. |
| /// Can occur when writing to `stderr` or `stdout` or reading a configuration file. |
| /// [I/O error]: https://doc.rust-lang.org/std/io/struct.Error.html |
| Io, |
| |
| /// Represents a [Format error] (which is a part of [`Display`]). |
| /// Typically caused by writing to `stderr` or `stdout`. |
| /// |
| /// [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html |
| /// [Format error]: https://doc.rust-lang.org/std/fmt/struct.Error.html |
| Format, |
| } |
| |
| /// Command Line Argument Parser Error |
| #[derive(Debug)] |
| pub struct Error { |
| /// Formatted error message |
| pub message: String, |
| /// The type of error |
| pub kind: ErrorKind, |
| /// Any additional information passed along, such as the argument name that caused the error |
| pub info: Option<Vec<String>>, |
| } |
| |
| impl Error { |
| /// Should the message be written to `stdout` or not |
| pub fn use_stderr(&self) -> bool { |
| match self.kind { |
| ErrorKind::HelpDisplayed | ErrorKind::VersionDisplayed => false, |
| _ => true, |
| } |
| } |
| |
| /// Prints the error to `stderr` and exits with a status of `1` |
| pub fn exit(&self) -> ! { |
| if self.use_stderr() { |
| wlnerr!("{}", self.message); |
| process::exit(1); |
| } |
| let out = io::stdout(); |
| writeln!(&mut out.lock(), "{}", self.message).expect("Error writing Error to stdout"); |
| process::exit(0); |
| } |
| |
| #[doc(hidden)] |
| pub fn write_to<W: Write>(&self, w: &mut W) -> io::Result<()> { |
| write!(w, "{}", self.message) |
| } |
| |
| #[doc(hidden)] |
| pub fn argument_conflict<O, U>( |
| arg: &AnyArg, |
| other: Option<O>, |
| usage: U, |
| color: ColorWhen, |
| ) -> Self |
| where |
| O: Into<String>, |
| U: Display, |
| { |
| let mut v = vec![arg.name().to_owned()]; |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} The argument '{}' cannot be used with {}\n\n\ |
| {}\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| c.warning(&*arg.to_string()), |
| match other { |
| Some(name) => { |
| let n = name.into(); |
| v.push(n.clone()); |
| c.warning(format!("'{}'", n)) |
| } |
| None => c.none("one or more of the other specified arguments".to_owned()), |
| }, |
| usage, |
| c.good("--help") |
| ), |
| kind: ErrorKind::ArgumentConflict, |
| info: Some(v), |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn empty_value<U>(arg: &AnyArg, usage: U, color: ColorWhen) -> Self |
| where |
| U: Display, |
| { |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} The argument '{}' requires a value but none was supplied\ |
| \n\n\ |
| {}\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| c.warning(arg.to_string()), |
| usage, |
| c.good("--help") |
| ), |
| kind: ErrorKind::EmptyValue, |
| info: Some(vec![arg.name().to_owned()]), |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn 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, |
| { |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| let suffix = suggestions::did_you_mean_value_suffix(bad_val.as_ref(), good_vals.iter()); |
| |
| let mut sorted = vec![]; |
| for v in good_vals { |
| let val = format!("{}", c.good(v)); |
| sorted.push(val); |
| } |
| sorted.sort(); |
| let valid_values = sorted.join(", "); |
| Error { |
| message: format!( |
| "{} '{}' isn't a valid value for '{}'\n\t\ |
| [possible values: {}]\n\ |
| {}\n\n\ |
| {}\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| c.warning(bad_val.as_ref()), |
| c.warning(arg.to_string()), |
| valid_values, |
| suffix.0, |
| usage, |
| c.good("--help") |
| ), |
| kind: ErrorKind::InvalidValue, |
| info: Some(vec![arg.name().to_owned(), bad_val.as_ref().to_owned()]), |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn 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, |
| { |
| let s = subcmd.into(); |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} The subcommand '{}' wasn't recognized\n\t\ |
| Did you mean '{}'?\n\n\ |
| If you believe you received this message in error, try \ |
| re-running with '{} {} {}'\n\n\ |
| {}\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| c.warning(&*s), |
| c.good(did_you_mean.as_ref()), |
| name, |
| c.good("--"), |
| &*s, |
| usage, |
| c.good("--help") |
| ), |
| kind: ErrorKind::InvalidSubcommand, |
| info: Some(vec![s]), |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn unrecognized_subcommand<S, N>(subcmd: S, name: N, color: ColorWhen) -> Self |
| where |
| S: Into<String>, |
| N: Display, |
| { |
| let s = subcmd.into(); |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} The subcommand '{}' wasn't recognized\n\n\ |
| {}\n\t\ |
| {} help <subcommands>...\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| c.warning(&*s), |
| c.warning("USAGE:"), |
| name, |
| c.good("--help") |
| ), |
| kind: ErrorKind::UnrecognizedSubcommand, |
| info: Some(vec![s]), |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn missing_required_argument<R, U>(required: R, usage: U, color: ColorWhen) -> Self |
| where |
| R: Display, |
| U: Display, |
| { |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} The following required arguments were not provided:{}\n\n\ |
| {}\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| required, |
| usage, |
| c.good("--help") |
| ), |
| kind: ErrorKind::MissingRequiredArgument, |
| info: None, |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn missing_subcommand<N, U>(name: N, usage: U, color: ColorWhen) -> Self |
| where |
| N: AsRef<str> + Display, |
| U: Display, |
| { |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} '{}' requires a subcommand, but one was not provided\n\n\ |
| {}\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| c.warning(name), |
| usage, |
| c.good("--help") |
| ), |
| kind: ErrorKind::MissingSubcommand, |
| info: None, |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn invalid_utf8<U>(usage: U, color: ColorWhen) -> Self |
| where |
| U: Display, |
| { |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} Invalid UTF-8 was detected in one or more arguments\n\n\ |
| {}\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| usage, |
| c.good("--help") |
| ), |
| kind: ErrorKind::InvalidUtf8, |
| info: None, |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn too_many_values<V, U>(val: V, arg: &AnyArg, usage: U, color: ColorWhen) -> Self |
| where |
| V: AsRef<str> + Display + ToOwned, |
| U: Display, |
| { |
| let v = val.as_ref(); |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} The value '{}' was provided to '{}', but it wasn't expecting \ |
| any more values\n\n\ |
| {}\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| c.warning(v), |
| c.warning(arg.to_string()), |
| usage, |
| c.good("--help") |
| ), |
| kind: ErrorKind::TooManyValues, |
| info: Some(vec![arg.name().to_owned(), v.to_owned()]), |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn too_few_values<U>( |
| arg: &AnyArg, |
| min_vals: u64, |
| curr_vals: usize, |
| usage: U, |
| color: ColorWhen, |
| ) -> Self |
| where |
| U: Display, |
| { |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} The argument '{}' requires at least {} values, but only {} w{} \ |
| provided\n\n\ |
| {}\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| c.warning(arg.to_string()), |
| c.warning(min_vals.to_string()), |
| c.warning(curr_vals.to_string()), |
| if curr_vals > 1 { "ere" } else { "as" }, |
| usage, |
| c.good("--help") |
| ), |
| kind: ErrorKind::TooFewValues, |
| info: Some(vec![arg.name().to_owned()]), |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn value_validation(arg: Option<&AnyArg>, err: String, color: ColorWhen) -> Self { |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} Invalid value{}: {}", |
| c.error("error:"), |
| if let Some(a) = arg { |
| format!(" for '{}'", c.warning(a.to_string())) |
| } else { |
| "".to_string() |
| }, |
| err |
| ), |
| kind: ErrorKind::ValueValidation, |
| info: None, |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn value_validation_auto(err: String) -> Self { |
| let n: Option<&AnyArg> = None; |
| Error::value_validation(n, err, ColorWhen::Auto) |
| } |
| |
| #[doc(hidden)] |
| pub fn 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, |
| { |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} The argument '{}' requires {} values, but {} w{} \ |
| provided\n\n\ |
| {}\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| c.warning(arg.to_string()), |
| c.warning(num_vals.to_string()), |
| c.warning(curr_vals.to_string()), |
| suffix, |
| usage, |
| c.good("--help") |
| ), |
| kind: ErrorKind::WrongNumberOfValues, |
| info: Some(vec![arg.name().to_owned()]), |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn unexpected_multiple_usage<U>(arg: &AnyArg, usage: U, color: ColorWhen) -> Self |
| where |
| U: Display, |
| { |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} The argument '{}' was provided more than once, but cannot \ |
| be used multiple times\n\n\ |
| {}\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| c.warning(arg.to_string()), |
| usage, |
| c.good("--help") |
| ), |
| kind: ErrorKind::UnexpectedMultipleUsage, |
| info: Some(vec![arg.name().to_owned()]), |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn unknown_argument<A, U>(arg: A, did_you_mean: &str, usage: U, color: ColorWhen) -> Self |
| where |
| A: Into<String>, |
| U: Display, |
| { |
| let a = arg.into(); |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!( |
| "{} Found argument '{}' which wasn't expected, or isn't valid in \ |
| this context{}\n\ |
| {}\n\n\ |
| For more information try {}", |
| c.error("error:"), |
| c.warning(&*a), |
| if did_you_mean.is_empty() { |
| "\n".to_owned() |
| } else { |
| format!("{}\n", did_you_mean) |
| }, |
| usage, |
| c.good("--help") |
| ), |
| kind: ErrorKind::UnknownArgument, |
| info: Some(vec![a]), |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn io_error(e: &Error, color: ColorWhen) -> Self { |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: color, |
| }); |
| Error { |
| message: format!("{} {}", c.error("error:"), e.description()), |
| kind: ErrorKind::Io, |
| info: None, |
| } |
| } |
| |
| #[doc(hidden)] |
| pub fn argument_not_found_auto<A>(arg: A) -> Self |
| where |
| A: Into<String>, |
| { |
| let a = arg.into(); |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: ColorWhen::Auto, |
| }); |
| Error { |
| message: format!( |
| "{} The argument '{}' wasn't found", |
| c.error("error:"), |
| a.clone() |
| ), |
| kind: ErrorKind::ArgumentNotFound, |
| info: Some(vec![a]), |
| } |
| } |
| |
| /// Create an error with a custom description. |
| /// |
| /// This can be used in combination with `Error::exit` to exit your program |
| /// with a custom error message. |
| pub fn with_description(description: &str, kind: ErrorKind) -> Self { |
| let c = Colorizer::new(ColorizerOption { |
| use_stderr: true, |
| when: ColorWhen::Auto, |
| }); |
| Error { |
| message: format!("{} {}", c.error("error:"), description), |
| kind: kind, |
| info: None, |
| } |
| } |
| } |
| |
| impl StdError for Error { |
| fn description(&self) -> &str { |
| &*self.message |
| } |
| } |
| |
| impl Display for Error { |
| fn fmt(&self, f: &mut std_fmt::Formatter) -> std_fmt::Result { |
| writeln!(f, "{}", self.message) |
| } |
| } |
| |
| impl From<io::Error> for Error { |
| fn from(e: io::Error) -> Self { |
| Error::with_description(e.description(), ErrorKind::Io) |
| } |
| } |
| |
| impl From<std_fmt::Error> for Error { |
| fn from(e: std_fmt::Error) -> Self { |
| Error::with_description(e.description(), ErrorKind::Format) |
| } |
| } |