fix: Loosen reflection lifetimes

Though we store a lot of values as `&'help str`, we return them as
`&'self str`, making it so they can not be used programmatically as part
of a `App::mut_arg` call.

This loosens the lifetimes so they can be used with `App::mut_arg`.
This also includes a test simulating the desired workflow described in #2966

I skipped `get_all_aliases`.  I ran into problems with lifetimes with
`all_subcommand_names`  and didn't quickly resolve it.  Rather than hold
this up, I punted on it for now.

We'll have to tighten these back up with #1041 but that will also enable
turning them into owned strings, so this will still be possible after
that issue is resolved, just the calls will be slightly different.
This commit is contained in:
Ed Page 2021-11-01 09:29:56 -05:00
parent 0adfb0fd76
commit ade6028da1
3 changed files with 28 additions and 14 deletions

View file

@ -115,7 +115,7 @@ impl<'help> App<'help> {
/// Get the long flag of the subcommand.
#[inline]
pub fn get_long_flag(&self) -> Option<&str> {
pub fn get_long_flag(&self) -> Option<&'help str> {
self.long_flag
}
@ -134,7 +134,7 @@ impl<'help> App<'help> {
///
/// [`App::about`]: App::about()
#[inline]
pub fn get_about(&self) -> Option<&str> {
pub fn get_about(&self) -> Option<&'help str> {
self.about
}
@ -142,7 +142,7 @@ impl<'help> App<'help> {
///
/// [`App::long_about`]: App::long_about()
#[inline]
pub fn get_long_about(&self) -> Option<&str> {
pub fn get_long_about(&self) -> Option<&'help str> {
self.long_about
}
@ -156,7 +156,7 @@ impl<'help> App<'help> {
/// Iterate through the *visible* aliases for this subcommand.
#[inline]
pub fn get_visible_aliases(&self) -> impl Iterator<Item = &str> {
pub fn get_visible_aliases(&self) -> impl Iterator<Item = &'help str> + '_ {
self.aliases.iter().filter(|(_, vis)| *vis).map(|a| a.0)
}
@ -180,7 +180,7 @@ impl<'help> App<'help> {
/// Iterate through the set of *all* the aliases for this subcommand, both visible and hidden.
#[inline]
pub fn get_all_aliases(&self) -> impl Iterator<Item = &str> {
pub fn get_all_aliases(&self) -> impl Iterator<Item = &str> + '_ {
self.aliases.iter().map(|a| a.0)
}

View file

@ -128,13 +128,13 @@ pub struct Arg<'help> {
impl<'help> Arg<'help> {
/// Get the name of the argument
#[inline]
pub fn get_name(&self) -> &str {
pub fn get_name(&self) -> &'help str {
self.name
}
/// Get the help specified for this argument, if any
#[inline]
pub fn get_about(&self) -> Option<&str> {
pub fn get_about(&self) -> Option<&'help str> {
self.about
}
@ -149,13 +149,13 @@ impl<'help> Arg<'help> {
/// ```
///
#[inline]
pub fn get_long_about(&self) -> Option<&str> {
pub fn get_long_about(&self) -> Option<&'help str> {
self.long_about
}
/// Get the help heading specified for this argument, if any
#[inline]
pub fn get_help_heading(&self) -> Option<&str> {
pub fn get_help_heading(&self) -> Option<&'help str> {
self.help_heading.unwrap_or_default()
}
@ -196,13 +196,13 @@ impl<'help> Arg<'help> {
/// Get the long option name for this argument, if any
#[inline]
pub fn get_long(&self) -> Option<&str> {
pub fn get_long(&self) -> Option<&'help str> {
self.long
}
/// Get visible aliases for this argument, if any
#[inline]
pub fn get_visible_aliases(&self) -> Option<Vec<&str>> {
pub fn get_visible_aliases(&self) -> Option<Vec<&'help str>> {
if self.aliases.is_empty() {
None
} else {
@ -218,7 +218,7 @@ impl<'help> Arg<'help> {
/// Get the long option name and its visible aliases, if any
#[inline]
pub fn get_long_and_visible_aliases(&self) -> Option<Vec<&str>> {
pub fn get_long_and_visible_aliases(&self) -> Option<Vec<&'help str>> {
let mut longs = match self.long {
Some(long) => vec![long],
None => return None,
@ -241,7 +241,7 @@ impl<'help> Arg<'help> {
/// Get the names of values for this argument.
#[inline]
pub fn get_value_names(&self) -> Option<&[&str]> {
pub fn get_value_names(&self) -> Option<&[&'help str]> {
if self.val_names.is_empty() {
None
} else {

View file

@ -3,7 +3,7 @@ mod utils;
use std::io::Write;
use std::str;
use clap::{App, Arg};
use clap::{App, Arg, ArgSettings};
static SCF2OP: &str = "flag present 2 times
option NOT present
@ -390,3 +390,17 @@ fn sc_short_flag_x2_short_opt_eq_pos() {
fn sc_short_flag_x2_long_opt_eq_pos() {
check_complex_output("clap-test subcmd value -f -f --option=some", SCF2OP);
}
#[test]
fn mut_arg_all() {
let mut app = utils::complex_app();
let arg_names = app
.get_arguments()
.map(|a| a.get_name())
.filter(|a| *a != "version" && *a != "help")
.collect::<Vec<_>>();
for arg_name in arg_names {
app = app.mut_arg(arg_name, |arg| arg.setting(ArgSettings::HidePossibleValues));
}
}