diff options
author | Valentin Popov <valentin@popov.link> | 2024-07-19 15:37:58 +0300 |
---|---|---|
committer | Valentin Popov <valentin@popov.link> | 2024-07-19 15:37:58 +0300 |
commit | a990de90fe41456a23e58bd087d2f107d321f3a1 (patch) | |
tree | 15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/clap_builder/src/error | |
parent | 3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff) | |
download | fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip |
Deleted vendor folder
Diffstat (limited to 'vendor/clap_builder/src/error')
-rw-r--r-- | vendor/clap_builder/src/error/context.rs | 114 | ||||
-rw-r--r-- | vendor/clap_builder/src/error/format.rs | 545 | ||||
-rw-r--r-- | vendor/clap_builder/src/error/kind.rs | 366 | ||||
-rw-r--r-- | vendor/clap_builder/src/error/mod.rs | 923 |
4 files changed, 0 insertions, 1948 deletions
diff --git a/vendor/clap_builder/src/error/context.rs b/vendor/clap_builder/src/error/context.rs deleted file mode 100644 index 045923c..0000000 --- a/vendor/clap_builder/src/error/context.rs +++ /dev/null @@ -1,114 +0,0 @@ -/// Semantics for a piece of error information -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -#[non_exhaustive] -#[cfg(feature = "error-context")] -pub enum ContextKind { - /// The cause of the error - InvalidSubcommand, - /// The cause of the error - InvalidArg, - /// Existing arguments - PriorArg, - /// Accepted subcommands - ValidSubcommand, - /// Accepted values - ValidValue, - /// Rejected values - InvalidValue, - /// Number of values present - ActualNumValues, - /// Number of allowed values - ExpectedNumValues, - /// Minimum number of allowed values - MinValues, - /// Potential fix for the user - SuggestedCommand, - /// Potential fix for the user - SuggestedSubcommand, - /// Potential fix for the user - SuggestedArg, - /// Potential fix for the user - SuggestedValue, - /// Trailing argument - TrailingArg, - /// Potential fix for the user - Suggested, - /// A usage string - Usage, - /// An opaque message to the user - Custom, -} - -impl ContextKind { - /// End-user description of the error case, where relevant - pub fn as_str(self) -> Option<&'static str> { - match self { - Self::InvalidSubcommand => Some("Invalid Subcommand"), - Self::InvalidArg => Some("Invalid Argument"), - Self::PriorArg => Some("Prior Argument"), - Self::ValidSubcommand => Some("Valid Subcommand"), - Self::ValidValue => Some("Valid Value"), - Self::InvalidValue => Some("Invalid Value"), - Self::ActualNumValues => Some("Actual Number of Values"), - Self::ExpectedNumValues => Some("Expected Number of Values"), - Self::MinValues => Some("Minimum Number of Values"), - Self::SuggestedCommand => Some("Suggested Command"), - Self::SuggestedSubcommand => Some("Suggested Subcommand"), - Self::SuggestedArg => Some("Suggested Argument"), - Self::SuggestedValue => Some("Suggested Value"), - Self::TrailingArg => Some("Trailing Argument"), - Self::Suggested => Some("Suggested"), - Self::Usage => None, - Self::Custom => None, - } - } -} - -impl std::fmt::Display for ContextKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.as_str().unwrap_or_default().fmt(f) - } -} - -/// A piece of error information -#[derive(Clone, Debug, PartialEq, Eq)] -#[non_exhaustive] -#[cfg(feature = "error-context")] -pub enum ContextValue { - /// [`ContextKind`] is self-sufficient, no additional information needed - None, - /// A single value - Bool(bool), - /// A single value - String(String), - /// Many values - Strings(Vec<String>), - /// A single value - StyledStr(crate::builder::StyledStr), - /// many value - StyledStrs(Vec<crate::builder::StyledStr>), - /// A single value - Number(isize), -} - -impl std::fmt::Display for ContextValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::None => "".fmt(f), - Self::Bool(v) => v.fmt(f), - Self::String(v) => v.fmt(f), - Self::Strings(v) => v.join(", ").fmt(f), - Self::StyledStr(v) => v.fmt(f), - Self::StyledStrs(v) => { - for (i, v) in v.iter().enumerate() { - if i != 0 { - ", ".fmt(f)?; - } - v.fmt(f)?; - } - Ok(()) - } - Self::Number(v) => v.fmt(f), - } - } -} diff --git a/vendor/clap_builder/src/error/format.rs b/vendor/clap_builder/src/error/format.rs deleted file mode 100644 index 49e617d..0000000 --- a/vendor/clap_builder/src/error/format.rs +++ /dev/null @@ -1,545 +0,0 @@ -#![allow(missing_copy_implementations)] -#![allow(missing_debug_implementations)] -#![cfg_attr(not(feature = "error-context"), allow(dead_code))] -#![cfg_attr(not(feature = "error-context"), allow(unused_imports))] - -use crate::builder::Command; -use crate::builder::StyledStr; -use crate::builder::Styles; -#[cfg(feature = "error-context")] -use crate::error::ContextKind; -#[cfg(feature = "error-context")] -use crate::error::ContextValue; -use crate::error::ErrorKind; -use crate::output::TAB; - -/// Defines how to format an error for displaying to the user -pub trait ErrorFormatter: Sized { - /// Stylize the error for the terminal - fn format_error(error: &crate::error::Error<Self>) -> StyledStr; -} - -/// Report [`ErrorKind`] -/// -/// No context is included. -/// -/// **NOTE:** Consider removing the `error-context` default feature if using this to remove all -/// overhead for [`RichFormatter`]. -#[non_exhaustive] -pub struct KindFormatter; - -impl ErrorFormatter for KindFormatter { - fn format_error(error: &crate::error::Error<Self>) -> StyledStr { - use std::fmt::Write as _; - let styles = &error.inner.styles; - - let mut styled = StyledStr::new(); - start_error(&mut styled, styles); - if let Some(msg) = error.kind().as_str() { - styled.push_str(msg); - } else if let Some(source) = error.inner.source.as_ref() { - let _ = write!(styled, "{source}"); - } else { - styled.push_str("unknown cause"); - } - styled.push_str("\n"); - styled - } -} - -/// Richly formatted error context -/// -/// This follows the [rustc diagnostic style guide](https://rustc-dev-guide.rust-lang.org/diagnostics.html#suggestion-style-guide). -#[non_exhaustive] -#[cfg(feature = "error-context")] -pub struct RichFormatter; - -#[cfg(feature = "error-context")] -impl ErrorFormatter for RichFormatter { - fn format_error(error: &crate::error::Error<Self>) -> StyledStr { - use std::fmt::Write as _; - let styles = &error.inner.styles; - let valid = &styles.get_valid(); - - let mut styled = StyledStr::new(); - start_error(&mut styled, styles); - - if !write_dynamic_context(error, &mut styled, styles) { - if let Some(msg) = error.kind().as_str() { - styled.push_str(msg); - } else if let Some(source) = error.inner.source.as_ref() { - let _ = write!(styled, "{source}"); - } else { - styled.push_str("unknown cause"); - } - } - - let mut suggested = false; - if let Some(valid) = error.get(ContextKind::SuggestedSubcommand) { - styled.push_str("\n"); - if !suggested { - styled.push_str("\n"); - suggested = true; - } - did_you_mean(&mut styled, styles, "subcommand", valid); - } - if let Some(valid) = error.get(ContextKind::SuggestedArg) { - styled.push_str("\n"); - if !suggested { - styled.push_str("\n"); - suggested = true; - } - did_you_mean(&mut styled, styles, "argument", valid); - } - if let Some(valid) = error.get(ContextKind::SuggestedValue) { - styled.push_str("\n"); - if !suggested { - styled.push_str("\n"); - suggested = true; - } - did_you_mean(&mut styled, styles, "value", valid); - } - let suggestions = error.get(ContextKind::Suggested); - if let Some(ContextValue::StyledStrs(suggestions)) = suggestions { - if !suggested { - styled.push_str("\n"); - } - for suggestion in suggestions { - let _ = write!( - styled, - "\n{TAB}{}tip:{} ", - valid.render(), - valid.render_reset() - ); - styled.push_styled(suggestion); - } - } - - let usage = error.get(ContextKind::Usage); - if let Some(ContextValue::StyledStr(usage)) = usage { - put_usage(&mut styled, usage); - } - - try_help(&mut styled, styles, error.inner.help_flag); - - styled - } -} - -fn start_error(styled: &mut StyledStr, styles: &Styles) { - use std::fmt::Write as _; - let error = &styles.get_error(); - let _ = write!(styled, "{}error:{} ", error.render(), error.render_reset()); -} - -#[must_use] -#[cfg(feature = "error-context")] -fn write_dynamic_context( - error: &crate::error::Error, - styled: &mut StyledStr, - styles: &Styles, -) -> bool { - use std::fmt::Write as _; - let valid = styles.get_valid(); - let invalid = styles.get_invalid(); - let literal = styles.get_literal(); - - match error.kind() { - ErrorKind::ArgumentConflict => { - let invalid_arg = error.get(ContextKind::InvalidArg); - let prior_arg = error.get(ContextKind::PriorArg); - if let (Some(ContextValue::String(invalid_arg)), Some(prior_arg)) = - (invalid_arg, prior_arg) - { - if ContextValue::String(invalid_arg.clone()) == *prior_arg { - let _ = write!( - styled, - "the argument '{}{invalid_arg}{}' cannot be used multiple times", - invalid.render(), - invalid.render_reset() - ); - } else { - let _ = write!( - styled, - "the argument '{}{invalid_arg}{}' cannot be used with", - invalid.render(), - invalid.render_reset() - ); - - match prior_arg { - ContextValue::Strings(values) => { - styled.push_str(":"); - for v in values { - let _ = write!( - styled, - "\n{TAB}{}{v}{}", - invalid.render(), - invalid.render_reset() - ); - } - } - ContextValue::String(value) => { - let _ = write!( - styled, - " '{}{value}{}'", - invalid.render(), - invalid.render_reset() - ); - } - _ => { - styled.push_str(" one or more of the other specified arguments"); - } - } - } - true - } else { - false - } - } - ErrorKind::NoEquals => { - let invalid_arg = error.get(ContextKind::InvalidArg); - if let Some(ContextValue::String(invalid_arg)) = invalid_arg { - let _ = write!( - styled, - "equal sign is needed when assigning values to '{}{invalid_arg}{}'", - invalid.render(), - invalid.render_reset() - ); - true - } else { - false - } - } - ErrorKind::InvalidValue => { - let invalid_arg = error.get(ContextKind::InvalidArg); - let invalid_value = error.get(ContextKind::InvalidValue); - if let ( - Some(ContextValue::String(invalid_arg)), - Some(ContextValue::String(invalid_value)), - ) = (invalid_arg, invalid_value) - { - if invalid_value.is_empty() { - let _ = write!( - styled, - "a value is required for '{}{invalid_arg}{}' but none was supplied", - invalid.render(), - invalid.render_reset() - ); - } else { - let _ = write!( - styled, - "invalid value '{}{invalid_value}{}' for '{}{invalid_arg}{}'", - invalid.render(), - invalid.render_reset(), - literal.render(), - literal.render_reset() - ); - } - - let values = error.get(ContextKind::ValidValue); - write_values_list("possible values", styled, valid, values); - - true - } else { - false - } - } - ErrorKind::InvalidSubcommand => { - let invalid_sub = error.get(ContextKind::InvalidSubcommand); - if let Some(ContextValue::String(invalid_sub)) = invalid_sub { - let _ = write!( - styled, - "unrecognized subcommand '{}{invalid_sub}{}'", - invalid.render(), - invalid.render_reset() - ); - true - } else { - false - } - } - ErrorKind::MissingRequiredArgument => { - let invalid_arg = error.get(ContextKind::InvalidArg); - if let Some(ContextValue::Strings(invalid_arg)) = invalid_arg { - styled.push_str("the following required arguments were not provided:"); - for v in invalid_arg { - let _ = write!( - styled, - "\n{TAB}{}{v}{}", - valid.render(), - valid.render_reset() - ); - } - true - } else { - false - } - } - ErrorKind::MissingSubcommand => { - let invalid_sub = error.get(ContextKind::InvalidSubcommand); - if let Some(ContextValue::String(invalid_sub)) = invalid_sub { - let _ = write!( - styled, - "'{}{invalid_sub}{}' requires a subcommand but one was not provided", - invalid.render(), - invalid.render_reset() - ); - let values = error.get(ContextKind::ValidSubcommand); - write_values_list("subcommands", styled, valid, values); - - true - } else { - false - } - } - ErrorKind::InvalidUtf8 => false, - ErrorKind::TooManyValues => { - let invalid_arg = error.get(ContextKind::InvalidArg); - let invalid_value = error.get(ContextKind::InvalidValue); - if let ( - Some(ContextValue::String(invalid_arg)), - Some(ContextValue::String(invalid_value)), - ) = (invalid_arg, invalid_value) - { - let _ = write!( - styled, - "unexpected value '{}{invalid_value}{}' for '{}{invalid_arg}{}' found; no more were expected", - invalid.render(), - invalid.render_reset(), - literal.render(), - literal.render_reset(), - ); - true - } else { - false - } - } - ErrorKind::TooFewValues => { - let invalid_arg = error.get(ContextKind::InvalidArg); - let actual_num_values = error.get(ContextKind::ActualNumValues); - let min_values = error.get(ContextKind::MinValues); - if let ( - Some(ContextValue::String(invalid_arg)), - Some(ContextValue::Number(actual_num_values)), - Some(ContextValue::Number(min_values)), - ) = (invalid_arg, actual_num_values, min_values) - { - let were_provided = singular_or_plural(*actual_num_values as usize); - let _ = write!( - styled, - "{}{min_values}{} more values required by '{}{invalid_arg}{}'; only {}{actual_num_values}{}{were_provided}", - valid.render(), - valid.render_reset(), - literal.render(), - literal.render_reset(), - invalid.render(), - invalid.render_reset(), - ); - true - } else { - false - } - } - ErrorKind::ValueValidation => { - let invalid_arg = error.get(ContextKind::InvalidArg); - let invalid_value = error.get(ContextKind::InvalidValue); - if let ( - Some(ContextValue::String(invalid_arg)), - Some(ContextValue::String(invalid_value)), - ) = (invalid_arg, invalid_value) - { - let _ = write!( - styled, - "invalid value '{}{invalid_value}{}' for '{}{invalid_arg}{}'", - invalid.render(), - invalid.render_reset(), - literal.render(), - literal.render_reset(), - ); - if let Some(source) = error.inner.source.as_deref() { - let _ = write!(styled, ": {source}"); - } - true - } else { - false - } - } - ErrorKind::WrongNumberOfValues => { - let invalid_arg = error.get(ContextKind::InvalidArg); - let actual_num_values = error.get(ContextKind::ActualNumValues); - let num_values = error.get(ContextKind::ExpectedNumValues); - if let ( - Some(ContextValue::String(invalid_arg)), - Some(ContextValue::Number(actual_num_values)), - Some(ContextValue::Number(num_values)), - ) = (invalid_arg, actual_num_values, num_values) - { - let were_provided = singular_or_plural(*actual_num_values as usize); - let _ = write!( - styled, - "{}{num_values}{} values required for '{}{invalid_arg}{}' but {}{actual_num_values}{}{were_provided}", - valid.render(), - valid.render_reset(), - literal.render(), - literal.render_reset(), - invalid.render(), - invalid.render_reset(), - ); - true - } else { - false - } - } - ErrorKind::UnknownArgument => { - let invalid_arg = error.get(ContextKind::InvalidArg); - if let Some(ContextValue::String(invalid_arg)) = invalid_arg { - let _ = write!( - styled, - "unexpected argument '{}{invalid_arg}{}' found", - invalid.render(), - invalid.render_reset(), - ); - true - } else { - false - } - } - ErrorKind::DisplayHelp - | ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand - | ErrorKind::DisplayVersion - | ErrorKind::Io - | ErrorKind::Format => false, - } -} - -#[cfg(feature = "error-context")] -fn write_values_list( - list_name: &'static str, - styled: &mut StyledStr, - valid: &anstyle::Style, - possible_values: Option<&ContextValue>, -) { - use std::fmt::Write as _; - if let Some(ContextValue::Strings(possible_values)) = possible_values { - if !possible_values.is_empty() { - let _ = write!(styled, "\n{TAB}[{list_name}: "); - - let style = valid.render(); - let reset = valid.render_reset(); - for (idx, val) in possible_values.iter().enumerate() { - if idx > 0 { - styled.push_str(", "); - } - let _ = write!(styled, "{style}{}{reset}", Escape(val)); - } - - styled.push_str("]"); - } - } -} - -pub(crate) fn format_error_message( - message: &str, - styles: &Styles, - cmd: Option<&Command>, - usage: Option<&StyledStr>, -) -> StyledStr { - let mut styled = StyledStr::new(); - start_error(&mut styled, styles); - styled.push_str(message); - if let Some(usage) = usage { - put_usage(&mut styled, usage); - } - if let Some(cmd) = cmd { - try_help(&mut styled, styles, get_help_flag(cmd)); - } - styled -} - -/// Returns the singular or plural form on the verb to be based on the argument's value. -fn singular_or_plural(n: usize) -> &'static str { - if n > 1 { - " were provided" - } else { - " was provided" - } -} - -fn put_usage(styled: &mut StyledStr, usage: &StyledStr) { - styled.push_str("\n\n"); - styled.push_styled(usage); -} - -pub(crate) fn get_help_flag(cmd: &Command) -> Option<&'static str> { - if !cmd.is_disable_help_flag_set() { - Some("--help") - } else if cmd.has_subcommands() && !cmd.is_disable_help_subcommand_set() { - Some("help") - } else { - None - } -} - -fn try_help(styled: &mut StyledStr, styles: &Styles, help: Option<&str>) { - if let Some(help) = help { - use std::fmt::Write as _; - let literal = &styles.get_literal(); - let _ = write!( - styled, - "\n\nFor more information, try '{}{help}{}'.\n", - literal.render(), - literal.render_reset() - ); - } else { - styled.push_str("\n"); - } -} - -#[cfg(feature = "error-context")] -fn did_you_mean(styled: &mut StyledStr, styles: &Styles, context: &str, valid: &ContextValue) { - use std::fmt::Write as _; - - let _ = write!( - styled, - "{TAB}{}tip:{}", - styles.get_valid().render(), - styles.get_valid().render_reset() - ); - if let ContextValue::String(valid) = valid { - let _ = write!( - styled, - " a similar {context} exists: '{}{valid}{}'", - styles.get_valid().render(), - styles.get_valid().render_reset() - ); - } else if let ContextValue::Strings(valid) = valid { - if valid.len() == 1 { - let _ = write!(styled, " a similar {context} exists: ",); - } else { - let _ = write!(styled, " some similar {context}s exist: ",); - } - for (i, valid) in valid.iter().enumerate() { - if i != 0 { - styled.push_str(", "); - } - let _ = write!( - styled, - "'{}{valid}{}'", - styles.get_valid().render(), - styles.get_valid().render_reset() - ); - } - } -} - -struct Escape<'s>(&'s str); - -impl<'s> std::fmt::Display for Escape<'s> { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - if self.0.contains(char::is_whitespace) { - std::fmt::Debug::fmt(self.0, f) - } else { - self.0.fmt(f) - } - } -} diff --git a/vendor/clap_builder/src/error/kind.rs b/vendor/clap_builder/src/error/kind.rs deleted file mode 100644 index a9d576c..0000000 --- a/vendor/clap_builder/src/error/kind.rs +++ /dev/null @@ -1,366 +0,0 @@ -/// Command line argument parser kind of error -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -#[non_exhaustive] -pub enum ErrorKind { - /// Occurs when an [`Arg`][crate::Arg] has a set of possible values, - /// and the user provides a value which isn't in that set. - /// - /// # Examples - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind}; - /// let result = Command::new("prog") - /// .arg(Arg::new("speed") - /// .value_parser(["fast", "slow"])) - /// .try_get_matches_from(vec!["prog", "other"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue); - /// ``` - InvalidValue, - - /// Occurs when a user provides a flag, option, argument or subcommand which isn't defined. - /// - /// # Examples - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::{Command, arg, error::ErrorKind}; - /// let result = Command::new("prog") - /// .arg(arg!(--flag "some flag")) - /// .try_get_matches_from(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 - /// - /// ```rust - /// # #[cfg(feature = "suggestions")] { - /// # use clap_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind, }; - /// let result = Command::new("prog") - /// .subcommand(Command::new("config") - /// .about("Used for configuration") - /// .arg(Arg::new("config_file") - /// .help("The configuration file to use"))) - /// .try_get_matches_from(vec!["prog", "confi"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidSubcommand); - /// # } - /// ``` - /// - /// [`Subcommand`]: crate::Subcommand - /// [`UnknownArgument`]: ErrorKind::UnknownArgument - InvalidSubcommand, - - /// Occurs when the user doesn't use equals for an option that requires equal - /// sign to provide values. - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; - /// let res = Command::new("prog") - /// .arg(Arg::new("color") - /// .action(ArgAction::Set) - /// .require_equals(true) - /// .long("color")) - /// .try_get_matches_from(vec!["prog", "--color", "red"]); - /// assert!(res.is_err()); - /// assert_eq!(res.unwrap_err().kind(), ErrorKind::NoEquals); - /// ``` - NoEquals, - - /// Occurs when the user provides a value for an argument with a custom validation and the - /// value fails that validation. - /// - /// # Examples - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind, value_parser}; - /// fn is_numeric(val: &str) -> Result<(), String> { - /// match val.parse::<i64>() { - /// Ok(..) => Ok(()), - /// Err(..) => Err(String::from("value wasn't a number!")), - /// } - /// } - /// - /// let result = Command::new("prog") - /// .arg(Arg::new("num") - /// .value_parser(value_parser!(u8))) - /// .try_get_matches_from(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::num_args`]. - /// - /// # Examples - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind}; - /// let result = Command::new("prog") - /// .arg(Arg::new("arg") - /// .num_args(1..=2)) - /// .try_get_matches_from(vec!["prog", "too", "many", "values"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyValues); - /// ``` - /// [`Arg::num_args`]: crate::Arg::num_args() - TooManyValues, - - /// Occurs when the user provides fewer values for an argument than were defined by setting - /// [`Arg::num_args`]. - /// - /// # Examples - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind}; - /// let result = Command::new("prog") - /// .arg(Arg::new("some_opt") - /// .long("opt") - /// .num_args(3..)) - /// .try_get_matches_from(vec!["prog", "--opt", "too", "few"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooFewValues); - /// ``` - /// [`Arg::num_args`]: crate::Arg::num_args() - TooFewValues, - - /// Occurs when the user provides a different number of values for an argument than what's - /// been defined by setting [`Arg::num_args`] or than was implicitly set by - /// [`Arg::value_names`]. - /// - /// # Examples - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; - /// let result = Command::new("prog") - /// .arg(Arg::new("some_opt") - /// .long("opt") - /// .action(ArgAction::Set) - /// .num_args(2)) - /// .try_get_matches_from(vec!["prog", "--opt", "wrong"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::WrongNumberOfValues); - /// ``` - /// - /// [`Arg::num_args`]: crate::Arg::num_args() - /// [`Arg::value_names`]: crate::Arg::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_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; - /// let result = Command::new("prog") - /// .arg(Arg::new("debug") - /// .long("debug") - /// .action(ArgAction::SetTrue) - /// .conflicts_with("color")) - /// .arg(Arg::new("color") - /// .long("color") - /// .action(ArgAction::SetTrue)) - /// .try_get_matches_from(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_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind}; - /// let result = Command::new("prog") - /// .arg(Arg::new("debug") - /// .required(true)) - /// .try_get_matches_from(vec!["prog"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument); - /// ``` - MissingRequiredArgument, - - /// Occurs when a subcommand is required (as defined by [`Command::subcommand_required`]), - /// but the user does not provide one. - /// - /// # Examples - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::{Command, error::ErrorKind}; - /// let err = Command::new("prog") - /// .subcommand_required(true) - /// .subcommand(Command::new("test")) - /// .try_get_matches_from(vec![ - /// "myprog", - /// ]); - /// assert!(err.is_err()); - /// assert_eq!(err.unwrap_err().kind(), ErrorKind::MissingSubcommand); - /// # ; - /// ``` - /// - /// [`Command::subcommand_required`]: crate::Command::subcommand_required - MissingSubcommand, - - /// Occurs when the user provides a value containing invalid UTF-8. - /// - /// To allow arbitrary data - /// - Set [`Arg::value_parser(value_parser!(OsString))`] for argument values - /// - Set [`Command::external_subcommand_value_parser`] for external-subcommand - /// values - /// - /// # Platform Specific - /// - /// Non-Windows platforms only (such as Linux, Unix, OSX, etc.) - /// - /// # Examples - /// - /// ```rust - /// # #[cfg(unix)] { - /// # use clap_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind, ArgAction}; - /// # use std::os::unix::ffi::OsStringExt; - /// # use std::ffi::OsString; - /// let result = Command::new("prog") - /// .arg(Arg::new("utf8") - /// .short('u') - /// .action(ArgAction::Set)) - /// .try_get_matches_from(vec![OsString::from("myprog"), - /// OsString::from("-u"), - /// OsString::from_vec(vec![0xE9])]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidUtf8); - /// # } - /// ``` - /// - /// [`Arg::allow_invalid_utf8`]: crate::Arg::allow_invalid_utf8 - /// [`Command::external_subcommand_value_parser`]: crate::Command::external_subcommand_value_parser - 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 - /// # #[cfg(feature = "help")] { - /// # use clap_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind}; - /// let result = Command::new("prog") - /// .try_get_matches_from(vec!["prog", "--help"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelp); - /// # } - /// ``` - DisplayHelp, - - /// Occurs when either an argument or a [`Subcommand`] is required, as defined by - /// [`Command::arg_required_else_help`] , but the user did not provide - /// one. - /// - /// # Examples - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind, }; - /// let result = Command::new("prog") - /// .arg_required_else_help(true) - /// .subcommand(Command::new("config") - /// .about("Used for configuration") - /// .arg(Arg::new("config_file") - /// .help("The configuration file to use"))) - /// .try_get_matches_from(vec!["prog"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand); - /// ``` - /// - /// [`Subcommand`]: crate::Subcommand - /// [`Command::arg_required_else_help`]: crate::Command::arg_required_else_help - DisplayHelpOnMissingArgumentOrSubcommand, - - /// Not a true "error" as it means `--version` or similar was used. - /// The message will be sent to `stdout`. - /// - /// # Examples - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::{Command, Arg, error::ErrorKind}; - /// let result = Command::new("prog") - /// .version("3.0") - /// .try_get_matches_from(vec!["prog", "--version"]); - /// assert!(result.is_err()); - /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayVersion); - /// ``` - DisplayVersion, - - /// Represents an [I/O error]. - /// Can occur when writing to `stderr` or `stdout` or reading a configuration file. - /// - /// [I/O error]: std::io::Error - Io, - - /// Represents a [Format error] (which is a part of [`Display`]). - /// Typically caused by writing to `stderr` or `stdout`. - /// - /// [`Display`]: std::fmt::Display - /// [Format error]: std::fmt::Error - Format, -} - -impl ErrorKind { - /// End-user description of the error case, where relevant - pub fn as_str(self) -> Option<&'static str> { - match self { - Self::InvalidValue => Some("one of the values isn't valid for an argument"), - Self::UnknownArgument => Some("unexpected argument found"), - Self::InvalidSubcommand => Some("unrecognized subcommand"), - Self::NoEquals => Some("equal is needed when assigning values to one of the arguments"), - Self::ValueValidation => Some("invalid value for one of the arguments"), - Self::TooManyValues => Some("unexpected value for an argument found"), - Self::TooFewValues => Some("more values required for an argument"), - Self::WrongNumberOfValues => Some("too many or too few values for an argument"), - Self::ArgumentConflict => { - Some("an argument cannot be used with one or more of the other specified arguments") - } - Self::MissingRequiredArgument => { - Some("one or more required arguments were not provided") - } - Self::MissingSubcommand => Some("a subcommand is required but one was not provided"), - Self::InvalidUtf8 => Some("invalid UTF-8 was detected in one or more arguments"), - Self::DisplayHelp => None, - Self::DisplayHelpOnMissingArgumentOrSubcommand => None, - Self::DisplayVersion => None, - Self::Io => None, - Self::Format => None, - } - } -} - -impl std::fmt::Display for ErrorKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.as_str().unwrap_or_default().fmt(f) - } -} diff --git a/vendor/clap_builder/src/error/mod.rs b/vendor/clap_builder/src/error/mod.rs deleted file mode 100644 index af90e27..0000000 --- a/vendor/clap_builder/src/error/mod.rs +++ /dev/null @@ -1,923 +0,0 @@ -//! Error reporting - -#![cfg_attr(not(feature = "error-context"), allow(dead_code))] -#![cfg_attr(not(feature = "error-context"), allow(unused_imports))] -#![cfg_attr(not(feature = "error-context"), allow(unused_variables))] -#![cfg_attr(not(feature = "error-context"), allow(unused_mut))] -#![cfg_attr(not(feature = "error-context"), allow(clippy::let_and_return))] - -// Std -use std::{ - borrow::Cow, - convert::From, - error, - fmt::{self, Debug, Display, Formatter}, - io::{self}, - result::Result as StdResult, -}; - -// Internal -use crate::builder::StyledStr; -use crate::builder::Styles; -use crate::output::fmt::Colorizer; -use crate::output::fmt::Stream; -use crate::parser::features::suggestions; -use crate::util::FlatMap; -use crate::util::{color::ColorChoice, safe_exit, SUCCESS_CODE, USAGE_CODE}; -use crate::Command; - -#[cfg(feature = "error-context")] -mod context; -mod format; -mod kind; - -pub use format::ErrorFormatter; -pub use format::KindFormatter; -pub use kind::ErrorKind; - -#[cfg(feature = "error-context")] -pub use context::ContextKind; -#[cfg(feature = "error-context")] -pub use context::ContextValue; -#[cfg(feature = "error-context")] -pub use format::RichFormatter; - -#[cfg(not(feature = "error-context"))] -pub use KindFormatter as DefaultFormatter; -#[cfg(feature = "error-context")] -pub use RichFormatter as DefaultFormatter; - -/// Short hand for [`Result`] type -/// -/// [`Result`]: std::result::Result -pub type Result<T, E = Error> = StdResult<T, E>; - -/// Command Line Argument Parser Error -/// -/// See [`Command::error`] to create an error. -/// -/// [`Command::error`]: crate::Command::error -pub struct Error<F: ErrorFormatter = DefaultFormatter> { - inner: Box<ErrorInner>, - phantom: std::marker::PhantomData<F>, -} - -#[derive(Debug)] -struct ErrorInner { - kind: ErrorKind, - #[cfg(feature = "error-context")] - context: FlatMap<ContextKind, ContextValue>, - message: Option<Message>, - source: Option<Box<dyn error::Error + Send + Sync>>, - help_flag: Option<&'static str>, - styles: Styles, - color_when: ColorChoice, - color_help_when: ColorChoice, - backtrace: Option<Backtrace>, -} - -impl<F: ErrorFormatter> Error<F> { - /// Create an unformatted error - /// - /// This is for you need to pass the error up to - /// a place that has access to the `Command` at which point you can call [`Error::format`]. - /// - /// Prefer [`Command::error`] for generating errors. - /// - /// [`Command::error`]: crate::Command::error - pub fn raw(kind: ErrorKind, message: impl std::fmt::Display) -> Self { - Self::new(kind).set_message(message.to_string()) - } - - /// Format the existing message with the Command's context - #[must_use] - pub fn format(mut self, cmd: &mut Command) -> Self { - cmd._build_self(false); - let usage = cmd.render_usage_(); - if let Some(message) = self.inner.message.as_mut() { - message.format(cmd, usage); - } - self.with_cmd(cmd) - } - - /// Create an error with a pre-defined message - /// - /// See also - /// - [`Error::insert`] - /// - [`Error::with_cmd`] - /// - /// # Example - /// - /// ```rust - /// # #[cfg(feature = "error-context")] { - /// # use clap_builder as clap; - /// # use clap::error::ErrorKind; - /// # use clap::error::ContextKind; - /// # use clap::error::ContextValue; - /// - /// let cmd = clap::Command::new("prog"); - /// - /// let mut err = clap::Error::new(ErrorKind::ValueValidation) - /// .with_cmd(&cmd); - /// err.insert(ContextKind::InvalidArg, ContextValue::String("--foo".to_owned())); - /// err.insert(ContextKind::InvalidValue, ContextValue::String("bar".to_owned())); - /// - /// err.print(); - /// # } - /// ``` - pub fn new(kind: ErrorKind) -> Self { - Self { - inner: Box::new(ErrorInner { - kind, - #[cfg(feature = "error-context")] - context: FlatMap::new(), - message: None, - source: None, - help_flag: None, - styles: Styles::plain(), - color_when: ColorChoice::Never, - color_help_when: ColorChoice::Never, - backtrace: Backtrace::new(), - }), - phantom: Default::default(), - } - } - - /// Apply [`Command`]'s formatting to the error - /// - /// Generally, this is used with [`Error::new`] - pub fn with_cmd(self, cmd: &Command) -> Self { - self.set_styles(cmd.get_styles().clone()) - .set_color(cmd.get_color()) - .set_colored_help(cmd.color_help()) - .set_help_flag(format::get_help_flag(cmd)) - } - - /// Apply an alternative formatter to the error - /// - /// # Example - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::Command; - /// # use clap::Arg; - /// # use clap::error::KindFormatter; - /// let cmd = Command::new("foo") - /// .arg(Arg::new("input").required(true)); - /// let matches = cmd - /// .try_get_matches_from(["foo", "input.txt"]) - /// .map_err(|e| e.apply::<KindFormatter>()) - /// .unwrap_or_else(|e| e.exit()); - /// ``` - pub fn apply<EF: ErrorFormatter>(self) -> Error<EF> { - Error { - inner: self.inner, - phantom: Default::default(), - } - } - - /// Type of error for programmatic processing - pub fn kind(&self) -> ErrorKind { - self.inner.kind - } - - /// Additional information to further qualify the error - #[cfg(feature = "error-context")] - pub fn context(&self) -> impl Iterator<Item = (ContextKind, &ContextValue)> { - self.inner.context.iter().map(|(k, v)| (*k, v)) - } - - /// Lookup a piece of context - #[inline(never)] - #[cfg(feature = "error-context")] - pub fn get(&self, kind: ContextKind) -> Option<&ContextValue> { - self.inner.context.get(&kind) - } - - /// Insert a piece of context - #[inline(never)] - #[cfg(feature = "error-context")] - pub fn insert(&mut self, kind: ContextKind, value: ContextValue) -> Option<ContextValue> { - self.inner.context.insert(kind, value) - } - - /// Should the message be written to `stdout` or not? - #[inline] - pub fn use_stderr(&self) -> bool { - self.stream() == Stream::Stderr - } - - pub(crate) fn stream(&self) -> Stream { - match self.kind() { - ErrorKind::DisplayHelp | ErrorKind::DisplayVersion => Stream::Stdout, - _ => Stream::Stderr, - } - } - - /// Returns the exit code that `.exit` will exit the process with. - /// - /// When the error's kind would print to `stderr` this returns `2`, - /// else it returns `0`. - pub fn exit_code(&self) -> i32 { - if self.use_stderr() { - USAGE_CODE - } else { - SUCCESS_CODE - } - } - - /// Prints the error and exits. - /// - /// Depending on the error kind, this either prints to `stderr` and exits with a status of `2` - /// or prints to `stdout` and exits with a status of `0`. - pub fn exit(&self) -> ! { - // Swallow broken pipe errors - let _ = self.print(); - safe_exit(self.exit_code()) - } - - /// Prints formatted and colored error to `stdout` or `stderr` according to its error kind - /// - /// # Example - /// ```no_run - /// # use clap_builder as clap; - /// use clap::Command; - /// - /// match Command::new("Command").try_get_matches() { - /// Ok(matches) => { - /// // do_something - /// }, - /// Err(err) => { - /// err.print().expect("Error writing Error"); - /// // do_something - /// }, - /// }; - /// ``` - pub fn print(&self) -> io::Result<()> { - let style = self.formatted(); - let color_when = if matches!( - self.kind(), - ErrorKind::DisplayHelp | ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand, - ) { - self.inner.color_help_when - } else { - self.inner.color_when - }; - let c = Colorizer::new(self.stream(), color_when).with_content(style.into_owned()); - c.print() - } - - /// Render the error message to a [`StyledStr`]. - /// - /// # Example - /// ```no_run - /// # use clap_builder as clap; - /// use clap::Command; - /// - /// match Command::new("Command").try_get_matches() { - /// Ok(matches) => { - /// // do_something - /// }, - /// Err(err) => { - /// let err = err.render(); - /// println!("{err}"); - /// // do_something - /// }, - /// }; - /// ``` - pub fn render(&self) -> StyledStr { - self.formatted().into_owned() - } - - #[inline(never)] - fn for_app(kind: ErrorKind, cmd: &Command, styled: StyledStr) -> Self { - Self::new(kind).set_message(styled).with_cmd(cmd) - } - - pub(crate) fn set_message(mut self, message: impl Into<Message>) -> Self { - self.inner.message = Some(message.into()); - self - } - - pub(crate) fn set_source(mut self, source: Box<dyn error::Error + Send + Sync>) -> Self { - self.inner.source = Some(source); - self - } - - pub(crate) fn set_styles(mut self, styles: Styles) -> Self { - self.inner.styles = styles; - self - } - - pub(crate) fn set_color(mut self, color_when: ColorChoice) -> Self { - self.inner.color_when = color_when; - self - } - - pub(crate) fn set_colored_help(mut self, color_help_when: ColorChoice) -> Self { - self.inner.color_help_when = color_help_when; - self - } - - pub(crate) fn set_help_flag(mut self, help_flag: Option<&'static str>) -> Self { - self.inner.help_flag = help_flag; - self - } - - /// Does not verify if `ContextKind` is already present - #[inline(never)] - #[cfg(feature = "error-context")] - pub(crate) fn insert_context_unchecked( - mut self, - kind: ContextKind, - value: ContextValue, - ) -> Self { - self.inner.context.insert_unchecked(kind, value); - self - } - - /// Does not verify if `ContextKind` is already present - #[inline(never)] - #[cfg(feature = "error-context")] - pub(crate) fn extend_context_unchecked<const N: usize>( - mut self, - context: [(ContextKind, ContextValue); N], - ) -> Self { - self.inner.context.extend_unchecked(context); - self - } - - pub(crate) fn display_help(cmd: &Command, styled: StyledStr) -> Self { - Self::for_app(ErrorKind::DisplayHelp, cmd, styled) - } - - pub(crate) fn display_help_error(cmd: &Command, styled: StyledStr) -> Self { - Self::for_app( - ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand, - cmd, - styled, - ) - } - - pub(crate) fn display_version(cmd: &Command, styled: StyledStr) -> Self { - Self::for_app(ErrorKind::DisplayVersion, cmd, styled) - } - - pub(crate) fn argument_conflict( - cmd: &Command, - arg: String, - mut others: Vec<String>, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::ArgumentConflict).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - let others = match others.len() { - 0 => ContextValue::None, - 1 => ContextValue::String(others.pop().unwrap()), - _ => ContextValue::Strings(others), - }; - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - (ContextKind::PriorArg, others), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn empty_value(cmd: &Command, good_vals: &[String], arg: String) -> Self { - Self::invalid_value(cmd, "".to_owned(), good_vals, arg) - } - - pub(crate) fn no_equals(cmd: &Command, arg: String, usage: Option<StyledStr>) -> Self { - let mut err = Self::new(ErrorKind::NoEquals).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err - .extend_context_unchecked([(ContextKind::InvalidArg, ContextValue::String(arg))]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn invalid_value( - cmd: &Command, - bad_val: String, - good_vals: &[String], - arg: String, - ) -> Self { - let suggestion = suggestions::did_you_mean(&bad_val, good_vals.iter()).pop(); - let mut err = Self::new(ErrorKind::InvalidValue).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - (ContextKind::InvalidValue, ContextValue::String(bad_val)), - ( - ContextKind::ValidValue, - ContextValue::Strings(good_vals.iter().map(|s| (*s).to_owned()).collect()), - ), - ]); - if let Some(suggestion) = suggestion { - err = err.insert_context_unchecked( - ContextKind::SuggestedValue, - ContextValue::String(suggestion), - ); - } - } - - err - } - - pub(crate) fn invalid_subcommand( - cmd: &Command, - subcmd: String, - did_you_mean: Vec<String>, - name: String, - suggested_trailing_arg: bool, - usage: Option<StyledStr>, - ) -> Self { - use std::fmt::Write as _; - let styles = cmd.get_styles(); - let invalid = &styles.get_invalid(); - let valid = &styles.get_valid(); - let mut err = Self::new(ErrorKind::InvalidSubcommand).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - let mut suggestions = vec![]; - if suggested_trailing_arg { - let mut styled_suggestion = StyledStr::new(); - let _ = write!( - styled_suggestion, - "to pass '{}{subcmd}{}' as a value, use '{}{name} -- {subcmd}{}'", - invalid.render(), - invalid.render_reset(), - valid.render(), - valid.render_reset() - ); - suggestions.push(styled_suggestion); - } - - err = err.extend_context_unchecked([ - (ContextKind::InvalidSubcommand, ContextValue::String(subcmd)), - ( - ContextKind::SuggestedSubcommand, - ContextValue::Strings(did_you_mean), - ), - ( - ContextKind::Suggested, - ContextValue::StyledStrs(suggestions), - ), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn unrecognized_subcommand( - cmd: &Command, - subcmd: String, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::InvalidSubcommand).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([( - ContextKind::InvalidSubcommand, - ContextValue::String(subcmd), - )]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn missing_required_argument( - cmd: &Command, - required: Vec<String>, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::MissingRequiredArgument).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([( - ContextKind::InvalidArg, - ContextValue::Strings(required), - )]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn missing_subcommand( - cmd: &Command, - parent: String, - available: Vec<String>, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::MissingSubcommand).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([ - (ContextKind::InvalidSubcommand, ContextValue::String(parent)), - ( - ContextKind::ValidSubcommand, - ContextValue::Strings(available), - ), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn invalid_utf8(cmd: &Command, usage: Option<StyledStr>) -> Self { - let mut err = Self::new(ErrorKind::InvalidUtf8).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn too_many_values( - cmd: &Command, - val: String, - arg: String, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::TooManyValues).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - (ContextKind::InvalidValue, ContextValue::String(val)), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn too_few_values( - cmd: &Command, - arg: String, - min_vals: usize, - curr_vals: usize, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::TooFewValues).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - ( - ContextKind::MinValues, - ContextValue::Number(min_vals as isize), - ), - ( - ContextKind::ActualNumValues, - ContextValue::Number(curr_vals as isize), - ), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn value_validation( - arg: String, - val: String, - err: Box<dyn error::Error + Send + Sync>, - ) -> Self { - let mut err = Self::new(ErrorKind::ValueValidation).set_source(err); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - (ContextKind::InvalidValue, ContextValue::String(val)), - ]); - } - - err - } - - pub(crate) fn wrong_number_of_values( - cmd: &Command, - arg: String, - num_vals: usize, - curr_vals: usize, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::WrongNumberOfValues).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - ( - ContextKind::ExpectedNumValues, - ContextValue::Number(num_vals as isize), - ), - ( - ContextKind::ActualNumValues, - ContextValue::Number(curr_vals as isize), - ), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn unknown_argument( - cmd: &Command, - arg: String, - did_you_mean: Option<(String, Option<String>)>, - suggested_trailing_arg: bool, - usage: Option<StyledStr>, - ) -> Self { - use std::fmt::Write as _; - let styles = cmd.get_styles(); - let invalid = &styles.get_invalid(); - let valid = &styles.get_valid(); - let mut err = Self::new(ErrorKind::UnknownArgument).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - let mut suggestions = vec![]; - if suggested_trailing_arg { - let mut styled_suggestion = StyledStr::new(); - let _ = write!( - styled_suggestion, - "to pass '{}{arg}{}' as a value, use '{}-- {arg}{}'", - invalid.render(), - invalid.render_reset(), - valid.render(), - valid.render_reset() - ); - suggestions.push(styled_suggestion); - } - - err = err - .extend_context_unchecked([(ContextKind::InvalidArg, ContextValue::String(arg))]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - match did_you_mean { - Some((flag, Some(sub))) => { - let mut styled_suggestion = StyledStr::new(); - let _ = write!( - styled_suggestion, - "'{}{sub} {flag}{}' exists", - valid.render(), - valid.render_reset() - ); - suggestions.push(styled_suggestion); - } - Some((flag, None)) => { - err = err.insert_context_unchecked( - ContextKind::SuggestedArg, - ContextValue::String(flag), - ); - } - None => {} - } - if !suggestions.is_empty() { - err = err.insert_context_unchecked( - ContextKind::Suggested, - ContextValue::StyledStrs(suggestions), - ); - } - } - - err - } - - pub(crate) fn unnecessary_double_dash( - cmd: &Command, - arg: String, - usage: Option<StyledStr>, - ) -> Self { - use std::fmt::Write as _; - let styles = cmd.get_styles(); - let invalid = &styles.get_invalid(); - let valid = &styles.get_valid(); - let mut err = Self::new(ErrorKind::UnknownArgument).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - let mut styled_suggestion = StyledStr::new(); - let _ = write!( - styled_suggestion, - "subcommand '{}{arg}{}' exists; to use it, remove the '{}--{}' before it", - valid.render(), - valid.render_reset(), - invalid.render(), - invalid.render_reset() - ); - - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - ( - ContextKind::Suggested, - ContextValue::StyledStrs(vec![styled_suggestion]), - ), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - fn formatted(&self) -> Cow<'_, StyledStr> { - if let Some(message) = self.inner.message.as_ref() { - message.formatted(&self.inner.styles) - } else { - let styled = F::format_error(self); - Cow::Owned(styled) - } - } -} - -impl<F: ErrorFormatter> From<io::Error> for Error<F> { - fn from(e: io::Error) -> Self { - Error::raw(ErrorKind::Io, e) - } -} - -impl<F: ErrorFormatter> From<fmt::Error> for Error<F> { - fn from(e: fmt::Error) -> Self { - Error::raw(ErrorKind::Format, e) - } -} - -impl<F: ErrorFormatter> std::fmt::Debug for Error<F> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - self.inner.fmt(f) - } -} - -impl<F: ErrorFormatter> error::Error for Error<F> { - #[allow(trivial_casts)] - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - self.inner.source.as_ref().map(|e| e.as_ref() as _) - } -} - -impl<F: ErrorFormatter> Display for Error<F> { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - // Assuming `self.message` already has a trailing newline, from `try_help` or similar - ok!(write!(f, "{}", self.formatted())); - if let Some(backtrace) = self.inner.backtrace.as_ref() { - ok!(writeln!(f)); - ok!(writeln!(f, "Backtrace:")); - ok!(writeln!(f, "{backtrace}")); - } - Ok(()) - } -} - -#[derive(Clone, Debug)] -pub(crate) enum Message { - Raw(String), - Formatted(StyledStr), -} - -impl Message { - fn format(&mut self, cmd: &Command, usage: Option<StyledStr>) { - match self { - Message::Raw(s) => { - let mut message = String::new(); - std::mem::swap(s, &mut message); - - let styled = format::format_error_message( - &message, - cmd.get_styles(), - Some(cmd), - usage.as_ref(), - ); - - *self = Self::Formatted(styled); - } - Message::Formatted(_) => {} - } - } - - fn formatted(&self, styles: &Styles) -> Cow<StyledStr> { - match self { - Message::Raw(s) => { - let styled = format::format_error_message(s, styles, None, None); - - Cow::Owned(styled) - } - Message::Formatted(s) => Cow::Borrowed(s), - } - } -} - -impl From<String> for Message { - fn from(inner: String) -> Self { - Self::Raw(inner) - } -} - -impl From<StyledStr> for Message { - fn from(inner: StyledStr) -> Self { - Self::Formatted(inner) - } -} - -#[cfg(feature = "debug")] -#[derive(Debug)] -struct Backtrace(backtrace::Backtrace); - -#[cfg(feature = "debug")] -impl Backtrace { - fn new() -> Option<Self> { - Some(Self(backtrace::Backtrace::new())) - } -} - -#[cfg(feature = "debug")] -impl Display for Backtrace { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - // `backtrace::Backtrace` uses `Debug` instead of `Display` - write!(f, "{:?}", self.0) - } -} - -#[cfg(not(feature = "debug"))] -#[derive(Debug)] -struct Backtrace; - -#[cfg(not(feature = "debug"))] -impl Backtrace { - fn new() -> Option<Self> { - None - } -} - -#[cfg(not(feature = "debug"))] -impl Display for Backtrace { - fn fmt(&self, _: &mut Formatter) -> fmt::Result { - Ok(()) - } -} - -#[test] -fn check_auto_traits() { - static_assertions::assert_impl_all!(Error: Send, Sync, Unpin); -} |