diff options
Diffstat (limited to 'vendor/clap_builder/src')
24 files changed, 1074 insertions, 430 deletions
diff --git a/vendor/clap_builder/src/builder/action.rs b/vendor/clap_builder/src/builder/action.rs index becdeda0e..79ee9238e 100644 --- a/vendor/clap_builder/src/builder/action.rs +++ b/vendor/clap_builder/src/builder/action.rs @@ -1,3 +1,6 @@ +#[cfg(debug_assertions)] +use crate::util::AnyValueId; + /// Behavior of arguments when they are encountered while parsing /// /// # Examples @@ -337,9 +340,7 @@ impl ArgAction { } #[cfg(debug_assertions)] - pub(crate) fn value_type_id(&self) -> Option<crate::parser::AnyValueId> { - use crate::parser::AnyValueId; - + pub(crate) fn value_type_id(&self) -> Option<AnyValueId> { match self { Self::Set => None, Self::Append => None, diff --git a/vendor/clap_builder/src/builder/arg.rs b/vendor/clap_builder/src/builder/arg.rs index 574e6fbaf..ce7e02d87 100644 --- a/vendor/clap_builder/src/builder/arg.rs +++ b/vendor/clap_builder/src/builder/arg.rs @@ -17,7 +17,9 @@ use crate::builder::OsStr; use crate::builder::PossibleValue; use crate::builder::Str; use crate::builder::StyledStr; +use crate::builder::Styles; use crate::builder::ValueRange; +use crate::util::AnyValueId; use crate::ArgAction; use crate::Id; use crate::ValueHint; @@ -4004,7 +4006,7 @@ impl Arg { self.value_hint.unwrap_or_else(|| { if self.is_takes_value_set() { let type_id = self.get_value_parser().type_id(); - if type_id == crate::parser::AnyValueId::of::<std::path::PathBuf>() { + if type_id == AnyValueId::of::<std::path::PathBuf>() { ValueHint::AnyPath } else { ValueHint::default() @@ -4270,49 +4272,74 @@ impl Arg { } } - pub(crate) fn stylized(&self, required: Option<bool>) -> StyledStr { + pub(crate) fn stylized(&self, styles: &Styles, required: Option<bool>) -> StyledStr { + use std::fmt::Write as _; + let literal = styles.get_literal(); + let mut styled = StyledStr::new(); // Write the name such --long or -l if let Some(l) = self.get_long() { - styled.literal("--"); - styled.literal(l); + let _ = write!( + styled, + "{}--{l}{}", + literal.render(), + literal.render_reset() + ); } else if let Some(s) = self.get_short() { - styled.literal("-"); - styled.literal(s); + let _ = write!(styled, "{}-{s}{}", literal.render(), literal.render_reset()); } - styled.push_styled(&self.stylize_arg_suffix(required)); + styled.push_styled(&self.stylize_arg_suffix(styles, required)); styled } - pub(crate) fn stylize_arg_suffix(&self, required: Option<bool>) -> StyledStr { + pub(crate) fn stylize_arg_suffix(&self, styles: &Styles, required: Option<bool>) -> StyledStr { + use std::fmt::Write as _; + let literal = styles.get_literal(); + let placeholder = styles.get_placeholder(); let mut styled = StyledStr::new(); let mut need_closing_bracket = false; if self.is_takes_value_set() && !self.is_positional() { let is_optional_val = self.get_min_vals() == 0; - if self.is_require_equals_set() { + let (style, start) = if self.is_require_equals_set() { if is_optional_val { need_closing_bracket = true; - styled.placeholder("[="); + (placeholder, "[=") } else { - styled.literal("="); + (literal, "=") } } else if is_optional_val { need_closing_bracket = true; - styled.placeholder(" ["); + (placeholder, " [") } else { - styled.placeholder(" "); - } + (placeholder, " ") + }; + let _ = write!(styled, "{}{start}{}", style.render(), style.render_reset()); } if self.is_takes_value_set() || self.is_positional() { let required = required.unwrap_or_else(|| self.is_required_set()); let arg_val = self.render_arg_val(required); - styled.placeholder(arg_val); + let _ = write!( + styled, + "{}{arg_val}{}", + placeholder.render(), + placeholder.render_reset() + ); } else if matches!(*self.get_action(), ArgAction::Count) { - styled.placeholder("..."); + let _ = write!( + styled, + "{}...{}", + placeholder.render(), + placeholder.render_reset() + ); } if need_closing_bracket { - styled.placeholder("]"); + let _ = write!( + styled, + "{}]{}", + placeholder.render(), + placeholder.render_reset() + ); } styled @@ -4400,7 +4427,8 @@ impl Eq for Arg {} impl Display for Arg { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - self.stylized(None).fmt(f) + let plain = Styles::plain(); + self.stylized(&plain, None).fmt(f) } } diff --git a/vendor/clap_builder/src/builder/command.rs b/vendor/clap_builder/src/builder/command.rs index 34c04b425..799623581 100644 --- a/vendor/clap_builder/src/builder/command.rs +++ b/vendor/clap_builder/src/builder/command.rs @@ -11,11 +11,13 @@ use std::path::Path; // Internal use crate::builder::app_settings::{AppFlags, AppSettings}; use crate::builder::arg_settings::ArgSettings; +use crate::builder::ext::Extensions; use crate::builder::ArgAction; use crate::builder::IntoResettable; use crate::builder::PossibleValue; use crate::builder::Str; use crate::builder::StyledStr; +use crate::builder::Styles; use crate::builder::{Arg, ArgGroup, ArgPredicate}; use crate::error::ErrorKind; use crate::error::Result as ClapResult; @@ -90,8 +92,6 @@ pub struct Command { usage_name: Option<String>, help_str: Option<StyledStr>, disp_ord: Option<usize>, - term_w: Option<usize>, - max_w: Option<usize>, #[cfg(feature = "help")] template: Option<StyledStr>, settings: AppFlags, @@ -105,6 +105,7 @@ pub struct Command { subcommand_heading: Option<Str>, external_value_parser: Option<super::ValueParser>, long_help_exists: bool, + app_ext: Extensions, } /// # Basic API @@ -1080,6 +1081,30 @@ impl Command { } } + /// Sets the [`Styles`] for terminal output + /// + /// **NOTE:** This choice is propagated to all child subcommands. + /// + /// **NOTE:** Default behaviour is [`Styles::default`]. + /// + /// # Examples + /// + /// ```no_run + /// # use clap_builder as clap; + /// # use clap::{Command, ColorChoice, builder::Styles}; + /// Command::new("myprog") + /// .styles(Styles::styled().usage(Default::default())) + /// .get_matches(); + /// ``` + #[cfg(feature = "color")] + #[inline] + #[must_use] + #[cfg(feature = "unstable-styles")] + pub fn styles(mut self, styles: Styles) -> Self { + self.app_ext.set(styles); + self + } + /// Sets the terminal width at which to wrap help messages. /// /// Using `0` will ignore terminal widths and use source formatting. @@ -1104,7 +1129,7 @@ impl Command { #[must_use] #[cfg(any(not(feature = "unstable-v5"), feature = "wrap_help"))] pub fn term_width(mut self, width: usize) -> Self { - self.term_w = Some(width); + self.app_ext.set(TermWidth(width)); self } @@ -1131,8 +1156,8 @@ impl Command { #[inline] #[must_use] #[cfg(any(not(feature = "unstable-v5"), feature = "wrap_help"))] - pub fn max_term_width(mut self, w: usize) -> Self { - self.max_w = Some(w); + pub fn max_term_width(mut self, width: usize) -> Self { + self.app_ext.set(MaxTermWidth(width)); self } @@ -1912,7 +1937,7 @@ impl Command { self } - /// Change the starting value for assigning future display orders for ags. + /// Change the starting value for assigning future display orders for args. /// /// This will be used for any arg that hasn't had [`Arg::display_order`] called. #[inline] @@ -3338,6 +3363,12 @@ impl Command { } } + /// Return the current `Styles` for the `Command` + #[inline] + pub fn get_styles(&self) -> &Styles { + self.app_ext.get().unwrap_or_default() + } + /// Iterate through the set of subcommands, getting a reference to each. #[inline] pub fn get_subcommands(&self) -> impl Iterator<Item = &Command> { @@ -3720,12 +3751,12 @@ impl Command { #[cfg(feature = "help")] pub(crate) fn get_term_width(&self) -> Option<usize> { - self.term_w + self.app_ext.get::<TermWidth>().map(|e| e.0) } #[cfg(feature = "help")] pub(crate) fn get_max_term_width(&self) -> Option<usize> { - self.max_w + self.app_ext.get::<MaxTermWidth>().map(|e| e.0) } pub(crate) fn get_keymap(&self) -> &MKeyMap { @@ -4190,8 +4221,7 @@ impl Command { sc.settings = sc.settings | self.g_settings; sc.g_settings = sc.g_settings | self.g_settings; - sc.term_w = self.term_w; - sc.max_w = self.max_w; + sc.app_ext.update(&self.app_ext); } } @@ -4322,9 +4352,9 @@ impl Command { .collect::<Vec<_>>() .join("|"); let mut styled = StyledStr::new(); - styled.none("<"); - styled.none(g_string); - styled.none(">"); + styled.push_str("<"); + styled.push_string(g_string); + styled.push_str(">"); styled } } @@ -4612,8 +4642,6 @@ impl Default for Command { usage_name: Default::default(), help_str: Default::default(), disp_ord: Default::default(), - term_w: Default::default(), - max_w: Default::default(), #[cfg(feature = "help")] template: Default::default(), settings: Default::default(), @@ -4627,6 +4655,7 @@ impl Default for Command { subcommand_heading: Default::default(), external_value_parser: Default::default(), long_help_exists: false, + app_ext: Default::default(), } } } @@ -4651,6 +4680,18 @@ impl fmt::Display for Command { } } +pub(crate) trait AppTag: crate::builder::ext::Extension {} + +#[derive(Default, Copy, Clone, Debug)] +struct TermWidth(usize); + +impl AppTag for TermWidth {} + +#[derive(Default, Copy, Clone, Debug)] +struct MaxTermWidth(usize); + +impl AppTag for MaxTermWidth {} + fn two_elements_of<I, T>(mut iter: I) -> Option<(T, T)> where I: Iterator<Item = T>, diff --git a/vendor/clap_builder/src/builder/ext.rs b/vendor/clap_builder/src/builder/ext.rs new file mode 100644 index 000000000..2fb0d96b9 --- /dev/null +++ b/vendor/clap_builder/src/builder/ext.rs @@ -0,0 +1,216 @@ +use crate::util::AnyValueId; +use crate::util::FlatMap; + +#[derive(Default, Clone, Debug)] +pub(crate) struct Extensions { + extensions: FlatMap<AnyValueId, BoxedExtension>, +} + +impl Extensions { + #[allow(dead_code)] + pub(crate) fn get<T: Extension>(&self) -> Option<&T> { + let id = AnyValueId::of::<T>(); + self.extensions.get(&id).map(|e| e.as_ref::<T>()) + } + + #[allow(dead_code)] + pub(crate) fn get_mut<T: Extension>(&mut self) -> Option<&mut T> { + let id = AnyValueId::of::<T>(); + self.extensions.get_mut(&id).map(|e| e.as_mut::<T>()) + } + + #[allow(dead_code)] + pub(crate) fn get_or_insert_default<T: Extension + Default>(&mut self) -> &mut T { + let id = AnyValueId::of::<T>(); + self.extensions + .entry(id) + .or_insert_with(|| BoxedExtension::new(T::default())) + .as_mut::<T>() + } + + #[allow(dead_code)] + pub(crate) fn set<T: Extension + Into<BoxedEntry>>(&mut self, tagged: T) -> bool { + let BoxedEntry { id, value } = tagged.into(); + self.extensions.insert(id, value).is_some() + } + + #[allow(dead_code)] + pub(crate) fn remove<T: Extension>(&mut self) -> Option<Box<dyn Extension>> { + let id = AnyValueId::of::<T>(); + self.extensions.remove(&id).map(BoxedExtension::into_inner) + } + + pub(crate) fn update(&mut self, other: &Self) { + for (key, value) in other.extensions.iter() { + self.extensions.insert(*key, value.clone()); + } + } +} + +/// Supports conversion to `Any`. Traits to be extended by `impl_downcast!` must extend `Extension`. +pub(crate) trait Extension: std::fmt::Debug + Send + Sync + 'static { + /// Convert `Box<dyn Trait>` (where `Trait: Extension`) to `Box<dyn Any>`. + /// + /// `Box<dyn Any>` can /// then be further `downcast` into + /// `Box<ConcreteType>` where `ConcreteType` implements `Trait`. + fn into_any(self: Box<Self>) -> Box<dyn std::any::Any>; + /// Clone `&Box<dyn Trait>` (where `Trait: Extension`) to `Box<dyn Extension>`. + /// + /// `Box<dyn Any>` can /// then be further `downcast` into + // `Box<ConcreteType>` where `ConcreteType` implements `Trait`. + fn clone_extension(&self) -> Box<dyn Extension>; + /// Convert `&Trait` (where `Trait: Extension`) to `&Any`. + /// + /// This is needed since Rust cannot /// generate `&Any`'s vtable from + /// `&Trait`'s. + fn as_any(&self) -> &dyn std::any::Any; + /// Convert `&mut Trait` (where `Trait: Extension`) to `&Any`. + /// + /// This is needed since Rust cannot /// generate `&mut Any`'s vtable from + /// `&mut Trait`'s. + fn as_any_mut(&mut self) -> &mut dyn std::any::Any; +} + +impl<T> Extension for T +where + T: Clone + std::fmt::Debug + Send + Sync + 'static, +{ + fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> { + self + } + fn clone_extension(&self) -> Box<dyn Extension> { + Box::new(self.clone()) + } + fn as_any(&self) -> &dyn std::any::Any { + self + } + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } +} + +impl Clone for Box<dyn Extension> { + fn clone(&self) -> Self { + self.as_ref().clone_extension() + } +} + +#[derive(Clone)] +#[repr(transparent)] +struct BoxedExtension(Box<dyn Extension>); + +impl BoxedExtension { + fn new<T: Extension>(inner: T) -> Self { + Self(Box::new(inner)) + } + + fn into_inner(self) -> Box<dyn Extension> { + self.0 + } + + fn as_ref<T: Extension>(&self) -> &T { + self.0.as_ref().as_any().downcast_ref::<T>().unwrap() + } + + fn as_mut<T: Extension>(&mut self) -> &mut T { + self.0.as_mut().as_any_mut().downcast_mut::<T>().unwrap() + } +} + +impl std::fmt::Debug for BoxedExtension { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + self.0.fmt(f) + } +} + +#[derive(Clone)] +pub(crate) struct BoxedEntry { + id: AnyValueId, + value: BoxedExtension, +} + +impl BoxedEntry { + pub(crate) fn new(r: impl Extension) -> Self { + let id = AnyValueId::from(&r); + let value = BoxedExtension::new(r); + BoxedEntry { id, value } + } +} + +impl<R: Extension> From<R> for BoxedEntry { + fn from(inner: R) -> Self { + BoxedEntry::new(inner) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[derive(Default, Copy, Clone, Debug, PartialEq, Eq)] + struct Number(usize); + + #[test] + fn get() { + let mut ext = Extensions::default(); + ext.set(Number(10)); + assert_eq!(ext.get::<Number>(), Some(&Number(10))); + } + + #[test] + fn get_mut() { + let mut ext = Extensions::default(); + ext.set(Number(10)); + *ext.get_mut::<Number>().unwrap() = Number(20); + assert_eq!(ext.get::<Number>(), Some(&Number(20))); + } + + #[test] + fn get_or_insert_default_empty() { + let mut ext = Extensions::default(); + assert_eq!(ext.get_or_insert_default::<Number>(), &Number(0)); + } + + #[test] + fn get_or_insert_default_full() { + let mut ext = Extensions::default(); + ext.set(Number(10)); + assert_eq!(ext.get_or_insert_default::<Number>(), &Number(10)); + } + + #[test] + fn set() { + let mut ext = Extensions::default(); + assert!(!ext.set(Number(10))); + assert_eq!(ext.get::<Number>(), Some(&Number(10))); + assert!(ext.set(Number(20))); + assert_eq!(ext.get::<Number>(), Some(&Number(20))); + } + + #[test] + fn reset() { + let mut ext = Extensions::default(); + assert_eq!(ext.get::<Number>(), None); + + assert!(ext.remove::<Number>().is_none()); + assert_eq!(ext.get::<Number>(), None); + + assert!(!ext.set(Number(10))); + assert_eq!(ext.get::<Number>(), Some(&Number(10))); + + assert!(ext.remove::<Number>().is_some()); + assert_eq!(ext.get::<Number>(), None); + } + + #[test] + fn update() { + let mut ext = Extensions::default(); + assert_eq!(ext.get::<Number>(), None); + + let mut new = Extensions::default(); + assert!(!new.set(Number(10))); + + ext.update(&new); + assert_eq!(ext.get::<Number>(), Some(&Number(10))); + } +} diff --git a/vendor/clap_builder/src/builder/mod.rs b/vendor/clap_builder/src/builder/mod.rs index 098ad576e..495c84587 100644 --- a/vendor/clap_builder/src/builder/mod.rs +++ b/vendor/clap_builder/src/builder/mod.rs @@ -7,6 +7,7 @@ mod arg_group; mod arg_predicate; mod arg_settings; mod command; +mod ext; mod os_str; mod possible_value; mod range; @@ -34,6 +35,8 @@ pub use range::ValueRange; pub use resettable::IntoResettable; pub use resettable::Resettable; pub use styled_str::StyledStr; +#[cfg(feature = "unstable-styles")] +pub use styled_str::Styles; pub use value_hint::ValueHint; pub use value_parser::_AutoValueParser; pub use value_parser::via_prelude; @@ -58,3 +61,6 @@ pub use value_parser::_AnonymousValueParser; pub(crate) use self::str::Inner as StrInner; pub(crate) use action::CountType; pub(crate) use arg_settings::{ArgFlags, ArgSettings}; +pub(crate) use command::AppTag; +#[cfg(not(feature = "unstable-styles"))] +pub(crate) use styled_str::Styles; diff --git a/vendor/clap_builder/src/builder/styled_str.rs b/vendor/clap_builder/src/builder/styled_str.rs index 94c838aaa..e4acc63ff 100644 --- a/vendor/clap_builder/src/builder/styled_str.rs +++ b/vendor/clap_builder/src/builder/styled_str.rs @@ -33,39 +33,14 @@ impl StyledStr { self.0.as_str() } - pub(crate) fn header(&mut self, msg: impl Into<String>) { - self.stylize(Style::Header, msg.into()); - } - - pub(crate) fn literal(&mut self, msg: impl Into<String>) { - self.stylize(Style::Literal, msg.into()); - } - - pub(crate) fn placeholder(&mut self, msg: impl Into<String>) { - self.stylize(Style::Placeholder, msg.into()); - } - - #[cfg_attr(not(feature = "error-context"), allow(dead_code))] - pub(crate) fn good(&mut self, msg: impl Into<String>) { - self.stylize(Style::Good, msg.into()); - } - - #[cfg_attr(not(feature = "error-context"), allow(dead_code))] - pub(crate) fn warning(&mut self, msg: impl Into<String>) { - self.stylize(Style::Warning, msg.into()); - } - - pub(crate) fn error(&mut self, msg: impl Into<String>) { - self.stylize(Style::Error, msg.into()); - } - - #[allow(dead_code)] - pub(crate) fn hint(&mut self, msg: impl Into<String>) { - self.stylize(Style::Hint, msg.into()); + /// May allow the compiler to consolidate the `Drop`s for `msg`, reducing code size compared to + /// `styled.push_str(&msg)` + pub(crate) fn push_string(&mut self, msg: String) { + self.0.push_str(&msg); } - pub(crate) fn none(&mut self, msg: impl Into<String>) { - self.0.push_str(&msg.into()); + pub(crate) fn push_str(&mut self, msg: &str) { + self.0.push_str(msg); } pub(crate) fn trim(&mut self) { @@ -122,21 +97,6 @@ impl StyledStr { self.0 = new; } - #[cfg(feature = "color")] - fn stylize(&mut self, style: Style, msg: String) { - if !msg.is_empty() { - use std::fmt::Write as _; - - let style = style.as_style(); - let _ = write!(self.0, "{}{}{}", style.render(), msg, style.render_reset()); - } - } - - #[cfg(not(feature = "color"))] - fn stylize(&mut self, _style: Style, msg: String) { - self.0.push_str(&msg); - } - #[inline(never)] #[cfg(feature = "help")] pub(crate) fn display_width(&self) -> usize { @@ -194,7 +154,7 @@ impl From<std::string::String> for StyledStr { impl From<&'_ std::string::String> for StyledStr { fn from(name: &'_ std::string::String) -> Self { let mut styled = StyledStr::new(); - styled.none(name); + styled.push_str(name); styled } } @@ -202,7 +162,7 @@ impl From<&'_ std::string::String> for StyledStr { impl From<&'static str> for StyledStr { fn from(name: &'static str) -> Self { let mut styled = StyledStr::new(); - styled.none(name); + styled.push_str(name); styled } } @@ -238,28 +198,163 @@ impl std::fmt::Display for StyledStr { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub(crate) enum Style { - Header, - Literal, - Placeholder, - Good, - Warning, - Error, - Hint, +/// Terminal styling definitions +#[derive(Clone, Debug)] +#[allow(missing_copy_implementations)] // Large enough type that I want an explicit `clone()` for now +pub struct Styles { + header: anstyle::Style, + error: anstyle::Style, + usage: anstyle::Style, + literal: anstyle::Style, + placeholder: anstyle::Style, + valid: anstyle::Style, + invalid: anstyle::Style, } -impl Style { - #[cfg(feature = "color")] - fn as_style(&self) -> anstyle::Style { - match self { - Style::Header => (anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE).into(), - Style::Literal => anstyle::Effects::BOLD.into(), - Style::Placeholder => anstyle::Style::default(), - Style::Good => anstyle::AnsiColor::Green.on_default(), - Style::Warning => anstyle::AnsiColor::Yellow.on_default(), - Style::Error => anstyle::AnsiColor::Red.on_default() | anstyle::Effects::BOLD, - Style::Hint => anstyle::Effects::DIMMED.into(), +impl Styles { + /// No terminal styling + pub const fn plain() -> Self { + Self { + header: anstyle::Style::new(), + error: anstyle::Style::new(), + usage: anstyle::Style::new(), + literal: anstyle::Style::new(), + placeholder: anstyle::Style::new(), + valid: anstyle::Style::new(), + invalid: anstyle::Style::new(), + } + } + + /// Default terminal styling + pub const fn styled() -> Self { + #[cfg(feature = "color")] + { + Self { + header: anstyle::Style::new().bold().underline(), + error: anstyle::Style::new() + .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Red))) + .bold(), + usage: anstyle::Style::new().bold().underline(), + literal: anstyle::Style::new().bold(), + placeholder: anstyle::Style::new(), + valid: anstyle::Style::new() + .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Green))), + invalid: anstyle::Style::new() + .fg_color(Some(anstyle::Color::Ansi(anstyle::AnsiColor::Yellow))), + } + } + #[cfg(not(feature = "color"))] + { + Self::plain() } } + + /// General Heading style, e.g. [`help_heading`][crate::Arg::help_heading] + #[inline] + pub const fn header(mut self, style: anstyle::Style) -> Self { + self.header = style; + self + } + + /// Error heading + #[inline] + pub const fn error(mut self, style: anstyle::Style) -> Self { + self.error = style; + self + } + + /// Usage heading + #[inline] + pub const fn usage(mut self, style: anstyle::Style) -> Self { + self.usage = style; + self + } + + /// Literal command-line syntax, e.g. `--help` + #[inline] + pub const fn literal(mut self, style: anstyle::Style) -> Self { + self.literal = style; + self + } + + /// Descriptions within command-line syntax, e.g. [`value_name`][crate::Arg::value_name] + #[inline] + pub const fn placeholder(mut self, style: anstyle::Style) -> Self { + self.placeholder = style; + self + } + + /// Highlight suggested usage + #[inline] + pub const fn valid(mut self, style: anstyle::Style) -> Self { + self.valid = style; + self + } + + /// Highlight invalid usage + #[inline] + pub const fn invalid(mut self, style: anstyle::Style) -> Self { + self.invalid = style; + self + } +} + +/// Reflection +impl Styles { + /// General Heading style, e.g. [`help_heading`][crate::Arg::help_heading] + #[inline(always)] + pub const fn get_header(&self) -> &anstyle::Style { + &self.header + } + + /// Error heading + #[inline(always)] + pub const fn get_error(&self) -> &anstyle::Style { + &self.error + } + + /// Usage heading + #[inline(always)] + pub const fn get_usage(&self) -> &anstyle::Style { + &self.usage + } + + /// Literal command-line syntax, e.g. `--help` + #[inline(always)] + pub const fn get_literal(&self) -> &anstyle::Style { + &self.literal + } + + /// Descriptions within command-line syntax, e.g. [`value_name`][crate::Arg::value_name] + #[inline(always)] + pub const fn get_placeholder(&self) -> &anstyle::Style { + &self.placeholder + } + + /// Highlight suggested usage + #[inline(always)] + pub const fn get_valid(&self) -> &anstyle::Style { + &self.valid + } + + /// Highlight invalid usage + #[inline(always)] + pub const fn get_invalid(&self) -> &anstyle::Style { + &self.invalid + } +} + +impl super::AppTag for Styles {} + +impl Default for Styles { + fn default() -> Self { + Self::styled() + } +} + +impl Default for &'_ Styles { + fn default() -> Self { + const STYLES: Styles = Styles::styled(); + &STYLES + } } diff --git a/vendor/clap_builder/src/builder/value_parser.rs b/vendor/clap_builder/src/builder/value_parser.rs index d4a1a7ab7..24631ce7c 100644 --- a/vendor/clap_builder/src/builder/value_parser.rs +++ b/vendor/clap_builder/src/builder/value_parser.rs @@ -1,8 +1,8 @@ use std::convert::TryInto; use std::ops::RangeBounds; -use crate::parser::AnyValue; -use crate::parser::AnyValueId; +use crate::util::AnyValue; +use crate::util::AnyValueId; /// Parse/validate argument values /// 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) } diff --git a/vendor/clap_builder/src/lib.rs b/vendor/clap_builder/src/lib.rs index a8c1201e0..97c32c141 100644 --- a/vendor/clap_builder/src/lib.rs +++ b/vendor/clap_builder/src/lib.rs @@ -16,6 +16,10 @@ clippy::single_char_pattern )] #![forbid(unsafe_code)] +// Wanting consistency in our calls +#![allow(clippy::write_with_newline)] +// Gets in the way of logging +#![allow(clippy::let_and_return)] // HACK https://github.com/rust-lang/rust-clippy/issues/7290 #![allow(clippy::single_component_path_imports)] #![allow(clippy::branches_sharing_code)] diff --git a/vendor/clap_builder/src/macros.rs b/vendor/clap_builder/src/macros.rs index 82a881198..59135e212 100644 --- a/vendor/clap_builder/src/macros.rs +++ b/vendor/clap_builder/src/macros.rs @@ -628,12 +628,13 @@ macro_rules! impl_settings { #[cfg(feature = "debug")] macro_rules! debug { ($($arg:tt)*) => ({ - let prefix = format!("[{:>w$}] \t", module_path!(), w = 28); + use std::fmt::Write as _; + let hint = anstyle::Style::new().dimmed(); + + let module_path = module_path!(); let body = format!($($arg)*); let mut styled = $crate::builder::StyledStr::new(); - styled.hint(prefix); - styled.hint(body); - styled.none("\n"); + let _ = write!(styled, "{}[{module_path:>28}]{body}{}\n", hint.render(), hint.render_reset()); let color = $crate::output::fmt::Colorizer::new($crate::output::fmt::Stream::Stderr, $crate::ColorChoice::Auto).with_content(styled); let _ = color.print(); }) diff --git a/vendor/clap_builder/src/output/help.rs b/vendor/clap_builder/src/output/help.rs index 4921f5f71..410616eb1 100644 --- a/vendor/clap_builder/src/output/help.rs +++ b/vendor/clap_builder/src/output/help.rs @@ -33,5 +33,5 @@ pub(crate) fn write_help(writer: &mut StyledStr, cmd: &Command, usage: &Usage<'_ // Remove any extra lines caused by book keeping writer.trim(); // Ensure there is still a trailing newline - writer.none("\n"); + writer.push_str("\n"); } diff --git a/vendor/clap_builder/src/output/help_template.rs b/vendor/clap_builder/src/output/help_template.rs index cea9a7687..86a61169c 100644 --- a/vendor/clap_builder/src/output/help_template.rs +++ b/vendor/clap_builder/src/output/help_template.rs @@ -1,3 +1,8 @@ +// HACK: for rust 1.64 (1.68 doesn't need this since this is in lib.rs) +// +// Wanting consistency in our calls +#![allow(clippy::write_with_newline)] + // Std use std::borrow::Cow; use std::cmp; @@ -7,6 +12,7 @@ use std::usize; use crate::builder::PossibleValue; use crate::builder::Str; use crate::builder::StyledStr; +use crate::builder::Styles; use crate::builder::{Arg, Command}; use crate::output::display_width; use crate::output::wrap; @@ -74,6 +80,7 @@ const DEFAULT_NO_ARGS_TEMPLATE: &str = "\ pub(crate) struct HelpTemplate<'cmd, 'writer> { writer: &'writer mut StyledStr, cmd: &'cmd Command, + styles: &'cmd Styles, usage: &'cmd Usage<'cmd>, next_line_help: bool, term_w: usize, @@ -112,6 +119,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { HelpTemplate { writer, cmd, + styles: cmd.get_styles(), usage, next_line_help, term_w, @@ -126,10 +134,11 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { /// [`Command::help_template`]: Command::help_template() pub(crate) fn write_templated_help(&mut self, template: &str) { debug!("HelpTemplate::write_templated_help"); + use std::fmt::Write as _; let mut parts = template.split('{'); if let Some(first) = parts.next() { - self.none(first); + self.writer.push_str(first); } for part in parts { if let Some((tag, rest)) = part.split_once('}') { @@ -163,7 +172,12 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { self.write_about(true, true); } "usage-heading" => { - self.header("Usage:"); + let _ = write!( + self.writer, + "{}Usage:{}", + self.styles.get_usage().render(), + self.styles.get_usage().render_reset() + ); } "usage" => { self.writer.push_styled( @@ -193,7 +207,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { self.write_subcommands(self.cmd); } "tab" => { - self.none(TAB); + self.writer.push_str(TAB); } "after-help" => { self.write_after_help(); @@ -202,12 +216,10 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { self.write_before_help(); } _ => { - self.none("{"); - self.none(tag); - self.none("}"); + let _ = write!(self.writer, "{{{tag}}}"); } } - self.none(rest); + self.writer.push_str(rest); } } } @@ -227,7 +239,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { .replace("{n}", "\n"), self.term_w, ); - self.none(&display_name); + self.writer.push_string(display_name); } /// Writes binary name of a Parser Object to the wrapped stream. @@ -245,7 +257,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { } else { wrap(&self.cmd.get_name().replace("{n}", "\n"), self.term_w) }; - self.none(&bin_name); + self.writer.push_string(bin_name); } fn write_version(&mut self) { @@ -254,18 +266,18 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { .get_version() .or_else(|| self.cmd.get_long_version()); if let Some(output) = version { - self.none(wrap(output, self.term_w)); + self.writer.push_string(wrap(output, self.term_w)); } } fn write_author(&mut self, before_new_line: bool, after_new_line: bool) { if let Some(author) = self.cmd.get_author() { if before_new_line { - self.none("\n"); + self.writer.push_str("\n"); } - self.none(wrap(author, self.term_w)); + self.writer.push_string(wrap(author, self.term_w)); if after_new_line { - self.none("\n"); + self.writer.push_str("\n"); } } } @@ -278,14 +290,14 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { }; if let Some(output) = about { if before_new_line { - self.none("\n"); + self.writer.push_str("\n"); } let mut output = output.clone(); output.replace_newline_var(); output.wrap(self.term_w); self.writer.push_styled(&output); if after_new_line { - self.none("\n"); + self.writer.push_str("\n"); } } } @@ -304,7 +316,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { output.replace_newline_var(); output.wrap(self.term_w); self.writer.push_styled(&output); - self.none("\n\n"); + self.writer.push_str("\n\n"); } } @@ -318,7 +330,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { self.cmd.get_after_help() }; if let Some(output) = after_help { - self.none("\n\n"); + self.writer.push_str("\n\n"); let mut output = output.clone(); output.replace_newline_var(); output.wrap(self.term_w); @@ -333,6 +345,9 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { /// including titles of a Parser Object to the wrapped stream. pub(crate) fn write_all_args(&mut self) { debug!("HelpTemplate::write_all_args"); + use std::fmt::Write as _; + let header = &self.styles.get_header(); + let pos = self .cmd .get_positionals() @@ -357,39 +372,52 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { if subcmds { if !first { - self.none("\n\n"); + self.writer.push_str("\n\n"); } first = false; let default_help_heading = Str::from("Commands"); - self.header( - self.cmd - .get_subcommand_help_heading() - .unwrap_or(&default_help_heading), + let help_heading = self + .cmd + .get_subcommand_help_heading() + .unwrap_or(&default_help_heading); + let _ = write!( + self.writer, + "{}{help_heading}:{}\n", + header.render(), + header.render_reset() ); - self.header(":"); - self.none("\n"); self.write_subcommands(self.cmd); } if !pos.is_empty() { if !first { - self.none("\n\n"); + self.writer.push_str("\n\n"); } first = false; // Write positional args if any - self.header("Arguments:"); - self.none("\n"); + let help_heading = "Arguments"; + let _ = write!( + self.writer, + "{}{help_heading}:{}\n", + header.render(), + header.render_reset() + ); self.write_args(&pos, "Arguments", positional_sort_key); } if !non_pos.is_empty() { if !first { - self.none("\n\n"); + self.writer.push_str("\n\n"); } first = false; - self.header("Options:"); - self.none("\n"); + let help_heading = "Options"; + let _ = write!( + self.writer, + "{}{help_heading}:{}\n", + header.render(), + header.render_reset() + ); self.write_args(&non_pos, "Options", option_sort_key); } if !custom_headings.is_empty() { @@ -408,12 +436,15 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { if !args.is_empty() { if !first { - self.none("\n\n"); + self.writer.push_str("\n\n"); } first = false; - self.header(heading); - self.header(":"); - self.none("\n"); + let _ = write!( + self.writer, + "{}{heading}:{}\n", + header.render(), + header.render_reset() + ); self.write_args(&args, heading, option_sort_key); } } @@ -451,9 +482,9 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { for (i, (_, arg)) in ord_v.iter().enumerate() { if i != 0 { - self.none("\n"); + self.writer.push_str("\n"); if next_line_help && self.use_long { - self.none("\n"); + self.writer.push_str("\n"); } } self.write_arg(arg, next_line_help, longest); @@ -464,10 +495,11 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { fn write_arg(&mut self, arg: &Arg, next_line_help: bool, longest: usize) { let spec_vals = &self.spec_vals(arg); - self.none(TAB); + self.writer.push_str(TAB); self.short(arg); self.long(arg); - self.writer.push_styled(&arg.stylize_arg_suffix(None)); + self.writer + .push_styled(&arg.stylize_arg_suffix(self.styles, None)); self.align_to_about(arg, next_line_help, longest); let about = if self.use_long { @@ -486,22 +518,37 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { /// Writes argument's short command to the wrapped stream. fn short(&mut self, arg: &Arg) { debug!("HelpTemplate::short"); + use std::fmt::Write as _; + let literal = &self.styles.get_literal(); if let Some(s) = arg.get_short() { - self.literal(format!("-{s}")); + let _ = write!( + self.writer, + "{}-{s}{}", + literal.render(), + literal.render_reset() + ); } else if arg.get_long().is_some() { - self.none(" "); + self.writer.push_str(" "); } } /// Writes argument's long command to the wrapped stream. fn long(&mut self, arg: &Arg) { debug!("HelpTemplate::long"); + use std::fmt::Write as _; + let literal = &self.styles.get_literal(); + if let Some(long) = arg.get_long() { if arg.get_short().is_some() { - self.none(", "); + self.writer.push_str(", "); } - self.literal(format!("--{long}")); + let _ = write!( + self.writer, + "{}--{long}{}", + literal.render(), + literal.render_reset() + ); } } @@ -513,9 +560,10 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { next_line_help, longest ); - if self.use_long || next_line_help { + let padding = if self.use_long || next_line_help { // long help prints messages on the next line so it doesn't need to align text debug!("HelpTemplate::align_to_about: printing long help so skip alignment"); + 0 } else if !arg.is_positional() { let self_len = display_width(&arg.to_string()); // Since we're writing spaces from the tab point we first need to know if we @@ -533,7 +581,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { self_len, spcs ); - self.spaces(spcs); + spcs } else { let self_len = display_width(&arg.to_string()); let padding = TAB_WIDTH; @@ -543,8 +591,10 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { self_len, spcs ); - self.spaces(spcs); - } + spcs + }; + + self.write_padding(padding); } /// Writes argument's help to the wrapped stream. @@ -557,13 +607,15 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { longest: usize, ) { debug!("HelpTemplate::help"); + use std::fmt::Write as _; + let literal = &self.styles.get_literal(); // Is help on next line, if so then indent if next_line_help { debug!("HelpTemplate::help: Next Line...{:?}", next_line_help); - self.none("\n"); - self.none(TAB); - self.none(NEXT_LINE_INDENT); + self.writer.push_str("\n"); + self.writer.push_str(TAB); + self.writer.push_str(NEXT_LINE_INDENT); } let spaces = if next_line_help { @@ -585,9 +637,9 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { } else { " " }; - help.none(sep); + help.push_str(sep); } - help.none(spec_vals); + help.push_str(spec_vals); } let avail_chars = self.term_w.saturating_sub(spaces); debug!( @@ -612,11 +664,6 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { "HelpTemplate::help: Found possible vals...{:?}", possible_vals ); - if !help_is_empty { - self.none("\n\n"); - self.spaces(spaces); - } - self.none("Possible values:"); let longest = possible_vals .iter() .filter_map(|f| f.get_visible_quoted_name().map(|name| display_width(&name))) @@ -641,21 +688,29 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { }; let trailing_indent = self.get_spaces(trailing_indent); + if !help_is_empty { + let _ = write!(self.writer, "\n\n{:spaces$}", ""); + } + self.writer.push_str("Possible values:"); for pv in possible_vals.iter().filter(|pv| !pv.is_hide_set()) { - self.none("\n"); - self.spaces(spaces); - self.none("- "); - self.literal(pv.get_name()); + let name = pv.get_name(); + let _ = write!( + self.writer, + "\n{:spaces$}- {}{name}{}", + "", + literal.render(), + literal.render_reset() + ); if let Some(help) = pv.get_help() { debug!("HelpTemplate::help: Possible Value help"); if possible_value_new_line { - self.none(":\n"); - self.spaces(trailing_indent.len()); + let padding = trailing_indent.len(); + let _ = write!(self.writer, ":\n{:padding$}", ""); } else { - self.none(": "); // To align help messages - self.spaces(longest - display_width(pv.get_name())); + let padding = longest - display_width(pv.get_name()); + let _ = write!(self.writer, ": {:padding$}", ""); } let avail_chars = if self.term_w > trailing_indent.len() { @@ -801,24 +856,13 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { spec_vals.join(connector) } - fn header<T: Into<String>>(&mut self, msg: T) { - self.writer.header(msg); - } - - fn literal<T: Into<String>>(&mut self, msg: T) { - self.writer.literal(msg); - } - - fn none<T: Into<String>>(&mut self, msg: T) { - self.writer.none(msg); - } - fn get_spaces(&self, n: usize) -> String { " ".repeat(n) } - fn spaces(&mut self, n: usize) { - self.none(self.get_spaces(n)); + fn write_padding(&mut self, amount: usize) { + use std::fmt::Write as _; + let _ = write!(self.writer, "{:amount$}", ""); } } @@ -827,6 +871,9 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { /// Writes help for subcommands of a Parser Object to the wrapped stream. fn write_subcommands(&mut self, cmd: &Command) { debug!("HelpTemplate::write_subcommands"); + use std::fmt::Write as _; + let literal = &self.styles.get_literal(); + // The shortest an arg can legally be is 2 (i.e. '-x') let mut longest = 2; let mut ord_v = Vec::new(); @@ -835,14 +882,28 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { .filter(|subcommand| should_show_subcommand(subcommand)) { let mut styled = StyledStr::new(); - styled.literal(subcommand.get_name()); + let name = subcommand.get_name(); + let _ = write!( + styled, + "{}{name}{}", + literal.render(), + literal.render_reset() + ); if let Some(short) = subcommand.get_short_flag() { - styled.none(", "); - styled.literal(format!("-{short}")); + let _ = write!( + styled, + ", {}-{short}{}", + literal.render(), + literal.render_reset() + ); } if let Some(long) = subcommand.get_long_flag() { - styled.none(", "); - styled.literal(format!("--{long}")); + let _ = write!( + styled, + ", {}--{long}{}", + literal.render(), + literal.render_reset() + ); } longest = longest.max(styled.display_width()); ord_v.push((subcommand.get_display_order(), styled, subcommand)); @@ -858,7 +919,7 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { if first { first = false; } else { - self.none("\n"); + self.writer.push_str("\n"); } self.write_subcommand(sc_str, sc, next_line_help, longest); } @@ -942,12 +1003,12 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { /// Writes subcommand to the wrapped stream. fn subcmd(&mut self, sc_str: StyledStr, next_line_help: bool, longest: usize) { - let width = sc_str.display_width(); - - self.none(TAB); + self.writer.push_str(TAB); self.writer.push_styled(&sc_str); if !next_line_help { - self.spaces(longest + TAB_WIDTH - width); + let width = sc_str.display_width(); + let padding = longest + TAB_WIDTH - width; + self.write_padding(padding); } } } diff --git a/vendor/clap_builder/src/output/usage.rs b/vendor/clap_builder/src/output/usage.rs index c49ca2cb0..dd99c63c7 100644 --- a/vendor/clap_builder/src/output/usage.rs +++ b/vendor/clap_builder/src/output/usage.rs @@ -5,6 +5,7 @@ // Internal use crate::builder::StyledStr; +use crate::builder::Styles; use crate::builder::{ArgPredicate, Command}; use crate::parser::ArgMatcher; use crate::util::ChildGraph; @@ -15,6 +16,7 @@ static DEFAULT_SUB_VALUE_NAME: &str = "COMMAND"; pub(crate) struct Usage<'cmd> { cmd: &'cmd Command, + styles: &'cmd Styles, required: Option<&'cmd ChildGraph<Id>>, } @@ -22,6 +24,7 @@ impl<'cmd> Usage<'cmd> { pub(crate) fn new(cmd: &'cmd Command) -> Self { Usage { cmd, + styles: cmd.get_styles(), required: None, } } @@ -37,9 +40,14 @@ impl<'cmd> Usage<'cmd> { debug!("Usage::create_usage_with_title"); let usage = some!(self.create_usage_no_title(used)); + use std::fmt::Write as _; let mut styled = StyledStr::new(); - styled.header("Usage:"); - styled.none(" "); + let _ = write!( + styled, + "{}Usage:{} ", + self.styles.get_usage().render(), + self.styles.get_usage().render_reset() + ); styled.push_styled(&usage); Some(styled) } @@ -72,16 +80,33 @@ impl<'cmd> Usage<'cmd> { // Creates a usage string for display in help messages (i.e. not for errors) fn create_help_usage(&self, incl_reqs: bool) -> StyledStr { debug!("Usage::create_help_usage; incl_reqs={:?}", incl_reqs); + use std::fmt::Write as _; + let literal = &self.styles.get_literal(); + let placeholder = &self.styles.get_placeholder(); let mut styled = StyledStr::new(); + let name = self .cmd .get_usage_name() .or_else(|| self.cmd.get_bin_name()) .unwrap_or_else(|| self.cmd.get_name()); - styled.literal(name); + if !name.is_empty() { + // the trim won't properly remove a leading space due to the formatting + let _ = write!( + styled, + "{}{name}{}", + literal.render(), + literal.render_reset() + ); + } if self.needs_options_tag() { - styled.placeholder(" [OPTIONS]"); + let _ = write!( + styled, + "{} [OPTIONS]{}", + placeholder.render(), + placeholder.render_reset() + ); } self.write_args(&[], !incl_reqs, &mut styled); @@ -90,32 +115,45 @@ impl<'cmd> Usage<'cmd> { if self.cmd.has_visible_subcommands() && incl_reqs || self.cmd.is_allow_external_subcommands_set() { - let placeholder = self + let value_name = self .cmd .get_subcommand_value_name() .unwrap_or(DEFAULT_SUB_VALUE_NAME); if self.cmd.is_subcommand_negates_reqs_set() || self.cmd.is_args_conflicts_with_subcommands_set() { - styled.none("\n"); - styled.none(" "); + let _ = write!(styled, "\n "); if self.cmd.is_args_conflicts_with_subcommands_set() { // Short-circuit full usage creation since no args will be relevant - styled.literal(name); + let _ = write!( + styled, + "{}{name}{}", + literal.render(), + literal.render_reset() + ); } else { styled.push_styled(&self.create_help_usage(false)); } - styled.placeholder(" <"); - styled.placeholder(placeholder); - styled.placeholder(">"); + let _ = write!( + styled, + " {}<{value_name}>{}", + placeholder.render(), + placeholder.render_reset() + ); } else if self.cmd.is_subcommand_required_set() { - styled.placeholder(" <"); - styled.placeholder(placeholder); - styled.placeholder(">"); + let _ = write!( + styled, + " {}<{value_name}>{}", + placeholder.render(), + placeholder.render_reset() + ); } else { - styled.placeholder(" ["); - styled.placeholder(placeholder); - styled.placeholder("]"); + let _ = write!( + styled, + " {}[{value_name}]{}", + placeholder.render(), + placeholder.render_reset() + ); } } styled.trim(); @@ -127,25 +165,36 @@ impl<'cmd> Usage<'cmd> { // args, and requirements fn create_smart_usage(&self, used: &[Id]) -> StyledStr { debug!("Usage::create_smart_usage"); + use std::fmt::Write; + let literal = &self.styles.get_literal(); + let placeholder = &self.styles.get_placeholder(); let mut styled = StyledStr::new(); - styled.literal( - self.cmd - .get_usage_name() - .or_else(|| self.cmd.get_bin_name()) - .unwrap_or_else(|| self.cmd.get_name()), + let bin_name = self + .cmd + .get_usage_name() + .or_else(|| self.cmd.get_bin_name()) + .unwrap_or_else(|| self.cmd.get_name()); + let _ = write!( + styled, + "{}{bin_name}{}", + literal.render(), + literal.render_reset() ); self.write_args(used, false, &mut styled); if self.cmd.is_subcommand_required_set() { - styled.placeholder(" <"); - styled.placeholder( - self.cmd - .get_subcommand_value_name() - .unwrap_or(DEFAULT_SUB_VALUE_NAME), + let value_name = self + .cmd + .get_subcommand_value_name() + .unwrap_or(DEFAULT_SUB_VALUE_NAME); + let _ = write!( + styled, + " {}<{value_name}>{}", + placeholder.render(), + placeholder.render_reset() ); - styled.placeholder(">"); } styled } @@ -189,13 +238,15 @@ impl<'cmd> Usage<'cmd> { // Returns the required args in usage string form by fully unrolling all groups pub(crate) fn write_args(&self, incls: &[Id], force_optional: bool, styled: &mut StyledStr) { for required in self.get_args(incls, force_optional) { - styled.none(" "); + styled.push_str(" "); styled.push_styled(&required); } } pub(crate) fn get_args(&self, incls: &[Id], force_optional: bool) -> Vec<StyledStr> { debug!("Usage::get_args: incls={:?}", incls,); + use std::fmt::Write as _; + let literal = &self.styles.get_literal(); let required_owned; let required = if let Some(required) = self.required { @@ -247,7 +298,7 @@ impl<'cmd> Usage<'cmd> { continue; } - let stylized = arg.stylized(Some(!force_optional)); + let stylized = arg.stylized(self.styles, Some(!force_optional)); if let Some(index) = arg.get_index() { let new_len = index + 1; if required_positionals.len() < new_len { @@ -279,7 +330,7 @@ impl<'cmd> Usage<'cmd> { if pos.is_last_set() { let styled = required_positionals[index].take().unwrap(); let mut new = StyledStr::new(); - new.literal("-- "); + let _ = write!(new, "{}--{} ", literal.render(), literal.render_reset()); new.push_styled(&styled); required_positionals[index] = Some(new); } @@ -287,11 +338,11 @@ impl<'cmd> Usage<'cmd> { let mut styled; if pos.is_last_set() { styled = StyledStr::new(); - styled.literal("[-- "); - styled.push_styled(&pos.stylized(Some(true))); - styled.literal("]"); + let _ = write!(styled, "{}[--{} ", literal.render(), literal.render_reset()); + styled.push_styled(&pos.stylized(self.styles, Some(true))); + let _ = write!(styled, "{}]{}", literal.render(), literal.render_reset()); } else { - styled = pos.stylized(Some(false)); + styled = pos.stylized(self.styles, Some(false)); } required_positionals[index] = Some(styled); } @@ -411,7 +462,7 @@ impl<'cmd> Usage<'cmd> { continue; } - let stylized = arg.stylized(Some(true)); + let stylized = arg.stylized(self.styles, Some(true)); if let Some(index) = arg.get_index() { if !arg.is_last_set() || incl_last { let new_len = index + 1; diff --git a/vendor/clap_builder/src/parser/arg_matcher.rs b/vendor/clap_builder/src/parser/arg_matcher.rs index d584689cd..124d46f5f 100644 --- a/vendor/clap_builder/src/parser/arg_matcher.rs +++ b/vendor/clap_builder/src/parser/arg_matcher.rs @@ -5,10 +5,10 @@ use std::ops::Deref; // Internal use crate::builder::{Arg, ArgPredicate, Command}; -use crate::parser::AnyValue; use crate::parser::Identifier; use crate::parser::PendingArg; use crate::parser::{ArgMatches, MatchedArg, SubCommand, ValueSource}; +use crate::util::AnyValue; use crate::util::FlatMap; use crate::util::Id; use crate::INTERNAL_ERROR_MSG; @@ -130,7 +130,9 @@ impl ArgMatcher { } pub(crate) fn check_explicit(&self, arg: &Id, predicate: &ArgPredicate) -> bool { - self.get(arg).map_or(false, |a| a.check_explicit(predicate)) + self.get(arg) + .map(|a| a.check_explicit(predicate)) + .unwrap_or_default() } pub(crate) fn start_custom_arg(&mut self, arg: &Arg, source: ValueSource) { diff --git a/vendor/clap_builder/src/parser/error.rs b/vendor/clap_builder/src/parser/error.rs index 66b2bc79e..77b0bb0fc 100644 --- a/vendor/clap_builder/src/parser/error.rs +++ b/vendor/clap_builder/src/parser/error.rs @@ -1,3 +1,5 @@ +use crate::util::AnyValueId; + /// Violation of [`ArgMatches`][crate::ArgMatches] assumptions #[derive(Clone, Debug)] #[allow(missing_copy_implementations)] // We might add non-Copy types in the future @@ -7,9 +9,9 @@ pub enum MatchesError { #[non_exhaustive] Downcast { /// Type for value stored in [`ArgMatches`][crate::ArgMatches] - actual: super::AnyValueId, + actual: AnyValueId, /// The target type to downcast to - expected: super::AnyValueId, + expected: AnyValueId, }, /// Argument not defined in [`Command`][crate::Command] #[non_exhaustive] diff --git a/vendor/clap_builder/src/parser/matches/arg_matches.rs b/vendor/clap_builder/src/parser/matches/arg_matches.rs index 306ce9ed2..da8a34783 100644 --- a/vendor/clap_builder/src/parser/matches/arg_matches.rs +++ b/vendor/clap_builder/src/parser/matches/arg_matches.rs @@ -8,11 +8,11 @@ use std::slice::Iter; // Internal #[cfg(debug_assertions)] use crate::builder::Str; -use crate::parser::AnyValue; -use crate::parser::AnyValueId; use crate::parser::MatchedArg; use crate::parser::MatchesError; use crate::parser::ValueSource; +use crate::util::AnyValue; +use crate::util::AnyValueId; use crate::util::FlatMap; use crate::util::Id; use crate::INTERNAL_ERROR_MSG; diff --git a/vendor/clap_builder/src/parser/matches/matched_arg.rs b/vendor/clap_builder/src/parser/matches/matched_arg.rs index 901990cfb..24df8b160 100644 --- a/vendor/clap_builder/src/parser/matches/matched_arg.rs +++ b/vendor/clap_builder/src/parser/matches/matched_arg.rs @@ -6,10 +6,10 @@ use std::{ }; use crate::builder::ArgPredicate; -use crate::parser::AnyValue; -use crate::parser::AnyValueId; use crate::parser::ValueSource; use crate::util::eq_ignore_case; +use crate::util::AnyValue; +use crate::util::AnyValueId; use crate::INTERNAL_ERROR_MSG; #[derive(Debug, Clone)] diff --git a/vendor/clap_builder/src/parser/matches/mod.rs b/vendor/clap_builder/src/parser/matches/mod.rs index 0e3474fb3..eb865853c 100644 --- a/vendor/clap_builder/src/parser/matches/mod.rs +++ b/vendor/clap_builder/src/parser/matches/mod.rs @@ -1,9 +1,7 @@ -mod any_value; mod arg_matches; mod matched_arg; mod value_source; -pub use any_value::AnyValueId; pub use arg_matches::IdsRef; pub use arg_matches::RawValues; pub use arg_matches::Values; @@ -11,6 +9,5 @@ pub use arg_matches::ValuesRef; pub use arg_matches::{ArgMatches, Indices}; pub use value_source::ValueSource; -pub(crate) use any_value::AnyValue; pub(crate) use arg_matches::SubCommand; pub(crate) use matched_arg::MatchedArg; diff --git a/vendor/clap_builder/src/parser/mod.rs b/vendor/clap_builder/src/parser/mod.rs index c99e74f95..3e73544d5 100644 --- a/vendor/clap_builder/src/parser/mod.rs +++ b/vendor/clap_builder/src/parser/mod.rs @@ -10,8 +10,6 @@ mod validator; pub(crate) mod features; pub(crate) use self::arg_matcher::ArgMatcher; -pub(crate) use self::matches::AnyValue; -pub(crate) use self::matches::AnyValueId; pub(crate) use self::matches::{MatchedArg, SubCommand}; pub(crate) use self::parser::Identifier; pub(crate) use self::parser::PendingArg; diff --git a/vendor/clap_builder/src/parser/parser.rs b/vendor/clap_builder/src/parser/parser.rs index c29100485..723e1cd69 100644 --- a/vendor/clap_builder/src/parser/parser.rs +++ b/vendor/clap_builder/src/parser/parser.rs @@ -13,9 +13,9 @@ use crate::error::Result as ClapResult; use crate::mkeymap::KeyType; use crate::output::Usage; use crate::parser::features::suggestions; -use crate::parser::AnyValue; use crate::parser::{ArgMatcher, SubCommand}; use crate::parser::{Validator, ValueSource}; +use crate::util::AnyValue; use crate::util::Id; use crate::ArgAction; use crate::INTERNAL_ERROR_MSG; @@ -305,7 +305,8 @@ impl<'cmd> Parser<'cmd> { .cmd .get_positionals() .last() - .map_or(false, |p_name| !p_name.is_last_set()); + .map(|p_name| !p_name.is_last_set()) + .unwrap_or_default(); let missing_pos = self.cmd.is_allow_missing_positional_set() && is_second_to_last @@ -779,9 +780,10 @@ impl<'cmd> Parser<'cmd> { matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent) }) .filter(|&n| { - self.cmd.find(n).map_or(true, |a| { - !(a.is_hide_set() || required.contains(a.get_id())) - }) + self.cmd + .find(n) + .map(|a| !(a.is_hide_set() || required.contains(a.get_id()))) + .unwrap_or(true) }) .cloned() .collect(); @@ -810,9 +812,8 @@ impl<'cmd> Parser<'cmd> { .cmd .get_keymap() .get(&pos_counter) - .map_or(false, |arg| { - arg.is_allow_hyphen_values_set() && !arg.is_last_set() - }) + .map(|arg| arg.is_allow_hyphen_values_set() && !arg.is_last_set()) + .unwrap_or_default() { debug!( "Parser::parse_long_args: positional at {} allows hyphens", @@ -847,7 +848,8 @@ impl<'cmd> Parser<'cmd> { .cmd .get_keymap() .get(&pos_counter) - .map_or(false, |arg| arg.is_allow_negative_numbers_set()) + .map(|arg| arg.is_allow_negative_numbers_set()) + .unwrap_or_default() && short_arg.is_number() { debug!("Parser::parse_short_arg: negative number"); @@ -856,9 +858,8 @@ impl<'cmd> Parser<'cmd> { .cmd .get_keymap() .get(&pos_counter) - .map_or(false, |arg| { - arg.is_allow_hyphen_values_set() && !arg.is_last_set() - }) + .map(|arg| arg.is_allow_hyphen_values_set() && !arg.is_last_set()) + .unwrap_or_default() && short_arg .clone() .any(|c| !c.map(|c| self.cmd.contains_short(c)).unwrap_or_default()) @@ -1536,7 +1537,7 @@ impl<'cmd> Parser<'cmd> { .filter(|arg_id| { matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent) }) - .filter(|n| self.cmd.find(n).map_or(true, |a| !a.is_hide_set())) + .filter(|n| self.cmd.find(n).map(|a| !a.is_hide_set()).unwrap_or(true)) .cloned() .collect(); diff --git a/vendor/clap_builder/src/parser/validator.rs b/vendor/clap_builder/src/parser/validator.rs index 49d28a34f..5c3d34643 100644 --- a/vendor/clap_builder/src/parser/validator.rs +++ b/vendor/clap_builder/src/parser/validator.rs @@ -199,7 +199,10 @@ impl<'cmd> Validator<'cmd> { .map(|(n, _)| n) .filter(|n| { // Filter out the args we don't want to specify. - self.cmd.find(n).map_or(false, |a| !a.is_hide_set()) + self.cmd + .find(n) + .map(|a| !a.is_hide_set()) + .unwrap_or_default() }) .filter(|key| !conflicting_keys.contains(key)) .cloned() @@ -445,7 +448,10 @@ impl<'cmd> Validator<'cmd> { .map(|(n, _)| n) .filter(|n| { // Filter out the args we don't want to specify. - self.cmd.find(n).map_or(false, |a| !a.is_hide_set()) + self.cmd + .find(n) + .map(|a| !a.is_hide_set()) + .unwrap_or_default() }) .cloned() .chain(raw_req_args) diff --git a/vendor/clap_builder/src/parser/matches/any_value.rs b/vendor/clap_builder/src/util/any_value.rs index dc7a3e953..dc7a3e953 100644 --- a/vendor/clap_builder/src/parser/matches/any_value.rs +++ b/vendor/clap_builder/src/util/any_value.rs diff --git a/vendor/clap_builder/src/util/mod.rs b/vendor/clap_builder/src/util/mod.rs index e6a8f70ed..a92aef8c3 100644 --- a/vendor/clap_builder/src/util/mod.rs +++ b/vendor/clap_builder/src/util/mod.rs @@ -1,5 +1,6 @@ #![allow(clippy::single_component_path_imports)] +mod any_value; pub(crate) mod flat_map; pub(crate) mod flat_set; mod graph; @@ -8,6 +9,8 @@ mod str_to_bool; pub use self::id::Id; +pub(crate) use self::any_value::AnyValue; +pub(crate) use self::any_value::AnyValueId; pub(crate) use self::flat_map::Entry; pub(crate) use self::flat_map::FlatMap; pub(crate) use self::flat_set::FlatSet; |