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