From d1b2d29528b7794b41e66fc2136e395a02f8529b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:59:35 +0200 Subject: Merging upstream version 1.73.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/clap_builder/src/builder/action.rs | 62 ++++++++ vendor/clap_builder/src/builder/arg.rs | 10 ++ vendor/clap_builder/src/builder/command.rs | 16 +- vendor/clap_builder/src/builder/debug_asserts.rs | 51 ------- vendor/clap_builder/src/builder/mod.rs | 9 +- vendor/clap_builder/src/builder/styled_str.rs | 161 -------------------- vendor/clap_builder/src/builder/styling.rs | 181 +++++++++++++++++++++++ vendor/clap_builder/src/builder/value_parser.rs | 59 +++++++- vendor/clap_builder/src/error/mod.rs | 25 ++-- vendor/clap_builder/src/output/help_template.rs | 84 +++++++---- vendor/clap_builder/src/output/usage.rs | 15 ++ vendor/clap_builder/src/parser/parser.rs | 27 +++- 12 files changed, 437 insertions(+), 263 deletions(-) create mode 100644 vendor/clap_builder/src/builder/styling.rs (limited to 'vendor/clap_builder/src') diff --git a/vendor/clap_builder/src/builder/action.rs b/vendor/clap_builder/src/builder/action.rs index 79ee9238e..2def801f4 100644 --- a/vendor/clap_builder/src/builder/action.rs +++ b/vendor/clap_builder/src/builder/action.rs @@ -257,6 +257,58 @@ pub enum ArgAction { /// # } /// ``` Help, + /// When encountered, display [`Command::print_help`][super::Command::print_help] + /// + /// # Examples + /// + /// ```rust + /// # #[cfg(feature = "help")] { + /// # use clap_builder as clap; + /// # use clap::Command; + /// # use clap::Arg; + /// let cmd = Command::new("mycmd") + /// .arg( + /// Arg::new("special-help") + /// .short('?') + /// .action(clap::ArgAction::HelpShort) + /// ); + /// + /// // Existing help still exists + /// let err = cmd.clone().try_get_matches_from(["mycmd", "-h"]).unwrap_err(); + /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); + /// + /// // New help available + /// let err = cmd.try_get_matches_from(["mycmd", "-?"]).unwrap_err(); + /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); + /// # } + /// ``` + HelpShort, + /// When encountered, display [`Command::print_long_help`][super::Command::print_long_help] + /// + /// # Examples + /// + /// ```rust + /// # #[cfg(feature = "help")] { + /// # use clap_builder as clap; + /// # use clap::Command; + /// # use clap::Arg; + /// let cmd = Command::new("mycmd") + /// .arg( + /// Arg::new("special-help") + /// .short('?') + /// .action(clap::ArgAction::HelpLong) + /// ); + /// + /// // Existing help still exists + /// let err = cmd.clone().try_get_matches_from(["mycmd", "-h"]).unwrap_err(); + /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); + /// + /// // New help available + /// let err = cmd.try_get_matches_from(["mycmd", "-?"]).unwrap_err(); + /// assert_eq!(err.kind(), clap::error::ErrorKind::DisplayHelp); + /// # } + /// ``` + HelpLong, /// When encountered, display [`Command::version`][super::Command::version] /// /// Depending on the flag, [`Command::long_version`][super::Command::long_version] may be shown @@ -299,6 +351,8 @@ impl ArgAction { Self::SetFalse => false, Self::Count => false, Self::Help => false, + Self::HelpShort => false, + Self::HelpLong => false, Self::Version => false, } } @@ -311,6 +365,8 @@ impl ArgAction { Self::SetFalse => Some(std::ffi::OsStr::new("true")), Self::Count => Some(std::ffi::OsStr::new("0")), Self::Help => None, + Self::HelpShort => None, + Self::HelpLong => None, Self::Version => None, } } @@ -323,6 +379,8 @@ impl ArgAction { Self::SetFalse => Some(std::ffi::OsStr::new("false")), Self::Count => None, Self::Help => None, + Self::HelpShort => None, + Self::HelpLong => None, Self::Version => None, } } @@ -335,6 +393,8 @@ impl ArgAction { Self::SetFalse => Some(super::ValueParser::bool()), Self::Count => Some(crate::value_parser!(u8).into()), Self::Help => None, + Self::HelpShort => None, + Self::HelpLong => None, Self::Version => None, } } @@ -348,6 +408,8 @@ impl ArgAction { Self::SetFalse => None, Self::Count => Some(AnyValueId::of::()), Self::Help => None, + Self::HelpShort => None, + Self::HelpLong => None, Self::Version => None, } } diff --git a/vendor/clap_builder/src/builder/arg.rs b/vendor/clap_builder/src/builder/arg.rs index 5bfea9ad4..d067dec1d 100644 --- a/vendor/clap_builder/src/builder/arg.rs +++ b/vendor/clap_builder/src/builder/arg.rs @@ -1650,6 +1650,8 @@ impl Arg { /// at runtime, nor were the conditions met for `Arg::default_value_if`, the `Arg::default_value` /// will be applied. /// + /// Like with command-line values, this will be split by [`Arg::value_delimiter`]. + /// /// # Examples /// /// First we use the default value without providing any value at runtime. @@ -1747,6 +1749,8 @@ impl Arg { /// [`.require_equals(true)`][Arg::require_equals] configuration option. These are required in /// order to unambiguously determine what, if any, value was supplied for the argument. /// + /// Like with command-line values, this will be split by [`Arg::value_delimiter`]. + /// /// # Examples /// /// For POSIX style `--color`: @@ -1893,6 +1897,8 @@ impl Arg { /// [`ArgMatches::get_one`][crate::ArgMatches::get_one] will /// return the default specified. /// + /// Like with command-line values, this will be split by [`Arg::value_delimiter`]. + /// /// # Examples /// /// In this example, we show the variable coming from the environment: @@ -2734,6 +2740,8 @@ impl Arg { /// and `Arg::default_value_if`, and the user **did not** provide this arg at runtime, nor were /// the conditions met for `Arg::default_value_if`, the `Arg::default_value` will be applied. /// + /// Like with command-line values, this will be split by [`Arg::value_delimiter`]. + /// /// # Examples /// /// First we use the default value only if another arg is present at runtime. @@ -2873,6 +2881,8 @@ impl Arg { /// **NOTE**: The conditions are stored in order and evaluated in the same order. I.e. the first /// if multiple conditions are true, the first one found will be applied and the ultimate value. /// + /// Like with command-line values, this will be split by [`Arg::value_delimiter`]. + /// /// # Examples /// /// First we use the default value only if another arg is present at runtime. diff --git a/vendor/clap_builder/src/builder/command.rs b/vendor/clap_builder/src/builder/command.rs index 2c5eb1989..b2efdbc7e 100644 --- a/vendor/clap_builder/src/builder/command.rs +++ b/vendor/clap_builder/src/builder/command.rs @@ -1111,9 +1111,14 @@ impl Command { /// /// ```no_run /// # use clap_builder as clap; - /// # use clap::{Command, ColorChoice, builder::Styles}; + /// # use clap::{Command, ColorChoice, builder::styling}; + /// let styles = styling::Styles::styled() + /// .header(styling::AnsiColor::Green.on_default() | styling::Effects::BOLD) + /// .usage(styling::AnsiColor::Green.on_default() | styling::Effects::BOLD) + /// .literal(styling::AnsiColor::Blue.on_default() | styling::Effects::BOLD) + /// .placeholder(styling::AnsiColor::Cyan.on_default()); /// Command::new("myprog") - /// .styles(Styles::styled().usage(Default::default())) + /// .styles(styles) /// .get_matches(); /// ``` #[cfg(feature = "color")] @@ -1132,6 +1137,9 @@ impl Command { /// Defaults to current terminal width when `wrap_help` feature flag is enabled. If current /// width cannot be determined, the default is 100. /// + /// **`unstable-v5` feature**: Defaults to unbound, being subject to + /// [`Command::max_term_width`]. + /// /// **NOTE:** This setting applies globally and *not* on a per-command basis. /// /// **NOTE:** This requires the `wrap_help` feature @@ -1158,7 +1166,9 @@ impl Command { /// This only applies when [`term_width`][Command::term_width] is unset so that the current /// terminal's width will be used. See [`Command::term_width`] for more details. /// - /// Using `0` will ignore terminal widths and use source formatting (default). + /// Using `0` will ignore this, always respecting [`Command::term_width`] (default). + /// + /// **`unstable-v5` feature**: Defaults to 100. /// /// **NOTE:** This setting applies globally and *not* on a per-command basis. /// diff --git a/vendor/clap_builder/src/builder/debug_asserts.rs b/vendor/clap_builder/src/builder/debug_asserts.rs index ef970cdaa..29008be9f 100644 --- a/vendor/clap_builder/src/builder/debug_asserts.rs +++ b/vendor/clap_builder/src/builder/debug_asserts.rs @@ -1,8 +1,5 @@ use std::cmp::Ordering; -use clap_lex::OsStrExt as _; - -use crate::builder::OsStr; use crate::builder::ValueRange; use crate::mkeymap::KeyType; use crate::util::FlatSet; @@ -809,20 +806,6 @@ fn assert_arg(arg: &Arg) { } assert_arg_flags(arg); - - assert_defaults(arg, "default_value", arg.default_vals.iter()); - assert_defaults( - arg, - "default_missing_value", - arg.default_missing_vals.iter(), - ); - assert_defaults( - arg, - "default_value_if", - arg.default_vals_ifs - .iter() - .filter_map(|(_, _, default)| default.as_ref()), - ); } fn assert_arg_flags(arg: &Arg) { @@ -854,37 +837,3 @@ fn assert_arg_flags(arg: &Arg) { checker!(is_multiple_values_set requires is_takes_value_set); checker!(is_ignore_case_set requires is_takes_value_set); } - -fn assert_defaults<'d>( - arg: &Arg, - field: &'static str, - defaults: impl IntoIterator, -) { - for default_os in defaults { - let value_parser = arg.get_value_parser(); - let assert_cmd = Command::new("assert"); - if let Some(val_delim) = arg.get_value_delimiter() { - let mut val_delim_buffer = [0; 4]; - let val_delim = val_delim.encode_utf8(&mut val_delim_buffer); - for part in default_os.split(val_delim) { - if let Err(err) = value_parser.parse_ref(&assert_cmd, Some(arg), part) { - panic!( - "Argument `{}`'s {}={:?} failed validation: {}", - arg.get_id(), - field, - part.to_string_lossy(), - err - ); - } - } - } else if let Err(err) = value_parser.parse_ref(&assert_cmd, Some(arg), default_os) { - panic!( - "Argument `{}`'s {}={:?} failed validation: {}", - arg.get_id(), - field, - default_os, - err - ); - } - } -} diff --git a/vendor/clap_builder/src/builder/mod.rs b/vendor/clap_builder/src/builder/mod.rs index 495c84587..ad70911a9 100644 --- a/vendor/clap_builder/src/builder/mod.rs +++ b/vendor/clap_builder/src/builder/mod.rs @@ -23,6 +23,11 @@ mod debug_asserts; #[cfg(test)] mod tests; +#[cfg(feature = "unstable-styles")] +pub mod styling; +#[cfg(not(feature = "unstable-styles"))] +pub(crate) mod styling; + pub use self::str::Str; pub use action::ArgAction; pub use arg::Arg; @@ -36,7 +41,7 @@ pub use resettable::IntoResettable; pub use resettable::Resettable; pub use styled_str::StyledStr; #[cfg(feature = "unstable-styles")] -pub use styled_str::Styles; +pub use styling::Styles; pub use value_hint::ValueHint; pub use value_parser::_AutoValueParser; pub use value_parser::via_prelude; @@ -63,4 +68,4 @@ 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; +pub(crate) use styling::Styles; diff --git a/vendor/clap_builder/src/builder/styled_str.rs b/vendor/clap_builder/src/builder/styled_str.rs index e4acc63ff..d856a3015 100644 --- a/vendor/clap_builder/src/builder/styled_str.rs +++ b/vendor/clap_builder/src/builder/styled_str.rs @@ -197,164 +197,3 @@ impl std::fmt::Display for StyledStr { Ok(()) } } - -/// 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 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/styling.rs b/vendor/clap_builder/src/builder/styling.rs new file mode 100644 index 000000000..f7f2ee1e3 --- /dev/null +++ b/vendor/clap_builder/src/builder/styling.rs @@ -0,0 +1,181 @@ +//! Terminal [`Styles`] for help and error output + +pub use anstyle::*; + +/// Terminal styling definitions +/// +/// See also [`Command::styles`][crate::Command::styles]. +/// +/// # Example +/// +/// clap v3 styling +/// ```rust +/// # #[cfg(feature = "unstable-styles")] { +/// # use clap_builder as clap; +/// # use clap::builder::styling::*; +/// let styles = Styles::styled() +/// .header(AnsiColor::Yellow.on_default()) +/// .usage(AnsiColor::Green.on_default()) +/// .literal(AnsiColor::Green.on_default()) +/// .placeholder(AnsiColor::Green.on_default()); +/// # } +/// ``` +#[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 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 4b0955789..c7c7e61eb 100644 --- a/vendor/clap_builder/src/builder/value_parser.rs +++ b/vendor/clap_builder/src/builder/value_parser.rs @@ -2137,18 +2137,38 @@ impl ValueParserFactory for String { ValueParser::string() // Default `clap_derive` to optimized implementation } } +impl ValueParserFactory for Box { + type Parser = MapValueParser Box>; + fn value_parser() -> Self::Parser { + StringValueParser::new().map(String::into_boxed_str) + } +} impl ValueParserFactory for std::ffi::OsString { type Parser = ValueParser; fn value_parser() -> Self::Parser { ValueParser::os_string() // Default `clap_derive` to optimized implementation } } +impl ValueParserFactory for Box { + type Parser = + MapValueParser Box>; + fn value_parser() -> Self::Parser { + OsStringValueParser::new().map(std::ffi::OsString::into_boxed_os_str) + } +} impl ValueParserFactory for std::path::PathBuf { type Parser = ValueParser; fn value_parser() -> Self::Parser { ValueParser::path_buf() // Default `clap_derive` to optimized implementation } } +impl ValueParserFactory for Box { + type Parser = + MapValueParser Box>; + fn value_parser() -> Self::Parser { + PathBufValueParser::new().map(std::path::PathBuf::into_boxed_path) + } +} impl ValueParserFactory for bool { type Parser = ValueParser; fn value_parser() -> Self::Parser { @@ -2203,16 +2223,49 @@ impl ValueParserFactory for i32 { RangedI64ValueParser::new().range(start..=end) } } +impl ValueParserFactory for u64 { + type Parser = RangedU64ValueParser; + fn value_parser() -> Self::Parser { + RangedU64ValueParser::new() + } +} impl ValueParserFactory for i64 { type Parser = RangedI64ValueParser; fn value_parser() -> Self::Parser { RangedI64ValueParser::new() } } -impl ValueParserFactory for u64 { - type Parser = RangedU64ValueParser; +impl ValueParserFactory for std::num::Wrapping +where + T: ValueParserFactory, + ::Parser: TypedValueParser, + T: Send + Sync + Clone, +{ + type Parser = MapValueParser<::Parser, fn(T) -> std::num::Wrapping>; fn value_parser() -> Self::Parser { - RangedU64ValueParser::new() + T::value_parser().map(std::num::Wrapping) + } +} +impl ValueParserFactory for Box +where + T: ValueParserFactory, + ::Parser: TypedValueParser, + T: Send + Sync + Clone, +{ + type Parser = MapValueParser<::Parser, fn(T) -> Box>; + fn value_parser() -> Self::Parser { + T::value_parser().map(Box::new) + } +} +impl ValueParserFactory for std::sync::Arc +where + T: ValueParserFactory, + ::Parser: TypedValueParser, + T: Send + Sync + Clone, +{ + type Parser = MapValueParser<::Parser, fn(T) -> std::sync::Arc>; + fn value_parser() -> Self::Parser { + T::value_parser().map(std::sync::Arc::new) } } diff --git a/vendor/clap_builder/src/error/mod.rs b/vendor/clap_builder/src/error/mod.rs index 210a1717f..772058a5f 100644 --- a/vendor/clap_builder/src/error/mod.rs +++ b/vendor/clap_builder/src/error/mod.rs @@ -446,6 +446,7 @@ impl Error { subcmd: String, did_you_mean: Vec, name: String, + suggested_trailing_arg: bool, usage: Option, ) -> Self { use std::fmt::Write as _; @@ -456,15 +457,19 @@ impl Error { #[cfg(feature = "error-context")] { - let mut styled_suggestion = StyledStr::new(); - let _ = write!( - styled_suggestion, - "to pass '{}{subcmd}{}' as a value, use '{}{name} -- {subcmd}{}'", - invalid.render(), - invalid.render_reset(), - valid.render(), - valid.render_reset() - ); + let mut suggestions = vec![]; + if suggested_trailing_arg { + let mut styled_suggestion = StyledStr::new(); + let _ = write!( + styled_suggestion, + "to pass '{}{subcmd}{}' as a value, use '{}{name} -- {subcmd}{}'", + invalid.render(), + invalid.render_reset(), + valid.render(), + valid.render_reset() + ); + suggestions.push(styled_suggestion); + } err = err.extend_context_unchecked([ (ContextKind::InvalidSubcommand, ContextValue::String(subcmd)), @@ -474,7 +479,7 @@ impl Error { ), ( ContextKind::Suggested, - ContextValue::StyledStrs(vec![styled_suggestion]), + ContextValue::StyledStrs(suggestions), ), ]); if let Some(usage) = usage { diff --git a/vendor/clap_builder/src/output/help_template.rs b/vendor/clap_builder/src/output/help_template.rs index 68ff58077..da2e75413 100644 --- a/vendor/clap_builder/src/output/help_template.rs +++ b/vendor/clap_builder/src/output/help_template.rs @@ -101,7 +101,23 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { cmd.get_name(), use_long ); - let term_w = match cmd.get_term_width() { + let term_w = Self::term_w(cmd); + let next_line_help = cmd.is_next_line_help_set(); + + HelpTemplate { + writer, + cmd, + styles: cmd.get_styles(), + usage, + next_line_help, + term_w, + use_long, + } + } + + #[cfg(not(feature = "unstable-v5"))] + fn term_w(cmd: &'cmd Command) -> usize { + match cmd.get_term_width() { Some(0) => usize::MAX, Some(w) => w, None => { @@ -113,18 +129,27 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { }; cmp::min(current_width, max_width) } + } + } + + #[cfg(feature = "unstable-v5")] + fn term_w(cmd: &'cmd Command) -> usize { + let term_w = match cmd.get_term_width() { + Some(0) => usize::MAX, + Some(w) => w, + None => { + let (current_width, _h) = dimensions(); + current_width.unwrap_or(usize::MAX) + } }; - let next_line_help = cmd.is_next_line_help_set(); - HelpTemplate { - writer, - cmd, - styles: cmd.get_styles(), - usage, - next_line_help, - term_w, - use_long, - } + let max_term_w = match cmd.get_max_term_width() { + Some(0) => usize::MAX, + Some(mw) => mw, + None => 100, + }; + + cmp::min(term_w, max_term_w) } /// Write help to stream for the parser in the format defined by the template. @@ -676,32 +701,33 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { self.writer.push_str("Possible values:"); for pv in possible_vals.iter().filter(|pv| !pv.is_hide_set()) { let name = pv.get_name(); + + let mut descr = StyledStr::new(); let _ = write!( - self.writer, - "\n{:spaces$}- {}{name}{}", - "", + &mut descr, + "{}{name}{}", literal.render(), literal.render_reset() ); if let Some(help) = pv.get_help() { debug!("HelpTemplate::help: Possible Value help"); - // To align help messages - let padding = longest - display_width(pv.get_name()); - let _ = write!(self.writer, ": {:padding$}", ""); - - let avail_chars = if self.term_w > trailing_indent.len() { - self.term_w - trailing_indent.len() - } else { - usize::MAX - }; - - let mut help = help.clone(); - help.replace_newline_var(); - help.wrap(avail_chars); - help.indent("", &trailing_indent); - self.writer.push_styled(&help); + let padding = longest - display_width(name); + let _ = write!(&mut descr, ": {:padding$}", ""); + descr.push_styled(help); } + + let avail_chars = if self.term_w > trailing_indent.len() { + self.term_w - trailing_indent.len() + } else { + usize::MAX + }; + descr.replace_newline_var(); + descr.wrap(avail_chars); + descr.indent("", &trailing_indent); + + let _ = write!(self.writer, "\n{:spaces$}- ", "",); + self.writer.push_styled(&descr); } } } diff --git a/vendor/clap_builder/src/output/usage.rs b/vendor/clap_builder/src/output/usage.rs index 3f387a0d7..884a64df9 100644 --- a/vendor/clap_builder/src/output/usage.rs +++ b/vendor/clap_builder/src/output/usage.rs @@ -4,6 +4,7 @@ #![cfg_attr(not(feature = "usage"), allow(dead_code))] // Internal +use crate::builder::ArgAction; use crate::builder::StyledStr; use crate::builder::Styles; use crate::builder::{ArgPredicate, Command}; @@ -210,6 +211,20 @@ impl<'cmd> Usage<'cmd> { debug!("Usage::needs_options_tag:iter Option is built-in"); continue; } + match f.get_action() { + ArgAction::Set + | ArgAction::Append + | ArgAction::SetTrue + | ArgAction::SetFalse + | ArgAction::Count => {} + ArgAction::Help + | ArgAction::HelpShort + | ArgAction::HelpLong + | ArgAction::Version => { + debug!("Usage::needs_options_tag:iter Option is built-in"); + continue; + } + } if f.is_hide_set() { debug!("Usage::needs_options_tag:iter Option is hidden"); diff --git a/vendor/clap_builder/src/parser/parser.rs b/vendor/clap_builder/src/parser/parser.rs index d2e198b28..d6d8e8da4 100644 --- a/vendor/clap_builder/src/parser/parser.rs +++ b/vendor/clap_builder/src/parser/parser.rs @@ -302,6 +302,13 @@ impl<'cmd> Parser<'cmd> { .map(|p_name| !p_name.is_last_set()) .unwrap_or_default(); + let is_terminated = self + .cmd + .get_keymap() + .get(&pos_counter) + .map(|a| a.get_value_terminator().is_some()) + .unwrap_or_default(); + let missing_pos = self.cmd.is_allow_missing_positional_set() && is_second_to_last && !trailing_values; @@ -309,7 +316,7 @@ impl<'cmd> Parser<'cmd> { debug!("Parser::get_matches_with: Positional counter...{pos_counter}"); debug!("Parser::get_matches_with: Low index multiples...{low_index_mults:?}"); - if low_index_mults || missing_pos { + if (low_index_mults || missing_pos) && !is_terminated { let skip_current = if let Some(n) = raw_args.peek(&args_cursor) { if let Some(arg) = self .cmd @@ -474,6 +481,10 @@ impl<'cmd> Parser<'cmd> { } } + let suggested_trailing_arg = !trailing_values + && self.cmd.has_positionals() + && (arg_os.is_long() || arg_os.is_short()); + if !(self.cmd.is_args_conflicts_with_subcommands_set() && valid_arg_found) { let candidates = suggestions::did_you_mean( &arg_os.display().to_string(), @@ -489,6 +500,7 @@ impl<'cmd> Parser<'cmd> { .get_bin_name() .unwrap_or_else(|| self.cmd.get_name()) .to_owned(), + suggested_trailing_arg, Usage::new(self.cmd).create_usage_with_title(&[]), ); } @@ -505,9 +517,6 @@ impl<'cmd> Parser<'cmd> { } } - let suggested_trailing_arg = !trailing_values - && self.cmd.has_positionals() - && (arg_os.is_long() || arg_os.is_short()); ClapError::unknown_argument( self.cmd, arg_os.display().to_string(), @@ -1237,6 +1246,16 @@ impl<'cmd> Parser<'cmd> { debug!("Help: use_long={use_long}"); Err(self.help_err(use_long)) } + ArgAction::HelpShort => { + let use_long = false; + debug!("Help: use_long={use_long}"); + Err(self.help_err(use_long)) + } + ArgAction::HelpLong => { + let use_long = true; + debug!("Help: use_long={use_long}"); + Err(self.help_err(use_long)) + } ArgAction::Version => { let use_long = match ident { Some(Identifier::Long) => true, -- cgit v1.2.3