diff options
Diffstat (limited to 'vendor/clap_builder/src/error')
-rw-r--r-- | vendor/clap_builder/src/error/format.rs | 375 | ||||
-rw-r--r-- | vendor/clap_builder/src/error/mod.rs | 90 |
2 files changed, 298 insertions, 167 deletions
diff --git a/vendor/clap_builder/src/error/format.rs b/vendor/clap_builder/src/error/format.rs index 5ada0abe5..b5f0c1264 100644 --- a/vendor/clap_builder/src/error/format.rs +++ b/vendor/clap_builder/src/error/format.rs @@ -5,6 +5,7 @@ use crate::builder::Command; use crate::builder::StyledStr; +use crate::builder::Styles; #[cfg(feature = "error-context")] use crate::error::ContextKind; #[cfg(feature = "error-context")] @@ -29,16 +30,19 @@ 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); + start_error(&mut styled, styles); if let Some(msg) = error.kind().as_str() { - styled.none(msg.to_owned()); + styled.push_str(msg); } else if let Some(source) = error.inner.source.as_ref() { - styled.none(source.to_string()); + let _ = write!(styled, "{}", source); } else { - styled.none("unknown cause"); + styled.push_str("unknown cause"); } - styled.none("\n"); + styled.push_str("\n"); styled } } @@ -53,53 +57,60 @@ 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); + start_error(&mut styled, styles); - if !write_dynamic_context(error, &mut styled) { + if !write_dynamic_context(error, &mut styled, styles) { if let Some(msg) = error.kind().as_str() { - styled.none(msg.to_owned()); + styled.push_str(msg); } else if let Some(source) = error.inner.source.as_ref() { - styled.none(source.to_string()); + let _ = write!(styled, "{}", source); } else { - styled.none("unknown cause"); + styled.push_str("unknown cause"); } } let mut suggested = false; if let Some(valid) = error.get(ContextKind::SuggestedSubcommand) { - styled.none("\n"); + styled.push_str("\n"); if !suggested { - styled.none("\n"); + styled.push_str("\n"); suggested = true; } - did_you_mean(&mut styled, "subcommand", valid); + did_you_mean(&mut styled, styles, "subcommand", valid); } if let Some(valid) = error.get(ContextKind::SuggestedArg) { - styled.none("\n"); + styled.push_str("\n"); if !suggested { - styled.none("\n"); + styled.push_str("\n"); suggested = true; } - did_you_mean(&mut styled, "argument", valid); + did_you_mean(&mut styled, styles, "argument", valid); } if let Some(valid) = error.get(ContextKind::SuggestedValue) { - styled.none("\n"); + styled.push_str("\n"); if !suggested { - styled.none("\n"); + styled.push_str("\n"); suggested = true; } - did_you_mean(&mut styled, "value", valid); + did_you_mean(&mut styled, styles, "value", valid); } let suggestions = error.get(ContextKind::Suggested); if let Some(ContextValue::StyledStrs(suggestions)) = suggestions { if !suggested { - styled.none("\n"); + styled.push_str("\n"); } for suggestion in suggestions { - styled.none("\n"); - styled.none(TAB); - styled.good("tip: "); + let _ = write!( + styled, + "\n{TAB}{}tip:{} ", + valid.render(), + valid.render_reset() + ); styled.push_styled(suggestion); } } @@ -109,20 +120,30 @@ impl ErrorFormatter for RichFormatter { put_usage(&mut styled, usage); } - try_help(&mut styled, error.inner.help_flag); + try_help(&mut styled, styles, error.inner.help_flag); styled } } -fn start_error(styled: &mut StyledStr) { - styled.error("error:"); - styled.none(" "); +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) -> bool { +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); @@ -131,30 +152,42 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> (invalid_arg, prior_arg) { if ContextValue::String(invalid_arg.clone()) == *prior_arg { - styled.none("the argument '"); - styled.warning(invalid_arg); - styled.none("' cannot be used multiple times"); + let _ = write!( + styled, + "the argument '{}{invalid_arg}{}' cannot be used multiple times", + invalid.render(), + invalid.render_reset() + ); } else { - styled.none("the argument '"); - styled.warning(invalid_arg); - styled.none("' cannot be used with"); + let _ = write!( + styled, + "the argument '{}{invalid_arg}{}' cannot be used with", + invalid.render(), + invalid.render_reset() + ); match prior_arg { ContextValue::Strings(values) => { - styled.none(":"); + styled.push_str(":"); for v in values { - styled.none("\n"); - styled.none(TAB); - styled.warning(&**v); + let _ = write!( + styled, + "\n{TAB}{}{v}{}", + invalid.render(), + invalid.render_reset() + ); } } ContextValue::String(value) => { - styled.none(" '"); - styled.warning(value); - styled.none("'"); + let _ = write!( + styled, + " '{}{value}{}'", + invalid.render(), + invalid.render_reset() + ); } _ => { - styled.none(" one or more of the other specified arguments"); + styled.push_str(" one or more of the other specified arguments"); } } } @@ -166,9 +199,12 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> ErrorKind::NoEquals => { let invalid_arg = error.get(ContextKind::InvalidArg); if let Some(ContextValue::String(invalid_arg)) = invalid_arg { - styled.none("equal sign is needed when assigning values to '"); - styled.warning(invalid_arg); - styled.none("'"); + let _ = write!( + styled, + "equal sign is needed when assigning values to '{}{invalid_arg}{}'", + invalid.render(), + invalid.render_reset() + ); true } else { false @@ -183,31 +219,46 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> ) = (invalid_arg, invalid_value) { if invalid_value.is_empty() { - styled.none("a value is required for '"); - styled.warning(invalid_arg); - styled.none("' but none was supplied"); + let _ = write!( + styled, + "a value is required for '{}{invalid_arg}{}' but none was supplied", + invalid.render(), + invalid.render_reset() + ); } else { - styled.none("invalid value '"); - styled.none(invalid_value); - styled.none("' for '"); - styled.warning(invalid_arg); - styled.none("'"); + let _ = write!( + styled, + "invalid value '{}{invalid_value}{}' for '{}{invalid_arg}{}'", + invalid.render(), + invalid.render_reset(), + literal.render(), + literal.render_reset() + ); } let possible_values = error.get(ContextKind::ValidValue); if let Some(ContextValue::Strings(possible_values)) = possible_values { if !possible_values.is_empty() { - styled.none("\n"); - styled.none(TAB); - styled.none("[possible values: "); + let _ = write!(styled, "\n{TAB}[possible values: "); if let Some((last, elements)) = possible_values.split_last() { for v in elements { - styled.good(escape(v)); - styled.none(", "); + let _ = write!( + styled, + "{}{}{}, ", + valid.render(), + Escape(v), + valid.render_reset() + ); } - styled.good(escape(last)); + let _ = write!( + styled, + "{}{}{}", + valid.render(), + Escape(last), + valid.render_reset() + ); } - styled.none("]"); + styled.push_str("]"); } } true @@ -218,9 +269,12 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> ErrorKind::InvalidSubcommand => { let invalid_sub = error.get(ContextKind::InvalidSubcommand); if let Some(ContextValue::String(invalid_sub)) = invalid_sub { - styled.none("unrecognized subcommand '"); - styled.warning(invalid_sub); - styled.none("'"); + let _ = write!( + styled, + "unrecognized subcommand '{}{invalid_sub}{}'", + invalid.render(), + invalid.render_reset() + ); true } else { false @@ -229,11 +283,14 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> ErrorKind::MissingRequiredArgument => { let invalid_arg = error.get(ContextKind::InvalidArg); if let Some(ContextValue::Strings(invalid_arg)) = invalid_arg { - styled.none("the following required arguments were not provided:"); + styled.push_str("the following required arguments were not provided:"); for v in invalid_arg { - styled.none("\n"); - styled.none(TAB); - styled.good(&**v); + let _ = write!( + styled, + "\n{TAB}{}{v}{}", + valid.render(), + valid.render_reset() + ); } true } else { @@ -243,24 +300,36 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> ErrorKind::MissingSubcommand => { let invalid_sub = error.get(ContextKind::InvalidSubcommand); if let Some(ContextValue::String(invalid_sub)) = invalid_sub { - styled.none("'"); - styled.warning(invalid_sub); - styled.none("' requires a subcommand but one was not provided"); + let _ = write!( + styled, + "'{}{invalid_sub}{}' requires a subcommand but one was not provided", + invalid.render(), + invalid.render_reset() + ); let possible_values = error.get(ContextKind::ValidSubcommand); if let Some(ContextValue::Strings(possible_values)) = possible_values { if !possible_values.is_empty() { - styled.none("\n"); - styled.none(TAB); - styled.none("[subcommands: "); + let _ = write!(styled, "\n{TAB}[subcommands: "); if let Some((last, elements)) = possible_values.split_last() { for v in elements { - styled.good(escape(v)); - styled.none(", "); + let _ = write!( + styled, + "{}{}{}, ", + valid.render(), + Escape(v), + valid.render_reset() + ); } - styled.good(escape(last)); + let _ = write!( + styled, + "{}{}{}", + valid.render(), + Escape(last), + valid.render_reset() + ); } - styled.none("]"); + styled.push_str("]"); } } @@ -278,11 +347,14 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> Some(ContextValue::String(invalid_value)), ) = (invalid_arg, invalid_value) { - styled.none("unexpected value '"); - styled.warning(invalid_value); - styled.none("' for '"); - styled.warning(invalid_arg); - styled.none("' found; no more were expected"); + 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 @@ -299,12 +371,16 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> ) = (invalid_arg, actual_num_values, min_values) { let were_provided = singular_or_plural(*actual_num_values as usize); - styled.warning(min_values.to_string()); - styled.none(" more values required by '"); - styled.warning(invalid_arg); - styled.none("'; only "); - styled.warning(actual_num_values.to_string()); - styled.none(were_provided); + 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 @@ -318,15 +394,16 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> Some(ContextValue::String(invalid_value)), ) = (invalid_arg, invalid_value) { - styled.none("invalid value '"); - styled.warning(invalid_value); - styled.none("' for '"); - styled.warning(invalid_arg); + 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() { - styled.none("': "); - styled.none(source.to_string()); - } else { - styled.none("'"); + let _ = write!(styled, ": {}", source); } true } else { @@ -344,12 +421,16 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> ) = (invalid_arg, actual_num_values, num_values) { let were_provided = singular_or_plural(*actual_num_values as usize); - styled.warning(num_values.to_string()); - styled.none(" values required for '"); - styled.warning(invalid_arg); - styled.none("' but "); - styled.warning(actual_num_values.to_string()); - styled.none(were_provided); + 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 @@ -358,9 +439,12 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> ErrorKind::UnknownArgument => { let invalid_arg = error.get(ContextKind::InvalidArg); if let Some(ContextValue::String(invalid_arg)) = invalid_arg { - styled.none("unexpected argument '"); - styled.warning(invalid_arg.to_string()); - styled.none("' found"); + let _ = write!( + styled, + "unexpected argument '{}{invalid_arg}{}' found", + invalid.render(), + invalid.render_reset(), + ); true } else { false @@ -376,17 +460,18 @@ fn write_dynamic_context(error: &crate::error::Error, styled: &mut StyledStr) -> 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); - styled.none(message); + 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, get_help_flag(cmd)); + try_help(&mut styled, styles, get_help_flag(cmd)); } styled } @@ -401,7 +486,7 @@ fn singular_or_plural(n: usize) -> &'static str { } fn put_usage(styled: &mut StyledStr, usage: &StyledStr) { - styled.none("\n\n"); + styled.push_str("\n\n"); styled.push_styled(usage); } @@ -415,52 +500,66 @@ pub(crate) fn get_help_flag(cmd: &Command) -> Option<&'static str> { } } -fn try_help(styled: &mut StyledStr, help: Option<&str>) { +fn try_help(styled: &mut StyledStr, styles: &Styles, help: Option<&str>) { if let Some(help) = help { - styled.none("\n\nFor more information, try '"); - styled.literal(help.to_owned()); - styled.none("'.\n"); + 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.none("\n"); + styled.push_str("\n"); } } #[cfg(feature = "error-context")] -fn did_you_mean(styled: &mut StyledStr, context: &str, valid: &ContextValue) { - styled.none(TAB); - styled.good("tip:"); +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 { - styled.none(" a similar "); - styled.none(context); - styled.none(" exists: '"); - styled.good(valid); - styled.none("'"); + 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 { - styled.none(" a similar "); - styled.none(context); - styled.none(" exists: "); + let _ = write!(styled, " a similar {context} exists: ",); } else { - styled.none(" some similar "); - styled.none(context); - styled.none("s exist: "); + let _ = write!(styled, " some similar {context}s exist: ",); } for (i, valid) in valid.iter().enumerate() { if i != 0 { - styled.none(", "); + styled.push_str(", "); } - styled.none("'"); - styled.good(valid); - styled.none("'"); + let _ = write!( + styled, + "'{}{valid}{}'", + styles.get_valid().render(), + styles.get_valid().render_reset() + ); } } } -fn escape(s: impl AsRef<str>) -> String { - let s = s.as_ref(); - if s.contains(char::is_whitespace) { - format!("{s:?}") - } else { - s.to_owned() +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/mod.rs b/vendor/clap_builder/src/error/mod.rs index 52f17bd56..cb3629669 100644 --- a/vendor/clap_builder/src/error/mod.rs +++ b/vendor/clap_builder/src/error/mod.rs @@ -18,6 +18,7 @@ use std::{ // Internal use crate::builder::StyledStr; +use crate::builder::Styles; use crate::output::fmt::Colorizer; use crate::output::fmt::Stream; use crate::parser::features::suggestions; @@ -69,6 +70,7 @@ struct ErrorInner { 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>, @@ -132,6 +134,7 @@ impl<F: ErrorFormatter> Error<F> { message: None, source: None, help_flag: None, + styles: Styles::plain(), color_when: ColorChoice::Never, color_help_when: ColorChoice::Never, backtrace: Backtrace::new(), @@ -144,7 +147,8 @@ impl<F: ErrorFormatter> Error<F> { /// /// Generally, this is used with [`Error::new`] pub fn with_cmd(self, cmd: &Command) -> Self { - self.set_color(cmd.get_color()) + 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)) } @@ -295,6 +299,11 @@ impl<F: ErrorFormatter> Error<F> { 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 @@ -434,18 +443,23 @@ impl<F: ErrorFormatter> Error<F> { name: 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::InvalidSubcommand).with_cmd(cmd); #[cfg(feature = "error-context")] { let mut styled_suggestion = StyledStr::new(); - styled_suggestion.none("to pass '"); - styled_suggestion.warning(&subcmd); - styled_suggestion.none("' as a value, use '"); - styled_suggestion.good(name); - styled_suggestion.good(" -- "); - styled_suggestion.good(&subcmd); - styled_suggestion.none("'"); + let _ = write!( + styled_suggestion, + "to pass '{}{subcmd}{}' as a value, use '{}{name} -- {subcmd}{}'", + invalid.render(), + invalid.render_reset(), + valid.render(), + valid.render_reset() + ); err = err.extend_context_unchecked([ (ContextKind::InvalidSubcommand, ContextValue::String(subcmd)), @@ -661,6 +675,10 @@ impl<F: ErrorFormatter> Error<F> { 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")] @@ -668,12 +686,14 @@ impl<F: ErrorFormatter> Error<F> { let mut suggestions = vec![]; if suggested_trailing_arg { let mut styled_suggestion = StyledStr::new(); - styled_suggestion.none("to pass '"); - styled_suggestion.warning(&arg); - styled_suggestion.none("' as a value, use '"); - styled_suggestion.good("-- "); - styled_suggestion.good(&arg); - styled_suggestion.none("'"); + 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); } @@ -686,12 +706,12 @@ impl<F: ErrorFormatter> Error<F> { match did_you_mean { Some((flag, Some(sub))) => { let mut styled_suggestion = StyledStr::new(); - styled_suggestion.none("'"); - styled_suggestion.good(sub); - styled_suggestion.none(" "); - styled_suggestion.good("--"); - styled_suggestion.good(flag); - styled_suggestion.none("' exists"); + let _ = write!( + styled_suggestion, + "'{}{sub} --{flag}{}' exists", + valid.render(), + valid.render_reset() + ); suggestions.push(styled_suggestion); } Some((flag, None)) => { @@ -718,16 +738,23 @@ impl<F: ErrorFormatter> Error<F> { 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(); - styled_suggestion.none("subcommand '"); - styled_suggestion.good(&arg); - styled_suggestion.none("' exists; to use it, remove the '"); - styled_suggestion.warning("--"); - styled_suggestion.none("' before it"); + 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)), @@ -747,7 +774,7 @@ impl<F: ErrorFormatter> Error<F> { fn formatted(&self) -> Cow<'_, StyledStr> { if let Some(message) = self.inner.message.as_ref() { - message.formatted() + message.formatted(&self.inner.styles) } else { let styled = F::format_error(self); Cow::Owned(styled) @@ -806,7 +833,12 @@ impl Message { let mut message = String::new(); std::mem::swap(s, &mut message); - let styled = format::format_error_message(&message, Some(cmd), usage.as_ref()); + let styled = format::format_error_message( + &message, + cmd.get_styles(), + Some(cmd), + usage.as_ref(), + ); *self = Self::Formatted(styled); } @@ -814,10 +846,10 @@ impl Message { } } - fn formatted(&self) -> Cow<StyledStr> { + fn formatted(&self, styles: &Styles) -> Cow<StyledStr> { match self { Message::Raw(s) => { - let styled = format::format_error_message(s, None, None); + let styled = format::format_error_message(s, styles, None, None); Cow::Owned(styled) } |