diff options
Diffstat (limited to 'vendor/clap_builder/src/error/format.rs')
-rw-r--r-- | vendor/clap_builder/src/error/format.rs | 545 |
1 files changed, 0 insertions, 545 deletions
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) - } - } -} |