From bb0eab8a566a6f2c10178468283500d2351e27f2 Mon Sep 17 00:00:00 2001 From: CreepySkeleton Date: Tue, 10 Mar 2020 00:16:55 +0300 Subject: [PATCH] WIP --- clap_generate/src/generators/mod.rs | 9 +- clap_generate/src/generators/shells/elvish.rs | 8 +- clap_generate/src/generators/shells/fish.rs | 4 +- .../src/generators/shells/powershell.rs | 8 +- clap_generate/src/generators/shells/zsh.rs | 13 ++- clap_generate/src/macros.rs | 30 ++--- src/build/app/mod.rs | 25 ++++- src/build/app/view.rs | 103 ++++++++++++++++++ src/build/arg/mod.rs | 68 +++++------- src/build/arg/settings.rs | 9 +- src/build/arg/view.rs | 97 +++++++++++++++++ src/build/mod.rs | 4 +- src/macros.rs | 31 ++---- src/output/help.rs | 3 +- 14 files changed, 298 insertions(+), 114 deletions(-) create mode 100644 src/build/app/view.rs create mode 100644 src/build/arg/view.rs diff --git a/clap_generate/src/generators/mod.rs b/clap_generate/src/generators/mod.rs index 483b920e428..a52a5965fc7 100644 --- a/clap_generate/src/generators/mod.rs +++ b/clap_generate/src/generators/mod.rs @@ -177,9 +177,9 @@ pub trait Generator { fn flags<'b>(p: &'b App<'b>) -> Vec { debugln!("flags: name={}", p.name); - let mut flags: Vec<_> = flags!(p).cloned().collect(); + let mut flags: Vec<_> = p.view().flags().cloned().collect(); - if flags.iter().find(|x| x.name == "help").is_none() { + if flags.iter().find(|x| x.view().name() == "help").is_none() { flags.push( Arg::with_name("help") .short('h') @@ -189,7 +189,10 @@ pub trait Generator { } if !p.is_set(AppSettings::DisableVersion) - && flags.iter().find(|x| x.name == "version").is_none() + && flags + .iter() + .find(|x| x.view().name() == "version") + .is_none() { flags.push( Arg::with_name("version") diff --git a/clap_generate/src/generators/shells/elvish.rs b/clap_generate/src/generators/shells/elvish.rs index aa4bfa5cc31..b66a6d038a5 100644 --- a/clap_generate/src/generators/shells/elvish.rs +++ b/clap_generate/src/generators/shells/elvish.rs @@ -79,14 +79,14 @@ fn generate_inner<'b>( for option in opts!(p) { if let Some(data) = option.short { - let tooltip = get_tooltip(option.help, data); + let tooltip = get_tooltip(option.view().help(), data); completions.push_str(&preamble); completions.push_str(format!("-{} '{}'", data, tooltip).as_str()); } if let Some(data) = option.long { - let tooltip = get_tooltip(option.help, data); + let tooltip = get_tooltip(option.view().help(), data); completions.push_str(&preamble); completions.push_str(format!("--{} '{}'", data, tooltip).as_str()); @@ -95,14 +95,14 @@ fn generate_inner<'b>( for flag in Elvish::flags(p) { if let Some(data) = flag.short { - let tooltip = get_tooltip(flag.help, data); + let tooltip = get_tooltip(flag.view().help(), data); completions.push_str(&preamble); completions.push_str(format!("-{} '{}'", data, tooltip).as_str()); } if let Some(data) = flag.long { - let tooltip = get_tooltip(flag.help, data); + let tooltip = get_tooltip(flag.view().help(), data); completions.push_str(&preamble); completions.push_str(format!("--{} '{}'", data, tooltip).as_str()); diff --git a/clap_generate/src/generators/shells/fish.rs b/clap_generate/src/generators/shells/fish.rs index 966f08d0d2d..9d6050dc194 100644 --- a/clap_generate/src/generators/shells/fish.rs +++ b/clap_generate/src/generators/shells/fish.rs @@ -65,7 +65,7 @@ fn gen_fish_inner(root_command: &str, app: &App, buffer: &mut String) { template.push_str(format!(" -l {}", data).as_str()); } - if let Some(data) = option.help { + if let Some(data) = option.view().help() { template.push_str(format!(" -d '{}'", escape_string(data)).as_str()); } @@ -88,7 +88,7 @@ fn gen_fish_inner(root_command: &str, app: &App, buffer: &mut String) { template.push_str(format!(" -l {}", data).as_str()); } - if let Some(data) = flag.help { + if let Some(data) = flag.view().help() { template.push_str(format!(" -d '{}'", escape_string(data)).as_str()); } diff --git a/clap_generate/src/generators/shells/powershell.rs b/clap_generate/src/generators/shells/powershell.rs index 3d83c4a2853..074a70afa2f 100644 --- a/clap_generate/src/generators/shells/powershell.rs +++ b/clap_generate/src/generators/shells/powershell.rs @@ -86,7 +86,7 @@ fn generate_inner<'b>( for option in opts!(p) { if let Some(data) = option.short { - let tooltip = get_tooltip(option.help, data); + let tooltip = get_tooltip(option.view().help(), data); completions.push_str(&preamble); completions.push_str( @@ -99,7 +99,7 @@ fn generate_inner<'b>( } if let Some(data) = option.long { - let tooltip = get_tooltip(option.help, data); + let tooltip = get_tooltip(option.view().help(), data); completions.push_str(&preamble); completions.push_str( @@ -114,7 +114,7 @@ fn generate_inner<'b>( for flag in PowerShell::flags(p) { if let Some(data) = flag.short { - let tooltip = get_tooltip(flag.help, data); + let tooltip = get_tooltip(flag.view().help(), data); completions.push_str(&preamble); completions.push_str( @@ -127,7 +127,7 @@ fn generate_inner<'b>( } if let Some(data) = flag.long { - let tooltip = get_tooltip(flag.help, data); + let tooltip = get_tooltip(flag.view().help(), data); completions.push_str(&preamble); completions.push_str( diff --git a/clap_generate/src/generators/shells/zsh.rs b/clap_generate/src/generators/shells/zsh.rs index 3acdaab247c..d181d51f016 100644 --- a/clap_generate/src/generators/shells/zsh.rs +++ b/clap_generate/src/generators/shells/zsh.rs @@ -360,8 +360,8 @@ fn write_opts_of(p: &App) -> String { for o in opts!(p) { debugln!("Zsh::write_opts_of:iter: o={}", o.name); - let help = o.help.map_or(String::new(), escape_help); - let mut conflicts = get_zsh_arg_conflicts!(p, o, INTERNAL_ERROR_MSG); + let help = o.view().help().map_or(String::new(), escape_help); + let mut conflicts = get_zsh_arg_conflicts!(p, o); conflicts = if conflicts.is_empty() { String::new() @@ -432,7 +432,7 @@ fn write_flags_of(p: &App) -> String { for f in Zsh::flags(p) { debugln!("Zsh::write_flags_of:iter: f={}", f.name); - let help = f.help.map_or(String::new(), escape_help); + let help = f.view().help().map_or(String::new(), escape_help); let mut conflicts = get_zsh_arg_conflicts!(p, f, INTERNAL_ERROR_MSG); conflicts = if conflicts.is_empty() { @@ -496,10 +496,11 @@ fn write_positionals_of(p: &App) -> String { let a = format!( "'{optional}:{name}{help}:{action}' \\", optional = optional, - name = arg.name, + name = arg.view().name(), help = arg - .help - .map_or("".to_owned(), |v| " -- ".to_owned() + v) + .view() + .help() + .map_or(String::new(), |v| " -- ".to_owned() + v) .replace("[", "\\[") .replace("]", "\\]") .replace(":", "\\:"), diff --git a/clap_generate/src/macros.rs b/clap_generate/src/macros.rs index 748b258ed7a..2a12064bf37 100644 --- a/clap_generate/src/macros.rs +++ b/clap_generate/src/macros.rs @@ -8,27 +8,21 @@ macro_rules! w { } macro_rules! get_zsh_arg_conflicts { - ($app:expr, $arg:ident, $msg:ident) => { - if let Some(ref conf_vec) = $arg.blacklist { - let mut v = vec![]; + ($app:expr, $arg:ident) => {{ + let mut v = vec![]; - for arg_name in conf_vec { - let arg = find!($app, arg_name).expect($msg); - - if let Some(s) = arg.short { - v.push(format!("-{}", s)); - } - - if let Some(l) = arg.long { - v.push(format!("--{}", l)); - } + for arg in $app.view().conflicts_with($arg) { + if let Some(s) = arg.short { + v.push(format!("-{}", s)); } - v.join(" ") - } else { - String::new() + if let Some(l) = arg.long { + v.push(format!("--{}", l)); + } } - }; + + v.join(" ") + }}; } #[cfg(feature = "debug")] @@ -76,7 +70,7 @@ macro_rules! find { $what!($app).find(|a| &a.name == $name) }; ($app:expr, $name:expr) => { - $app.args.args.iter().find(|a| { + $app.args.args.iter().find_map(|a| { if let Some(v) = a.index { &v == $name } else { diff --git a/src/build/app/mod.rs b/src/build/app/mod.rs index 7d73af7d9a2..b47a08e36a6 100644 --- a/src/build/app/mod.rs +++ b/src/build/app/mod.rs @@ -1,5 +1,8 @@ mod settings; -pub use self::settings::{AppFlags, AppSettings}; +pub mod view; +pub(crate) use self::settings::AppFlags; +pub use self::settings::AppSettings; +pub use self::view::AppView; // Std use std::collections::HashMap; @@ -1392,6 +1395,11 @@ impl<'b> App<'b> { self._do_parse(&mut it) } + + /// Build an [`AppView`] instance corresponding to `self`. + pub fn view<'app>(&'app self) -> AppView<'app, 'b> { + AppView::from_ref(self) + } } // Internally used only @@ -1429,7 +1437,7 @@ impl<'b> App<'b> { } #[allow(clippy::debug_assert_with_mut_call)] - // used in clap_generate (https://github.com/clap-rs/clap_generate) + // PUB_HIDDEN: used in clap_generate #[doc(hidden)] pub fn _build(&mut self) { debugln!("App::_build;"); @@ -1503,6 +1511,7 @@ impl<'b> App<'b> { panic!(abort_message); } } + for sub_app in &app.subcommands { Self::_panic_on_missing_help(&sub_app, help_required_globally); } @@ -1536,7 +1545,7 @@ impl<'b> App<'b> { true } - pub fn _propagate(&mut self, prop: Propagation) { + pub(crate) fn _propagate(&mut self, prop: Propagation) { macro_rules! propagate_subcmd { ($_self:expr, $sc:expr) => {{ // We have to create a new scope in order to tell rustc the borrow of `sc` is @@ -1605,6 +1614,7 @@ impl<'b> App<'b> { self.args.push(help); } + if !(self .args .args @@ -1622,6 +1632,7 @@ impl<'b> App<'b> { self.args.push(version); } + if self.has_subcommands() && !self.is_set(AppSettings::DisableHelpSubcommand) && !subcommands!(self).any(|s| s.id == HELP_HASH) @@ -1719,7 +1730,7 @@ impl<'b> App<'b> { true } - // used in clap_generate (https://github.com/clap-rs/clap_generate) + // PUB_HIDDEN: used in clap_generate #[doc(hidden)] pub fn _build_bin_names(&mut self) { debugln!("App::_build_bin_names;"); @@ -1854,7 +1865,8 @@ impl<'b> App<'b> { } pub fn has_flags(&self) -> bool { - flags!(self).count() > 0 + let view = self.view().flags(); + view.count() > 0 } pub fn has_positionals(&self) -> bool { @@ -1866,7 +1878,8 @@ impl<'b> App<'b> { } pub fn has_visible_flags(&self) -> bool { - flags!(self).any(|o| !o.is_set(ArgSettings::Hidden)) + let view = self.view(); + view.flags().any(|o| !o.is_set(ArgSettings::Hidden)) } pub fn has_visible_positionals(&self) -> bool { diff --git a/src/build/app/view.rs b/src/build/app/view.rs new file mode 100644 index 00000000000..32bf9ac208a --- /dev/null +++ b/src/build/app/view.rs @@ -0,0 +1,103 @@ +//! A shim layer that allows querying certain info about `App`, +//! despite the corresponding fields being private. + +use super::*; +use crate::INTERNAL_ERROR_MSG; + +#[allow(missing_debug_implementations)] +pub struct AppView<'app, 'help> { + id: Id, + name: &'app String, + bin_name: Option<&'app String>, + author: Option<&'help str>, + version: Option<&'help str>, + long_version: Option<&'help str>, + about: Option<&'help str>, + long_about: Option<&'help str>, + more_help: Option<&'help str>, + pre_help: Option<&'help str>, + aliases: Option<&'app Vec<(&'help str, bool)>>, // (name, visible) + usage_str: Option<&'help str>, + usage: Option<&'app String>, + help_str: Option<&'help str>, + disp_ord: usize, + term_w: Option, + max_w: Option, + template: Option<&'help str>, + settings: AppFlags, + g_settings: AppFlags, + args: &'app MKeyMap<'help>, + subcommands: &'app Vec>, + groups: &'app Vec>, + help_headings: &'app Vec>, +} + +impl<'app, 'help> AppView<'app, 'help> { + pub(crate) fn from_ref(app: &'app App<'help>) -> AppView<'app, 'help> { + AppView { + id: app.id, + name: &app.name, + bin_name: app.bin_name.as_ref(), + author: app.author, + version: app.version, + long_version: app.long_version, + about: app.about, + long_about: app.long_about, + more_help: app.more_help, + pre_help: app.pre_help, + aliases: app.aliases.as_ref(), + usage_str: app.usage_str, + usage: app.usage.as_ref(), + help_str: app.help_str, + disp_ord: app.disp_ord, + term_w: app.term_w, + max_w: app.max_w, + template: app.template, + settings: app.settings, + g_settings: app.g_settings, + args: &app.args, + subcommands: &app.subcommands, + groups: &app.groups, + help_headings: &app.help_headings, + } + } +} + +impl<'app, 'help: 'app> AppView<'app, 'help> { + /// The list of args the given arg conflicts with. + /// + /// # Panics + /// + /// If `arg` conflicts with some args `self` don't know about, + /// it will panic. + pub fn conflicts_with(&self, arg: &'app Arg<'_>) -> Vec<&'app Arg<'help>> { + arg.blacklist.as_ref().map_or(vec![], |conflict_ids| { + conflict_ids + .iter() + .map(|id| { + self.args + .args + .iter() + .find(|arg| arg.id == *id) + .expect(INTERNAL_ERROR_MSG) + }) + .collect() + }) + } + + pub fn flags(&self) -> impl Iterator> { + self.args + .args + .iter() + .filter(|a| !a.is_set(ArgSettings::TakesValue) && !a.view().index().is_some()) + .filter(|a| !a.view().help_heading().is_some()) + } + + pub fn args(&'app self) -> impl Iterator> { + self.args.args.iter() + } + + // pub fn args_mut(&'app mut self) -> impl Iterator> { + // self.args.args.iter_mut() + // } +} diff --git a/src/build/arg/mod.rs b/src/build/arg/mod.rs index 291f1504852..252e31c4e5d 100644 --- a/src/build/arg/mod.rs +++ b/src/build/arg/mod.rs @@ -1,5 +1,9 @@ mod settings; -pub use self::settings::{ArgFlags, ArgSettings}; +pub mod view; + +pub(crate) use self::settings::ArgFlags; +pub use self::settings::ArgSettings; +pub use self::view::ArgView; // Std use std::borrow::Cow; @@ -54,18 +58,13 @@ type Id = u64; #[allow(missing_debug_implementations)] #[derive(Default, Clone)] pub struct Arg<'help> { + pub(crate) id: Id, + pub(crate) name: &'help str, + pub(crate) help: Option<&'help str>, + pub(crate) long_help: Option<&'help str>, + pub(crate) blacklist: Option>, #[doc(hidden)] - pub id: Id, - #[doc(hidden)] - pub name: &'help str, - #[doc(hidden)] - pub help: Option<&'help str>, - #[doc(hidden)] - pub long_help: Option<&'help str>, - #[doc(hidden)] - pub blacklist: Option>, - #[doc(hidden)] - pub settings: ArgFlags, + pub(crate) settings: ArgFlags, #[doc(hidden)] pub r_unless: Option>, #[doc(hidden)] @@ -121,15 +120,6 @@ pub struct Arg<'help> { } impl<'help> Arg<'help> { - /// @TODO @p2 @docs @v3-beta1: Write Docs - pub fn new(t: T) -> Self { - Arg { - id: t.key(), - disp_ord: 999, - unified_ord: 999, - ..Default::default() - } - } /// Creates a new instance of [`Arg`] using a unique string name. The name will be used to get /// information about whether or not the argument was used at runtime, get values, set /// relationships with other args, etc.. @@ -817,7 +807,7 @@ impl<'help> Arg<'help> { /// assert!(res.is_err()); /// assert_eq!(res.unwrap_err().kind, ErrorKind::ArgumentConflict); /// ``` - /// + /// /// [`Arg::conflicts_with_all(names)`]: ./struct.Arg.html#method.conflicts_with_all /// [`Arg::exclusive(true)`]: ./struct.Arg.html#method.exclusive @@ -4066,14 +4056,22 @@ impl<'help> Arg<'help> { self } - #[doc(hidden)] - pub fn _build(&mut self) { + /// Make a viewer for this arg, see [`view`]. + pub fn view<'arg>(&'arg self) -> ArgView<'arg, 'help> { + ArgView::from_ref(self) + } +} + +// NOT PUBLIC API, SUBJECT TO CHANGE AND DISAPPEAR DISREGARDING SEMVER +impl<'help> Arg<'help> { + pub(crate) fn _build(&mut self) { if (self.is_set(ArgSettings::UseValueDelimiter) || self.is_set(ArgSettings::RequireDelimiter)) && self.val_delim.is_none() { self.val_delim = Some(','); } + if self.index.is_some() || (self.short.is_none() && self.long.is_none()) { if self.max_vals.is_some() || self.min_vals.is_some() @@ -4091,31 +4089,23 @@ impl<'help> Arg<'help> { } } - // @TODO @p6 @naming @internal: rename to set_mut - #[doc(hidden)] - pub fn setb(&mut self, s: ArgSettings) { + pub(crate) fn setb(&mut self, s: ArgSettings) { self.settings.set(s); } - // @TODO @p6 @naming @internal: rename to unset_mut - #[doc(hidden)] - pub fn unsetb(&mut self, s: ArgSettings) { + pub(crate) fn unsetb(&mut self, s: ArgSettings) { self.settings.unset(s); } - #[doc(hidden)] - pub fn has_switch(&self) -> bool { + pub(crate) fn has_switch(&self) -> bool { self.short.is_some() || self.long.is_some() } - #[doc(hidden)] - pub fn longest_filter(&self) -> bool { + pub(crate) fn longest_filter(&self) -> bool { self.is_set(ArgSettings::TakesValue) || self.long.is_some() || self.short.is_none() } - // Used for positionals when printing - #[doc(hidden)] - pub fn multiple_str(&self) -> &str { + pub(crate) fn multiple_str(&self) -> &str { let mult_vals = self .val_names .as_ref() @@ -4130,9 +4120,7 @@ impl<'help> Arg<'help> { } } - // Used for positionals when printing - #[doc(hidden)] - pub fn name_no_brackets(&self) -> Cow { + pub(crate) fn name_no_brackets(&self) -> Cow { debugln!("PosBuilder::name_no_brackets:{}", self.name); let mut delim = String::new(); delim.push(if self.is_set(ArgSettings::RequireDelimiter) { diff --git a/src/build/arg/settings.rs b/src/build/arg/settings.rs index 520859e6bf4..692fd0befa7 100644 --- a/src/build/arg/settings.rs +++ b/src/build/arg/settings.rs @@ -29,15 +29,8 @@ bitflags! { } } -#[doc(hidden)] #[derive(Debug, Clone, Copy)] -pub struct ArgFlags(Flags); - -impl ArgFlags { - pub fn new() -> Self { - ArgFlags::default() - } -} +pub(crate) struct ArgFlags(Flags); // @TODO @p6 @internal: Reorder alphabetically impl_settings! { ArgSettings, ArgFlags, diff --git a/src/build/arg/view.rs b/src/build/arg/view.rs new file mode 100644 index 00000000000..9e925206bd3 --- /dev/null +++ b/src/build/arg/view.rs @@ -0,0 +1,97 @@ +//! A shim layer that allows querying certain info about `Arg`, +//! despite the corresponding fields being private. + +use super::*; + +#[allow(missing_debug_implementations)] +pub struct ArgView<'arg, 'help> { + name: &'help str, + help: Option<&'help str>, + blacklist: Option<&'arg Vec>, + settings: ArgFlags, + r_unless: Option<&'arg Vec>, + overrides: Option<&'arg Vec>, + groups: Option<&'arg Vec>, + requires: Option<&'arg Vec<(Option<&'help str>, Id)>>, + short: Option, + long: Option<&'help str>, + aliases: Option<&'arg Vec<(&'help str, bool)>>, // (name, visible) + disp_ord: usize, + unified_ord: usize, + possible_vals: Option<&'arg Vec<&'help str>>, + val_names: Option<&'arg VecMap<&'help str>>, + num_vals: Option, + max_vals: Option, + min_vals: Option, + validator: Option<&'arg Validator>, + validator_os: Option<&'arg ValidatorOs>, + val_delim: Option, + default_vals: Option<&'arg Vec<&'help OsStr>>, + default_vals_ifs: Option<&'arg VecMap<(Id, Option<&'help OsStr>, &'help OsStr)>>, + env: Option<&'arg (&'help OsStr, Option)>, + terminator: Option<&'help str>, + index: Option, + r_ifs: Option<&'arg Vec<(Id, &'help str)>>, + help_heading: Option<&'help str>, + global: bool, + exclusive: bool, +} + +impl<'arg, 'help> ArgView<'arg, 'help> { + pub(crate) fn from_ref(arg: &'arg Arg<'help>) -> Self { + ArgView { + name: arg.name, + help: arg.help, + blacklist: arg.blacklist.as_ref(), + settings: arg.settings, + r_unless: arg.r_unless.as_ref(), + overrides: arg.overrides.as_ref(), + groups: arg.groups.as_ref(), + requires: arg.requires.as_ref(), + short: arg.short, + long: arg.long, + aliases: arg.aliases.as_ref(), + disp_ord: arg.disp_ord, + unified_ord: arg.unified_ord, + possible_vals: arg.possible_vals.as_ref(), + val_names: arg.val_names.as_ref(), + num_vals: arg.num_vals, + max_vals: arg.max_vals, + min_vals: arg.min_vals, + validator: arg.validator.as_ref(), + validator_os: arg.validator_os.as_ref(), + val_delim: arg.val_delim, + default_vals: arg.default_vals.as_ref(), + default_vals_ifs: arg.default_vals_ifs.as_ref(), + env: arg.env.as_ref(), + terminator: arg.terminator, + index: arg.index, + r_ifs: arg.r_ifs.as_ref(), + help_heading: arg.help_heading, + global: arg.global, + exclusive: arg.exclusive, + } + } +} + +impl<'arg, 'help> ArgView<'arg, 'help> { + /// The arg index, as passed to [`Arg::index`]. + pub fn index(&self) -> Option { + self.index + } + + /// The heading, as passed to [`Arg::help_heading`]. + pub fn help_heading(&self) -> Option<&'help str> { + self.help_heading + } + + /// The help string, as passed to [`Arg::help`]. + pub fn help(&self) -> Option<&'help str> { + self.help + } + + /// The name the arg was created with. + pub fn name(&self) -> &'help str { + self.name + } +} diff --git a/src/build/mod.rs b/src/build/mod.rs index 3d67ba6be20..86620ee2641 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -7,7 +7,7 @@ pub mod arg; mod arg_group; mod usage_parser; -pub use self::app::{App, AppFlags, AppSettings, Propagation}; -pub use self::arg::{Arg, ArgFlags, ArgSettings}; +pub use self::app::{App, AppSettings, Propagation}; +pub use self::arg::{Arg, ArgSettings}; pub use self::arg_group::ArgGroup; pub use self::usage_parser::UsageParser; diff --git a/src/macros.rs b/src/macros.rs index 746b8306fc6..b6b6db3e2af 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -922,31 +922,22 @@ macro_rules! write_nspaces { #[macro_export] #[doc(hidden)] -macro_rules! flags { - ($app:expr, $how:ident) => {{ - $app.args - .args - .$how() - .filter(|a| !a.settings.is_set($crate::ArgSettings::TakesValue) && a.index.is_none()) - .filter(|a| !a.help_heading.is_some()) - }}; +macro_rules! opts { ($app:expr) => { - $crate::flags!($app, iter) + $app.view() + .args() + .filter(|a| a.is_set($crate::ArgSettings::TakesValue) && !a.view().index().is_some()) + .filter(|a| !a.view().help_heading().is_some()) }; } -#[macro_export] -#[doc(hidden)] -macro_rules! opts { - ($app:expr, $how:ident) => {{ - $app.args - .args - .$how() - .filter(|a| a.settings.is_set($crate::ArgSettings::TakesValue) && a.index.is_none()) - .filter(|a| !a.help_heading.is_some()) - }}; +#[allow(unused_macros)] +macro_rules! opts_mut { ($app:expr) => { - opts!($app, iter) + $app.view() + .args_mut() + .filter(|a| a.is_set($crate::ArgSettings::TakesValue) && !a.has_index()) + .filter(|a| !a.has_help_heading()) }; } diff --git a/src/output/help.rs b/src/output/help.rs index 3de4cd62c48..8e352616e6f 100644 --- a/src/output/help.rs +++ b/src/output/help.rs @@ -695,7 +695,8 @@ impl<'b, 'c, 'd, 'w> Help<'b, 'c, 'd, 'w> { self.writer.write_all(b"\n\n")?; } self.color(Format::Warning("FLAGS:\n"))?; - let flags_v: Vec<_> = flags!(self.parser.app).collect(); + let view = self.parser.app.view(); + let flags_v: Vec<_> = view.flags().collect(); self.write_args(&*flags_v)?; first = false; }