diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:26:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:26:03 +0000 |
commit | 9918693037dce8aa4bb6f08741b6812923486c18 (patch) | |
tree | 21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /vendor/clap_builder/src | |
parent | Releasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff) | |
download | rustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip |
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/clap_builder/src')
-rw-r--r-- | vendor/clap_builder/src/builder/app_settings.rs | 1 | ||||
-rw-r--r-- | vendor/clap_builder/src/builder/arg.rs | 4 | ||||
-rw-r--r-- | vendor/clap_builder/src/builder/command.rs | 84 | ||||
-rw-r--r-- | vendor/clap_builder/src/builder/styled_str.rs | 4 | ||||
-rw-r--r-- | vendor/clap_builder/src/output/help_template.rs | 73 | ||||
-rw-r--r-- | vendor/clap_builder/src/output/usage.rs | 205 | ||||
-rw-r--r-- | vendor/clap_builder/src/parser/matches/arg_matches.rs | 4 | ||||
-rw-r--r-- | vendor/clap_builder/src/parser/parser.rs | 5 | ||||
-rw-r--r-- | vendor/clap_builder/src/parser/validator.rs | 5 |
9 files changed, 279 insertions, 106 deletions
diff --git a/vendor/clap_builder/src/builder/app_settings.rs b/vendor/clap_builder/src/builder/app_settings.rs index 4fce4b4a2..f9a87dadc 100644 --- a/vendor/clap_builder/src/builder/app_settings.rs +++ b/vendor/clap_builder/src/builder/app_settings.rs @@ -57,6 +57,7 @@ pub(crate) enum AppSettings { SubcommandsNegateReqs, ArgsNegateSubcommands, SubcommandPrecedenceOverArg, + FlattenHelp, ArgRequiredElseHelp, NextLineHelp, DisableColoredHelp, diff --git a/vendor/clap_builder/src/builder/arg.rs b/vendor/clap_builder/src/builder/arg.rs index 8e247c176..f83b4642c 100644 --- a/vendor/clap_builder/src/builder/arg.rs +++ b/vendor/clap_builder/src/builder/arg.rs @@ -875,7 +875,7 @@ impl Arg { impl Arg { /// Specify how to react to an argument when parsing it. /// - /// [ArgAction][crate::ArgAction] controls things like + /// [ArgAction] controls things like /// - Overwriting previous values with new ones /// - Appending new values to all previous ones /// - Counting how many times a flag occurs @@ -1260,7 +1260,7 @@ impl Arg { /// Provide the shell a hint about how to complete this argument. /// - /// See [`ValueHint`][crate::ValueHint] for more information. + /// See [`ValueHint`] for more information. /// /// **NOTE:** implicitly sets [`Arg::action(ArgAction::Set)`]. /// diff --git a/vendor/clap_builder/src/builder/command.rs b/vendor/clap_builder/src/builder/command.rs index edcbace76..6e56b1834 100644 --- a/vendor/clap_builder/src/builder/command.rs +++ b/vendor/clap_builder/src/builder/command.rs @@ -298,6 +298,45 @@ impl Command { self } + /// Allows one to mutate an [`ArgGroup`] after it's been added to a [`Command`]. + /// + /// # Panics + /// + /// If the argument is undefined + /// + /// # Examples + /// + /// ```rust + /// # use clap_builder as clap; + /// # use clap::{Command, arg, ArgGroup}; + /// + /// Command::new("foo") + /// .arg(arg!(--"set-ver" <ver> "set the version manually").required(false)) + /// .arg(arg!(--major "auto increase major")) + /// .arg(arg!(--minor "auto increase minor")) + /// .arg(arg!(--patch "auto increase patch")) + /// .group(ArgGroup::new("vers") + /// .args(["set-ver", "major", "minor","patch"]) + /// .required(true)) + /// .mut_group("vers", |a| a.required(false)); + /// ``` + #[must_use] + #[cfg_attr(debug_assertions, track_caller)] + pub fn mut_group<F>(mut self, arg_id: impl AsRef<str>, f: F) -> Self + where + F: FnOnce(ArgGroup) -> ArgGroup, + { + let id = arg_id.as_ref(); + let index = self + .groups + .iter() + .position(|g| g.get_id() == id) + .unwrap_or_else(|| panic!("Group `{id}` is undefined")); + let a = self.groups.remove(index); + + self.groups.push(f(a)); + self + } /// Allows one to mutate a [`Command`] after it's been added as a subcommand. /// /// This can be useful for modifying auto-generated arguments of nested subcommands with @@ -1070,7 +1109,7 @@ impl Command { /// Replace prior occurrences of arguments rather than error /// /// For any argument that would conflict with itself by default (e.g. - /// [`ArgAction::Set`][ArgAction::Set], it will now override itself. + /// [`ArgAction::Set`], it will now override itself. /// /// This is the equivalent to saying the `foo` arg using [`Arg::overrides_with("foo")`] for all /// defined arguments. @@ -1359,7 +1398,7 @@ impl Command { /// assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument); /// ``` /// - /// You can create a custom version flag with [`ArgAction::Help`], [`ArgAction::HelpShort`], or + /// You can create a custom help flag with [`ArgAction::Help`], [`ArgAction::HelpShort`], or /// [`ArgAction::HelpLong`] /// ```rust /// # use clap_builder as clap; @@ -2049,6 +2088,21 @@ impl Command { self } + /// Flatten subcommand help into the current command's help + /// + /// This shows a summary of subcommands within the usage and help for the current command, similar to + /// `git stash --help` showing information on `push`, `pop`, etc. + /// To see more information, a user can still pass `--help` to the individual subcommands. + #[inline] + #[must_use] + pub fn flatten_help(self, yes: bool) -> Self { + if yes { + self.setting(AppSettings::FlattenHelp) + } else { + self.unset_setting(AppSettings::FlattenHelp) + } + } + /// Set the default section heading for future args. /// /// This will be used for any arg that hasn't had [`Arg::help_heading`] called. @@ -3335,6 +3389,20 @@ impl Command { self.usage_name.as_deref() } + #[inline] + #[cfg(feature = "usage")] + pub(crate) fn get_usage_name_fallback(&self) -> &str { + self.get_usage_name() + .unwrap_or_else(|| self.get_bin_name_fallback()) + } + + #[inline] + #[cfg(not(feature = "usage"))] + #[allow(dead_code)] + pub(crate) fn get_usage_name_fallback(&self) -> &str { + self.get_bin_name_fallback() + } + /// Get the name of the binary. #[inline] pub fn get_display_name(&self) -> Option<&str> { @@ -3347,6 +3415,12 @@ impl Command { self.bin_name.as_deref() } + /// Get the name of the binary. + #[inline] + pub(crate) fn get_bin_name_fallback(&self) -> &str { + self.bin_name.as_deref().unwrap_or_else(|| self.get_name()) + } + /// Set binary name. Uses `&mut self` instead of `self`. pub fn set_bin_name(&mut self, name: impl Into<String>) { self.bin_name = Some(name.into()); @@ -3410,6 +3484,12 @@ impl Command { self.long_about.as_ref() } + /// Get the custom section heading specified via [`Command::flatten_help`]. + #[inline] + pub fn is_flatten_help_set(&self) -> bool { + self.is_set(AppSettings::FlattenHelp) + } + /// Get the custom section heading specified via [`Command::next_help_heading`]. /// /// [`Command::help_heading`]: Command::help_heading() diff --git a/vendor/clap_builder/src/builder/styled_str.rs b/vendor/clap_builder/src/builder/styled_str.rs index df0f1b03b..e06ddbc9e 100644 --- a/vendor/clap_builder/src/builder/styled_str.rs +++ b/vendor/clap_builder/src/builder/styled_str.rs @@ -45,10 +45,6 @@ impl StyledStr { self.0.push_str(msg); } - pub(crate) fn trim(&mut self) { - self.0 = self.0.trim().to_owned() - } - pub(crate) fn trim_start_lines(&mut self) { if let Some(pos) = self.0.find('\n') { let (leading, help) = self.0.split_at(pos + 1); diff --git a/vendor/clap_builder/src/output/help_template.rs b/vendor/clap_builder/src/output/help_template.rs index da2e75413..9fe7211b3 100644 --- a/vendor/clap_builder/src/output/help_template.rs +++ b/vendor/clap_builder/src/output/help_template.rs @@ -393,9 +393,11 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { .filter_map(|arg| arg.get_help_heading()) .collect::<FlatSet<_>>(); + let flatten = self.cmd.is_flatten_help_set(); + let mut first = true; - if subcmds { + if subcmds && !flatten { if !first { self.writer.push_str("\n\n"); } @@ -474,6 +476,11 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { } } } + if subcmds && flatten { + let mut cmd = self.cmd.clone(); + cmd.build(); + self.write_flat_subcommands(&cmd, &mut first); + } } /// Sorts arguments by length and display order and write their help to the wrapped stream. @@ -874,6 +881,70 @@ impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { /// Subcommand handling impl<'cmd, 'writer> HelpTemplate<'cmd, 'writer> { /// Writes help for subcommands of a Parser Object to the wrapped stream. + fn write_flat_subcommands(&mut self, cmd: &Command, first: &mut bool) { + debug!( + "HelpTemplate::write_flat_subcommands, cmd={}, first={}", + cmd.get_name(), + *first + ); + use std::fmt::Write as _; + let header = &self.styles.get_header(); + + let mut ord_v = Vec::new(); + for subcommand in cmd + .get_subcommands() + .filter(|subcommand| should_show_subcommand(subcommand)) + { + ord_v.push(( + subcommand.get_display_order(), + subcommand.get_name(), + subcommand, + )); + } + ord_v.sort_by(|a, b| (a.0, &a.1).cmp(&(b.0, &b.1))); + for (_, _, subcommand) in ord_v { + if !*first { + self.writer.push_str("\n\n"); + } + *first = false; + + let heading = subcommand.get_usage_name_fallback(); + let about = subcommand + .get_about() + .or_else(|| subcommand.get_long_about()) + .unwrap_or_default(); + + let _ = write!( + self.writer, + "{}{heading}:{}\n", + header.render(), + header.render_reset() + ); + if !about.is_empty() { + let _ = write!(self.writer, "{about}\n",); + } + + let mut sub_help = HelpTemplate { + writer: self.writer, + cmd: subcommand, + styles: self.styles, + usage: self.usage, + next_line_help: self.next_line_help, + term_w: self.term_w, + use_long: self.use_long, + }; + let args = subcommand + .get_arguments() + .filter(|arg| should_show_arg(self.use_long, arg) && !arg.is_global_set()) + .collect::<Vec<_>>(); + sub_help.write_args(&args, heading, option_sort_key); + if subcommand.is_flatten_help_set() { + sub_help.write_flat_subcommands(subcommand, first); + } + } + } + + /// 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 _; diff --git a/vendor/clap_builder/src/output/usage.rs b/vendor/clap_builder/src/output/usage.rs index 884a64df9..d75b704ba 100644 --- a/vendor/clap_builder/src/output/usage.rs +++ b/vendor/clap_builder/src/output/usage.rs @@ -14,6 +14,7 @@ use crate::util::FlatSet; use crate::util::Id; static DEFAULT_SUB_VALUE_NAME: &str = "COMMAND"; +const USAGE_SEP: &str = "\n "; pub(crate) struct Usage<'cmd> { cmd: &'cmd Command, @@ -39,8 +40,6 @@ impl<'cmd> Usage<'cmd> { // any subcommands have been parsed (so as to give subcommands their own usage recursively) pub(crate) fn create_usage_with_title(&self, used: &[Id]) -> Option<StyledStr> { 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(); let _ = write!( @@ -49,28 +48,49 @@ impl<'cmd> Usage<'cmd> { self.styles.get_usage().render(), self.styles.get_usage().render_reset() ); - styled.push_styled(&usage); + if self.write_usage_no_title(&mut styled, used) { + styled.trim_end(); + } else { + return None; + } + debug!("Usage::create_usage_with_title: usage={styled}"); Some(styled) } // Creates a usage string (*without title*) if one was not provided by the user manually. pub(crate) fn create_usage_no_title(&self, used: &[Id]) -> Option<StyledStr> { debug!("Usage::create_usage_no_title"); + + let mut styled = StyledStr::new(); + if self.write_usage_no_title(&mut styled, used) { + styled.trim_end(); + debug!("Usage::create_usage_no_title: usage={styled}"); + Some(styled) + } else { + None + } + } + + // Creates a usage string (*without title*) if one was not provided by the user manually. + fn write_usage_no_title(&self, styled: &mut StyledStr, used: &[Id]) -> bool { + debug!("Usage::create_usage_no_title"); if let Some(u) = self.cmd.get_override_usage() { - Some(u.clone()) + styled.push_styled(u); + true } else { #[cfg(feature = "usage")] { if used.is_empty() { - Some(self.create_help_usage(true)) + self.write_help_usage(styled); } else { - Some(self.create_smart_usage(used)) + self.write_smart_usage(styled, used); } + true } #[cfg(not(feature = "usage"))] { - None + false } } } @@ -79,43 +99,97 @@ impl<'cmd> Usage<'cmd> { #[cfg(feature = "usage")] 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:?}"); + fn write_help_usage(&self, styled: &mut StyledStr) { + debug!("Usage::write_help_usage"); + use std::fmt::Write; + + if self.cmd.has_visible_subcommands() && self.cmd.is_flatten_help_set() { + if !self.cmd.is_subcommand_required_set() + || self.cmd.is_args_conflicts_with_subcommands_set() + { + self.write_arg_usage(styled, &[], true); + styled.trim_end(); + let _ = write!(styled, "{}", USAGE_SEP); + } + let mut cmd = self.cmd.clone(); + cmd.build(); + for (i, sub) in cmd + .get_subcommands() + .filter(|c| !c.is_hide_set()) + .enumerate() + { + if i != 0 { + styled.trim_end(); + let _ = write!(styled, "{}", USAGE_SEP); + } + Usage::new(sub).write_usage_no_title(styled, &[]); + } + } else { + self.write_arg_usage(styled, &[], true); + self.write_subcommand_usage(styled); + } + } + + // Creates a context aware usage string, or "smart usage" from currently used + // args, and requirements + fn write_smart_usage(&self, styled: &mut StyledStr, used: &[Id]) { + debug!("Usage::create_smart_usage"); + use std::fmt::Write; + let placeholder = &self.styles.get_placeholder(); + + self.write_arg_usage(styled, used, true); + + if self.cmd.is_subcommand_required_set() { + 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() + ); + } + } + + fn write_arg_usage(&self, styled: &mut StyledStr, used: &[Id], incl_reqs: bool) { + debug!("Usage::write_arg_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()); - if !name.is_empty() { + let bin_name = self.cmd.get_usage_name_fallback(); + if !bin_name.is_empty() { // the trim won't properly remove a leading space due to the formatting let _ = write!( styled, - "{}{name}{}", + "{}{bin_name}{} ", literal.render(), literal.render_reset() ); } - if self.needs_options_tag() { + if used.is_empty() && self.needs_options_tag() { let _ = write!( styled, - "{} [OPTIONS]{}", + "{}[OPTIONS]{} ", placeholder.render(), placeholder.render_reset() ); } - self.write_args(&[], !incl_reqs, &mut styled); + self.write_args(styled, used, !incl_reqs); + } + + fn write_subcommand_usage(&self, styled: &mut StyledStr) { + debug!("Usage::write_subcommand_usage"); + use std::fmt::Write as _; // incl_reqs is only false when this function is called recursively - if self.cmd.has_visible_subcommands() && incl_reqs - || self.cmd.is_allow_external_subcommands_set() - { + if self.cmd.has_visible_subcommands() || self.cmd.is_allow_external_subcommands_set() { + let literal = &self.styles.get_literal(); + let placeholder = &self.styles.get_placeholder(); let value_name = self .cmd .get_subcommand_value_name() @@ -123,81 +197,42 @@ impl<'cmd> Usage<'cmd> { if self.cmd.is_subcommand_negates_reqs_set() || self.cmd.is_args_conflicts_with_subcommands_set() { - let _ = write!(styled, "\n "); + styled.trim_end(); + let _ = write!(styled, "{}", USAGE_SEP); if self.cmd.is_args_conflicts_with_subcommands_set() { + let bin_name = self.cmd.get_usage_name_fallback(); // Short-circuit full usage creation since no args will be relevant let _ = write!( styled, - "{}{name}{}", + "{}{bin_name}{} ", literal.render(), literal.render_reset() ); } else { - styled.push_styled(&self.create_help_usage(false)); + self.write_arg_usage(styled, &[], false); } let _ = write!( styled, - " {}<{value_name}>{}", + "{}<{value_name}>{}", placeholder.render(), placeholder.render_reset() ); } else if self.cmd.is_subcommand_required_set() { let _ = write!( styled, - " {}<{value_name}>{}", + "{}<{value_name}>{}", placeholder.render(), placeholder.render_reset() ); } else { let _ = write!( styled, - " {}[{value_name}]{}", + "{}[{value_name}]{}", placeholder.render(), placeholder.render_reset() ); } } - styled.trim(); - debug!("Usage::create_help_usage: usage={styled}"); - styled - } - - // Creates a context aware usage string, or "smart usage" from currently used - // 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(); - - 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() { - 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 } // Determines if we need the `[OPTIONS]` tag in the usage string @@ -251,15 +286,8 @@ 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.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:?}",); + pub(crate) fn write_args(&self, styled: &mut StyledStr, incls: &[Id], force_optional: bool) { + debug!("Usage::write_args: incls={incls:?}",); use std::fmt::Write as _; let literal = &self.styles.get_literal(); @@ -366,17 +394,20 @@ impl<'cmd> Usage<'cmd> { } } - let mut ret_val = Vec::new(); if !force_optional { - ret_val.extend(required_opts); - ret_val.extend(required_groups); + for arg in required_opts { + styled.push_styled(&arg); + styled.push_str(" "); + } + for arg in required_groups { + styled.push_styled(&arg); + styled.push_str(" "); + } } - for pos in required_positionals.into_iter().flatten() { - ret_val.push(pos); + for arg in required_positionals.into_iter().flatten() { + styled.push_styled(&arg); + styled.push_str(" "); } - - debug!("Usage::get_args: ret_val={ret_val:?}"); - ret_val } pub(crate) fn get_required_usage_from( diff --git a/vendor/clap_builder/src/parser/matches/arg_matches.rs b/vendor/clap_builder/src/parser/matches/arg_matches.rs index 8390b0b58..e80c39b45 100644 --- a/vendor/clap_builder/src/parser/matches/arg_matches.rs +++ b/vendor/clap_builder/src/parser/matches/arg_matches.rs @@ -514,7 +514,7 @@ impl ArgMatches { MatchesError::unwrap(id, self.try_contains_id(id)) } - /// Iterate over [`Arg`][crate::Arg] and [`ArgGroup`][crate::ArgGroup] [`Id`][crate::Id]s via [`ArgMatches::ids`]. + /// Iterate over [`Arg`][crate::Arg] and [`ArgGroup`][crate::ArgGroup] [`Id`]s via [`ArgMatches::ids`]. /// /// # Examples /// @@ -1325,7 +1325,7 @@ pub(crate) struct SubCommand { pub(crate) matches: ArgMatches, } -/// Iterate over [`Arg`][crate::Arg] and [`ArgGroup`][crate::ArgGroup] [`Id`][crate::Id]s via [`ArgMatches::ids`]. +/// Iterate over [`Arg`][crate::Arg] and [`ArgGroup`][crate::ArgGroup] [`Id`]s via [`ArgMatches::ids`]. /// /// # Examples /// diff --git a/vendor/clap_builder/src/parser/parser.rs b/vendor/clap_builder/src/parser/parser.rs index 4b24eb0de..93616d68a 100644 --- a/vendor/clap_builder/src/parser/parser.rs +++ b/vendor/clap_builder/src/parser/parser.rs @@ -501,10 +501,7 @@ impl<'cmd> Parser<'cmd> { self.cmd, arg_os.display().to_string(), candidates, - self.cmd - .get_bin_name() - .unwrap_or_else(|| self.cmd.get_name()) - .to_owned(), + self.cmd.get_bin_name_fallback().to_owned(), suggested_trailing_arg, Usage::new(self.cmd).create_usage_with_title(&[]), ); diff --git a/vendor/clap_builder/src/parser/validator.rs b/vendor/clap_builder/src/parser/validator.rs index 17fb7c1e2..55f4633cc 100644 --- a/vendor/clap_builder/src/parser/validator.rs +++ b/vendor/clap_builder/src/parser/validator.rs @@ -63,10 +63,7 @@ impl<'cmd> Validator<'cmd> { } } if !has_subcmd && self.cmd.is_subcommand_required_set() { - let bn = self - .cmd - .get_bin_name() - .unwrap_or_else(|| self.cmd.get_name()); + let bn = self.cmd.get_bin_name_fallback(); return Err(Error::missing_subcommand( self.cmd, bn.to_string(), |