fix: Switch to owned types

Impact:
- Binary size: 556.6 KiB to 578.4 KiB
- build time: 6.4950 us (7% slower)
- parse time: 7.7256 us
- parse sc time: 8.1580 us (5% faster)

Fixes #1041
Fixes #2150
This commit is contained in:
Ed Page 2022-08-15 14:29:46 -05:00
parent fefeb7ee6f
commit 85f541d789
62 changed files with 800 additions and 621 deletions

View file

@ -10,7 +10,7 @@ fn build_help(cmd: &mut Command) -> String {
String::from_utf8(content).unwrap()
}
fn app_example1<'c>() -> Command<'c> {
fn app_example1() -> Command {
Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
@ -30,14 +30,14 @@ fn app_example1<'c>() -> Command<'c> {
)
}
fn app_example2<'c>() -> Command<'c> {
fn app_example2() -> Command {
Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
}
fn app_example3<'c>() -> Command<'c> {
fn app_example3() -> Command {
Command::new("MyApp")
.arg(
Arg::new("debug")
@ -65,7 +65,7 @@ fn app_example3<'c>() -> Command<'c> {
)
}
fn app_example4<'c>() -> Command<'c> {
fn app_example4() -> Command {
Command::new("MyApp")
.about("Parses an input file to do awesome things")
.version("1.0")
@ -91,7 +91,7 @@ fn app_example4<'c>() -> Command<'c> {
)
}
fn app_example5<'c>() -> Command<'c> {
fn app_example5() -> Command {
Command::new("MyApp").arg(
Arg::new("awesome")
.help("turns up the awesome")
@ -101,7 +101,7 @@ fn app_example5<'c>() -> Command<'c> {
)
}
fn app_example6<'c>() -> Command<'c> {
fn app_example6() -> Command {
Command::new("MyApp")
.arg(
Arg::new("input")
@ -113,7 +113,7 @@ fn app_example6<'c>() -> Command<'c> {
.arg(Arg::new("config").help("the config file to use").index(2))
}
fn app_example7<'c>() -> Command<'c> {
fn app_example7() -> Command {
Command::new("MyApp")
.arg(Arg::new("config"))
.arg(Arg::new("output"))
@ -130,7 +130,7 @@ fn app_example7<'c>() -> Command<'c> {
)
}
fn app_example8<'c>() -> Command<'c> {
fn app_example8() -> Command {
Command::new("MyApp")
.arg(Arg::new("config"))
.arg(Arg::new("output"))
@ -147,7 +147,7 @@ fn app_example8<'c>() -> Command<'c> {
)
}
fn app_example10<'c>() -> Command<'c> {
fn app_example10() -> Command {
Command::new("myapp").about("does awesome things").arg(
Arg::new("CONFIG")
.help("The config file to use (default is \"config.json\")")

View file

@ -270,12 +270,12 @@ OPTIONS:
{options}";
/// Build a clap application with short help strings.
fn app_short() -> Command<'static> {
fn app_short() -> Command {
cmd(false, |k| USAGES[k].short)
}
/// Build a clap application with long help strings.
fn app_long() -> Command<'static> {
fn app_long() -> Command {
cmd(true, |k| USAGES[k].long)
}
@ -294,7 +294,7 @@ fn build_help(cmd: &mut Command) -> String {
///
/// This is an intentionally stand-alone module so that it can be used easily
/// in a `build.rs` script to build shell completion files.
fn cmd<F>(_next_line_help: bool, doc: F) -> Command<'static>
fn cmd<F>(_next_line_help: bool, doc: F) -> Command
where
F: Fn(&'static str) -> &'static str,
{

View file

@ -21,7 +21,7 @@ pub fn parse_rustup_with_sc(c: &mut Criterion) {
});
}
fn build_cli() -> Command<'static> {
fn build_cli() -> Command {
Command::new("rustup")
.version("0.9.0") // Simulating
.about("The Rust toolchain installer")

View file

@ -16,7 +16,7 @@ use clap::{value_parser, Arg, Command, ValueHint};
use clap_complete::{generate, Generator, Shell};
use std::io;
fn build_cli() -> Command<'static> {
fn build_cli() -> Command {
Command::new("value_hints")
// AppSettings::TrailingVarArg is required to use ValueHint::CommandWithArguments
.trailing_var_arg(true)

View file

@ -1,7 +1,7 @@
use clap::FromArgMatches;
use clap::Subcommand;
fn command() -> clap::Command<'static> {
fn command() -> clap::Command {
let cmd = clap::Command::new("dynamic")
.arg(
clap::Arg::new("input")

View file

@ -374,7 +374,9 @@ complete OPTIONS -F _clap_complete_NAME EXECUTABLES
if let Some((flag, value)) = arg.to_long() {
if let Ok(flag) = flag {
if let Some(value) = value {
if let Some(arg) = cmd.get_arguments().find(|a| a.get_long() == Some(flag))
if let Some(arg) = cmd
.get_arguments()
.find(|a| a.get_long().map(|s| s.as_str()) == Some(flag))
{
completions.extend(
complete_arg_value(value.to_str().ok_or(value), arg, current_dir)
@ -431,7 +433,7 @@ complete OPTIONS -F _clap_complete_NAME EXECUTABLES
fn complete_arg_value(
value: Result<&str, &clap_lex::RawOsStr>,
arg: &clap::Arg<'_>,
arg: &clap::Arg,
current_dir: Option<&std::path::Path>,
) -> Vec<OsString> {
let mut values = Vec::new();

View file

@ -84,7 +84,7 @@ pub trait Generator {
/// ```
/// // src/cli.rs
/// # use clap::{Command, Arg, ArgAction};
/// pub fn build_cli() -> Command<'static> {
/// pub fn build_cli() -> Command {
/// Command::new("compl")
/// .about("Tests completions")
/// .arg(Arg::new("file")
@ -170,7 +170,7 @@ pub fn generate_to<G, S, T>(
) -> Result<PathBuf, Error>
where
G: Generator,
S: Into<String>,
S: Into<clap::Str>,
T: Into<OsString>,
{
cmd.set_bin_name(bin_name);
@ -223,7 +223,7 @@ where
pub fn generate<G, S>(gen: G, cmd: &mut clap::Command, bin_name: S, buf: &mut dyn Write)
where
G: Generator,
S: Into<String>,
S: Into<clap::Str>,
{
cmd.set_bin_name(bin_name);
_generate::<G, S>(gen, cmd, buf)
@ -232,7 +232,7 @@ where
fn _generate<G, S>(gen: G, cmd: &mut clap::Command, buf: &mut dyn Write)
where
G: Generator,
S: Into<String>,
S: Into<clap::Str>,
{
cmd.build();

View file

@ -19,10 +19,7 @@ pub fn all_subcommands(cmd: &Command) -> Vec<(String, String)> {
/// Finds the subcommand [`clap::Command`] from the given [`clap::Command`] with the given path.
///
/// **NOTE:** `path` should not contain the root `bin_name`.
pub fn find_subcommand_with_path<'help, 'cmd>(
p: &'cmd Command<'help>,
path: Vec<&str>,
) -> &'cmd Command<'help> {
pub fn find_subcommand_with_path<'cmd>(p: &'cmd Command, path: Vec<&str>) -> &'cmd Command {
let mut cmd = p;
for sc in path {
@ -118,7 +115,7 @@ pub fn longs_and_visible_aliases(p: &Command) -> Vec<String> {
/// Gets all the flags of a [`clap::Command`](Command).
/// Includes `help` and `version` depending on the [`clap::Command`] settings.
pub fn flags<'help>(p: &Command<'help>) -> Vec<Arg<'help>> {
pub fn flags(p: &Command) -> Vec<Arg> {
debug!("flags: name={}", p.get_name());
p.get_arguments()
.filter(|a| !a.get_num_args().expect("built").takes_values() && !a.is_positional())
@ -127,7 +124,7 @@ pub fn flags<'help>(p: &Command<'help>) -> Vec<Arg<'help>> {
}
/// Get the possible values for completion
pub fn possible_values(a: &Arg<'_>) -> Option<Vec<clap::builder::PossibleValue>> {
pub fn possible_values(a: &Arg) -> Option<Vec<clap::builder::PossibleValue>> {
if !a.get_num_args().expect("built").takes_values() {
None
} else {
@ -144,7 +141,7 @@ mod tests {
use clap::ArgAction;
use pretty_assertions::assert_eq;
fn common_app() -> Command<'static> {
fn common_app() -> Command {
Command::new("myapp")
.subcommand(
Command::new("test").subcommand(Command::new("config")).arg(
@ -161,14 +158,14 @@ mod tests {
.bin_name("my-cmd")
}
fn built() -> Command<'static> {
fn built() -> Command {
let mut cmd = common_app();
cmd.build();
cmd
}
fn built_with_version() -> Command<'static> {
fn built_with_version() -> Command {
let mut cmd = common_app().version("3.0");
cmd.build();
@ -219,14 +216,17 @@ mod tests {
let actual_flags = flags(&cmd);
assert_eq!(actual_flags.len(), 2);
assert_eq!(actual_flags[0].get_long(), Some("help"));
assert_eq!(actual_flags[1].get_long(), Some("version"));
assert_eq!(actual_flags[0].get_long().map(|s| s.as_str()), Some("help"));
assert_eq!(
actual_flags[1].get_long().map(|s| s.as_str()),
Some("version")
);
let sc_flags = flags(find_subcommand_with_path(&cmd, vec!["test"]));
assert_eq!(sc_flags.len(), 2);
assert_eq!(sc_flags[0].get_long(), Some("file"));
assert_eq!(sc_flags[1].get_long(), Some("help"));
assert_eq!(sc_flags[0].get_long().map(|s| s.as_str()), Some("file"));
assert_eq!(sc_flags[1].get_long().map(|s| s.as_str()), Some("help"));
}
#[test]
@ -235,13 +235,13 @@ mod tests {
let actual_flags = flags(&cmd);
assert_eq!(actual_flags.len(), 1);
assert_eq!(actual_flags[0].get_long(), Some("help"));
assert_eq!(actual_flags[0].get_long().map(|s| s.as_str()), Some("help"));
let sc_flags = flags(find_subcommand_with_path(&cmd, vec!["test"]));
assert_eq!(sc_flags.len(), 2);
assert_eq!(sc_flags[0].get_long(), Some("file"));
assert_eq!(sc_flags[1].get_long(), Some("help"));
assert_eq!(sc_flags[0].get_long().map(|s| s.as_str()), Some("file"));
assert_eq!(sc_flags[1].get_long().map(|s| s.as_str()), Some("help"));
}
#[test]

View file

@ -26,7 +26,7 @@
//! use clap_complete::{generate, Generator, Shell};
//! use std::io;
//!
//! fn build_cli() -> Command<'static> {
//! fn build_cli() -> Command {
//! Command::new("example")
//! .arg(Arg::new("file")
//! .help("some input file")

View file

@ -67,7 +67,7 @@ fn get_tooltip<T: ToString>(help: Option<&str>, data: T) -> String {
}
fn generate_inner<'help>(
p: &Command<'help>,
p: &Command,
previous_command_name: &str,
names: &mut Vec<&'help str>,
) -> String {
@ -84,7 +84,7 @@ fn generate_inner<'help>(
for option in p.get_opts() {
if let Some(shorts) = option.get_short_and_visible_aliases() {
let tooltip = get_tooltip(option.get_help(), shorts[0]);
let tooltip = get_tooltip(option.get_help().map(|s| s.as_str()), shorts[0]);
for short in shorts {
completions.push_str(&preamble);
completions.push_str(format!("-{} '{}'", short, tooltip).as_str());
@ -92,7 +92,7 @@ fn generate_inner<'help>(
}
if let Some(longs) = option.get_long_and_visible_aliases() {
let tooltip = get_tooltip(option.get_help(), longs[0]);
let tooltip = get_tooltip(option.get_help().map(|s| s.as_str()), longs[0]);
for long in longs {
completions.push_str(&preamble);
completions.push_str(format!("--{} '{}'", long, tooltip).as_str());
@ -102,7 +102,7 @@ fn generate_inner<'help>(
for flag in utils::flags(p) {
if let Some(shorts) = flag.get_short_and_visible_aliases() {
let tooltip = get_tooltip(flag.get_help(), shorts[0]);
let tooltip = get_tooltip(flag.get_help().map(|s| s.as_str()), shorts[0]);
for short in shorts {
completions.push_str(&preamble);
completions.push_str(format!("-{} '{}'", short, tooltip).as_str());
@ -110,7 +110,7 @@ fn generate_inner<'help>(
}
if let Some(longs) = flag.get_long_and_visible_aliases() {
let tooltip = get_tooltip(flag.get_help(), longs[0]);
let tooltip = get_tooltip(flag.get_help().map(|s| s.as_str()), longs[0]);
for long in longs {
completions.push_str(&preamble);
completions.push_str(format!("--{} '{}'", long, tooltip).as_str());
@ -120,7 +120,7 @@ fn generate_inner<'help>(
for subcommand in p.get_subcommands() {
let data = &subcommand.get_name();
let tooltip = get_tooltip(subcommand.get_about(), data);
let tooltip = get_tooltip(subcommand.get_about().map(|s| s.as_str()), data);
completions.push_str(&preamble);
completions.push_str(format!("{} '{}'", data, tooltip).as_str());

View file

@ -72,7 +72,7 @@ fn get_tooltip<T: ToString>(help: Option<&str>, data: T) -> String {
}
fn generate_inner<'help>(
p: &Command<'help>,
p: &Command,
previous_command_name: &str,
names: &mut Vec<&'help str>,
) -> String {
@ -89,7 +89,7 @@ fn generate_inner<'help>(
for option in p.get_opts() {
if let Some(shorts) = option.get_short_and_visible_aliases() {
let tooltip = get_tooltip(option.get_help(), shorts[0]);
let tooltip = get_tooltip(option.get_help().map(|s| s.as_str()), shorts[0]);
for short in shorts {
completions.push_str(&preamble);
completions.push_str(
@ -103,7 +103,7 @@ fn generate_inner<'help>(
}
if let Some(longs) = option.get_long_and_visible_aliases() {
let tooltip = get_tooltip(option.get_help(), longs[0]);
let tooltip = get_tooltip(option.get_help().map(|s| s.as_str()), longs[0]);
for long in longs {
completions.push_str(&preamble);
completions.push_str(
@ -119,7 +119,7 @@ fn generate_inner<'help>(
for flag in utils::flags(p) {
if let Some(shorts) = flag.get_short_and_visible_aliases() {
let tooltip = get_tooltip(flag.get_help(), shorts[0]);
let tooltip = get_tooltip(flag.get_help().map(|s| s.as_str()), shorts[0]);
for short in shorts {
completions.push_str(&preamble);
completions.push_str(
@ -133,7 +133,7 @@ fn generate_inner<'help>(
}
if let Some(longs) = flag.get_long_and_visible_aliases() {
let tooltip = get_tooltip(flag.get_help(), longs[0]);
let tooltip = get_tooltip(flag.get_help().map(|s| s.as_str()), longs[0]);
for long in longs {
completions.push_str(&preamble);
completions.push_str(
@ -149,7 +149,7 @@ fn generate_inner<'help>(
for subcommand in p.get_subcommands() {
let data = &subcommand.get_name();
let tooltip = get_tooltip(subcommand.get_about(), data);
let tooltip = get_tooltip(subcommand.get_about().map(|s| s.as_str()), data);
completions.push_str(&preamble);
completions.push_str(

View file

@ -153,7 +153,7 @@ fn subcommands_of(p: &Command) -> String {
let text = format!(
"'{name}:{help}' \\",
name = name,
help = escape_help(subcommand.get_about().unwrap_or(""))
help = escape_help(subcommand.get_about().unwrap_or_default())
);
if !text.is_empty() {
@ -280,13 +280,10 @@ esac",
//
// Given the bin_name "a b c" and the Command for "a" this returns the "c" Command.
// Given the bin_name "a b c" and the Command for "b" this returns the "c" Command.
fn parser_of<'help, 'cmd>(
parent: &'cmd Command<'help>,
bin_name: &str,
) -> Option<&'cmd Command<'help>> {
fn parser_of<'cmd>(parent: &'cmd Command, bin_name: &str) -> Option<&'cmd Command> {
debug!("parser_of: p={}, bin_name={}", parent.get_name(), bin_name);
if bin_name == parent.get_bin_name().unwrap_or("") {
if bin_name == *parent.get_bin_name().unwrap_or_default() {
return Some(parent);
}
@ -452,7 +449,10 @@ fn write_opts_of(p: &Command, p_global: Option<&Command>) -> String {
for o in p.get_opts() {
debug!("write_opts_of:iter: o={}", o.get_id());
let help = o.get_help().map_or(String::new(), escape_help);
let help = o
.get_help()
.map(|s| escape_help(s.as_str()))
.unwrap_or_default();
let conflicts = arg_conflicts(p, o, p_global);
let multiple = "*";
@ -548,7 +548,10 @@ fn write_flags_of(p: &Command, p_global: Option<&Command>) -> String {
for f in utils::flags(p) {
debug!("write_flags_of:iter: f={}", f.get_id());
let help = f.get_help().map_or(String::new(), escape_help);
let help = f
.get_help()
.map(|s| escape_help(s.as_str()))
.unwrap_or_default();
let conflicts = arg_conflicts(p, &f, p_global);
let multiple = "*";

View file

@ -1,4 +1,4 @@
pub fn basic_command(name: &'static str) -> clap::Command<'static> {
pub fn basic_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.arg(
clap::Arg::new("config")
@ -21,7 +21,7 @@ pub fn basic_command(name: &'static str) -> clap::Command<'static> {
)
}
pub fn feature_sample_command(name: &'static str) -> clap::Command<'static> {
pub fn feature_sample_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.propagate_version(true)
@ -51,7 +51,7 @@ pub fn feature_sample_command(name: &'static str) -> clap::Command<'static> {
)
}
pub fn special_commands_command(name: &'static str) -> clap::Command<'static> {
pub fn special_commands_command(name: &'static str) -> clap::Command {
feature_sample_command(name)
.subcommand(
clap::Command::new("some_cmd")
@ -70,7 +70,7 @@ pub fn special_commands_command(name: &'static str) -> clap::Command<'static> {
.subcommand(clap::Command::new("some-hidden-cmd").hide(true))
}
pub fn quoting_command(name: &'static str) -> clap::Command<'static> {
pub fn quoting_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.arg(
@ -120,7 +120,7 @@ pub fn quoting_command(name: &'static str) -> clap::Command<'static> {
])
}
pub fn aliases_command(name: &'static str) -> clap::Command<'static> {
pub fn aliases_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.about("testing bash completions")
@ -145,7 +145,7 @@ pub fn aliases_command(name: &'static str) -> clap::Command<'static> {
.arg(clap::Arg::new("positional"))
}
pub fn sub_subcommands_command(name: &'static str) -> clap::Command<'static> {
pub fn sub_subcommands_command(name: &'static str) -> clap::Command {
feature_sample_command(name).subcommand(
clap::Command::new("some_cmd")
.about("top level subcommand")
@ -163,7 +163,7 @@ pub fn sub_subcommands_command(name: &'static str) -> clap::Command<'static> {
)
}
pub fn value_hint_command(name: &'static str) -> clap::Command<'static> {
pub fn value_hint_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.trailing_var_arg(true)
.arg(
@ -251,7 +251,7 @@ pub fn assert_matches_path(
expected_path: impl AsRef<std::path::Path>,
gen: impl clap_complete::Generator,
mut cmd: clap::Command,
name: &str,
name: &'static str,
) {
let mut buf = vec![];
clap_complete::generate(gen, &mut cmd, name, &mut buf);

View file

@ -62,7 +62,7 @@ fn gen_fig_inner(
write!(buffer, "{:indent$}subcommands: [\n", "", indent = indent).unwrap();
// generate subcommands
for subcommand in cmd.get_subcommands() {
let mut aliases: Vec<&str> = subcommand.get_all_aliases().collect();
let mut aliases: Vec<&str> = subcommand.get_all_aliases().map(|s| s.as_str()).collect();
if !aliases.is_empty() {
aliases.insert(0, subcommand.get_name());

View file

@ -1,4 +1,4 @@
pub fn basic_command(name: &'static str) -> clap::Command<'static> {
pub fn basic_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.arg(
clap::Arg::new("config")
@ -21,7 +21,7 @@ pub fn basic_command(name: &'static str) -> clap::Command<'static> {
)
}
pub fn feature_sample_command(name: &'static str) -> clap::Command<'static> {
pub fn feature_sample_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.propagate_version(true)
@ -51,7 +51,7 @@ pub fn feature_sample_command(name: &'static str) -> clap::Command<'static> {
)
}
pub fn special_commands_command(name: &'static str) -> clap::Command<'static> {
pub fn special_commands_command(name: &'static str) -> clap::Command {
feature_sample_command(name)
.subcommand(
clap::Command::new("some_cmd")
@ -70,7 +70,7 @@ pub fn special_commands_command(name: &'static str) -> clap::Command<'static> {
.subcommand(clap::Command::new("some-hidden-cmd").hide(true))
}
pub fn quoting_command(name: &'static str) -> clap::Command<'static> {
pub fn quoting_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.arg(
@ -120,7 +120,7 @@ pub fn quoting_command(name: &'static str) -> clap::Command<'static> {
])
}
pub fn aliases_command(name: &'static str) -> clap::Command<'static> {
pub fn aliases_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.about("testing bash completions")
@ -145,7 +145,7 @@ pub fn aliases_command(name: &'static str) -> clap::Command<'static> {
.arg(clap::Arg::new("positional"))
}
pub fn sub_subcommands_command(name: &'static str) -> clap::Command<'static> {
pub fn sub_subcommands_command(name: &'static str) -> clap::Command {
feature_sample_command(name).subcommand(
clap::Command::new("some_cmd")
.about("top level subcommand")
@ -163,7 +163,7 @@ pub fn sub_subcommands_command(name: &'static str) -> clap::Command<'static> {
)
}
pub fn value_hint_command(name: &'static str) -> clap::Command<'static> {
pub fn value_hint_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.trailing_var_arg(true)
.arg(
@ -251,7 +251,7 @@ pub fn assert_matches_path(
expected_path: impl AsRef<std::path::Path>,
gen: impl clap_complete::Generator,
mut cmd: clap::Command,
name: &str,
name: &'static str,
) {
let mut buf = vec![];
clap_complete::generate(gen, &mut cmd, name, &mut buf);

View file

@ -87,10 +87,10 @@ pub fn gen_for_struct(
)]
#[deny(clippy::correctness)]
impl #impl_generics clap::Args for #struct_name #ty_generics #where_clause {
fn augment_args<'b>(#app_var: clap::Command<'b>) -> clap::Command<'b> {
fn augment_args<'b>(#app_var: clap::Command) -> clap::Command {
#augmentation
}
fn augment_args_for_update<'b>(#app_var: clap::Command<'b>) -> clap::Command<'b> {
fn augment_args_for_update<'b>(#app_var: clap::Command) -> clap::Command {
#augmentation_update
}
}
@ -228,17 +228,17 @@ pub fn gen_augment(
let next_display_order = attrs.next_display_order();
if override_required {
Some(quote_spanned! { kind.span()=>
let #old_heading_var = #app_var.get_next_help_heading();
let #old_heading_var = #app_var.get_next_help_heading().cloned();
let #app_var = #app_var #next_help_heading #next_display_order;
let #app_var = <#ty as clap::Args>::augment_args_for_update(#app_var);
let #app_var = #app_var.next_help_heading(#old_heading_var);
let #app_var = #app_var.next_help_heading(clap::builder::Resettable::from(#old_heading_var));
})
} else {
Some(quote_spanned! { kind.span()=>
let #old_heading_var = #app_var.get_next_help_heading();
let #old_heading_var = #app_var.get_next_help_heading().cloned();
let #app_var = #app_var #next_help_heading #next_display_order;
let #app_var = <#ty as clap::Args>::augment_args(#app_var);
let #app_var = #app_var.next_help_heading(#old_heading_var);
let #app_var = #app_var.next_help_heading(clap::builder::Resettable::from(#old_heading_var));
})
}
}

View file

@ -57,12 +57,12 @@ pub fn gen_for_struct(
)]
#[deny(clippy::correctness)]
impl #impl_generics clap::CommandFactory for #struct_name #ty_generics #where_clause {
fn command<'b>() -> clap::Command<'b> {
fn command<'b>() -> clap::Command {
let #app_var = clap::Command::new(#name);
<Self as clap::Args>::augment_args(#app_var)
}
fn command_for_update<'b>() -> clap::Command<'b> {
fn command_for_update<'b>() -> clap::Command {
let #app_var = clap::Command::new(#name);
<Self as clap::Args>::augment_args_for_update(#app_var)
}
@ -102,14 +102,14 @@ pub fn gen_for_enum(enum_name: &Ident, generics: &Generics, attrs: &[Attribute])
)]
#[deny(clippy::correctness)]
impl #impl_generics clap::CommandFactory for #enum_name #ty_generics #where_clause {
fn command<'b>() -> clap::Command<'b> {
fn command<'b>() -> clap::Command {
let #app_var = clap::Command::new(#name)
.subcommand_required(true)
.arg_required_else_help(true);
<Self as clap::Subcommand>::augment_subcommands(#app_var)
}
fn command_for_update<'b>() -> clap::Command<'b> {
fn command_for_update<'b>() -> clap::Command {
let #app_var = clap::Command::new(#name);
<Self as clap::Subcommand>::augment_subcommands_for_update(#app_var)
}

View file

@ -75,10 +75,10 @@ pub fn gen_for_enum(
)]
#[deny(clippy::correctness)]
impl #impl_generics clap::Subcommand for #enum_name #ty_generics #where_clause {
fn augment_subcommands <'b>(__clap_app: clap::Command<'b>) -> clap::Command<'b> {
fn augment_subcommands <'b>(__clap_app: clap::Command) -> clap::Command {
#augmentation
}
fn augment_subcommands_for_update <'b>(__clap_app: clap::Command<'b>) -> clap::Command<'b> {
fn augment_subcommands_for_update <'b>(__clap_app: clap::Command) -> clap::Command {
#augmentation_update
}
fn has_subcommand(__clap_name: &str) -> bool {
@ -193,17 +193,17 @@ fn gen_augment(
let next_display_order = attrs.next_display_order();
let subcommand = if override_required {
quote! {
let #old_heading_var = #app_var.get_next_help_heading();
let #old_heading_var = #app_var.get_next_help_heading().cloned();
let #app_var = #app_var #next_help_heading #next_display_order;
let #app_var = <#ty as clap::Subcommand>::augment_subcommands_for_update(#app_var);
let #app_var = #app_var.next_help_heading(#old_heading_var);
let #app_var = #app_var.next_help_heading(clap::builder::Resettable::from(#old_heading_var));
}
} else {
quote! {
let #old_heading_var = #app_var.get_next_help_heading();
let #old_heading_var = #app_var.get_next_help_heading().cloned();
let #app_var = #app_var #next_help_heading #next_display_order;
let #app_var = <#ty as clap::Subcommand>::augment_subcommands(#app_var);
let #app_var = #app_var.next_help_heading(#old_heading_var);
let #app_var = #app_var.next_help_heading(clap::builder::Resettable::from(#old_heading_var));
}
};
Some(subcommand)
@ -480,7 +480,7 @@ fn gen_from_arg_matches(
};
quote! {
if #sub_name == #subcommand_name_var && !#sub_arg_matches_var.contains_id("") {
if #subcommand_name_var == #sub_name && !#sub_arg_matches_var.contains_id("") {
return ::std::result::Result::Ok(#name :: #variant_name #constructor_block)
}
}

View file

@ -19,10 +19,10 @@ pub fn parser_enum(name: &Ident) {
pub fn into_app(name: &Ident) {
append_dummy(quote! {
impl clap::CommandFactory for #name {
fn command<'b>() -> clap::Command<'b> {
fn command<'b>() -> clap::Command {
unimplemented!()
}
fn command_for_update<'b>() -> clap::Command<'b> {
fn command_for_update<'b>() -> clap::Command {
unimplemented!()
}
}
@ -46,10 +46,10 @@ pub fn subcommand(name: &Ident) {
from_arg_matches(name);
append_dummy(quote! {
impl clap::Subcommand for #name {
fn augment_subcommands(_cmd: clap::Command<'_>) -> clap::Command<'_> {
fn augment_subcommands(_cmd: clap::Command) -> clap::Command {
unimplemented!()
}
fn augment_subcommands_for_update(_cmd: clap::Command<'_>) -> clap::Command<'_> {
fn augment_subcommands_for_update(_cmd: clap::Command) -> clap::Command {
unimplemented!()
}
fn has_subcommand(name: &str) -> bool {
@ -63,10 +63,10 @@ pub fn args(name: &Ident) {
from_arg_matches(name);
append_dummy(quote! {
impl clap::Args for #name {
fn augment_args(_cmd: clap::Command<'_>) -> clap::Command<'_> {
fn augment_args(_cmd: clap::Command) -> clap::Command {
unimplemented!()
}
fn augment_args_for_update(_cmd: clap::Command<'_>) -> clap::Command<'_> {
fn augment_args_for_update(_cmd: clap::Command) -> clap::Command {
unimplemented!()
}
}

View file

@ -229,10 +229,14 @@ impl RawArgs {
}
/// Inject arguments before the [`RawArgs::next`]
pub fn insert(&mut self, cursor: &ArgCursor, insert_items: &[&str]) {
pub fn insert(
&mut self,
cursor: &ArgCursor,
insert_items: impl IntoIterator<Item = impl Into<OsString>>,
) {
self.items.splice(
cursor.cursor..cursor.cursor,
insert_items.iter().map(OsString::from),
insert_items.into_iter().map(Into::into),
);
}

View file

@ -13,8 +13,8 @@ use roff::{roman, Roff};
use std::io::Write;
/// A manpage writer
pub struct Man<'a> {
cmd: clap::Command<'a>,
pub struct Man {
cmd: clap::Command,
title: String,
section: String,
date: String,
@ -23,11 +23,11 @@ pub struct Man<'a> {
}
/// Build a [`Man`]
impl<'a> Man<'a> {
impl Man {
/// Create a new manual page.
pub fn new(mut cmd: clap::Command<'a>) -> Self {
pub fn new(mut cmd: clap::Command) -> Self {
cmd.build();
let title = cmd.get_name().to_owned();
let title = cmd.get_name().as_str().to_owned();
let section = "1".to_owned();
let date = "".to_owned();
let source = format!(
@ -93,7 +93,7 @@ impl<'a> Man<'a> {
}
/// Generate ROFF output
impl<'a> Man<'a> {
impl Man {
/// Render a full manual page into the writer.
///
/// If customization is needed, you can call the individual sections you want and mix them into
@ -207,7 +207,7 @@ impl<'a> Man<'a> {
fn _render_subcommands_section(&self, roff: &mut Roff) {
let heading = subcommand_heading(&self.cmd);
roff.control("SH", [heading.as_str()]);
roff.control("SH", [heading]);
render::subcommands(roff, &self.cmd, &self.section);
}
@ -244,7 +244,7 @@ impl<'a> Man<'a> {
}
fn _render_authors_section(&self, roff: &mut Roff) {
let author = roman(self.cmd.get_author().unwrap_or_default());
let author = roman(self.cmd.get_author().unwrap_or_default().as_str());
roff.control("SH", ["AUTHORS"]);
roff.text([author]);
}

View file

@ -1,9 +1,9 @@
use roff::{bold, italic, roman, Inline, Roff};
pub(crate) fn subcommand_heading(cmd: &clap::Command) -> String {
pub(crate) fn subcommand_heading(cmd: &clap::Command) -> &str {
match cmd.get_subcommand_help_heading() {
Some(title) => title.to_string(),
None => "SUBCOMMANDS".to_string(),
Some(title) => title.as_str(),
None => "SUBCOMMANDS",
}
}
@ -28,7 +28,7 @@ pub(crate) fn description(roff: &mut Roff, cmd: &clap::Command) {
}
pub(crate) fn synopsis(roff: &mut Roff, cmd: &clap::Command) {
let mut line = vec![bold(cmd.get_name()), roman(" ")];
let mut line = vec![bold(cmd.get_name().as_str()), roman(" ")];
for opt in cmd.get_arguments().filter(|i| !i.is_hide_set()) {
let (lhs, rhs) = option_markers(opt);
@ -73,8 +73,9 @@ pub(crate) fn synopsis(roff: &mut Roff, cmd: &clap::Command) {
let (lhs, rhs) = subcommand_markers(cmd);
line.push(roman(lhs));
line.push(italic(
&cmd.get_subcommand_value_name()
.unwrap_or(&subcommand_heading(cmd))
cmd.get_subcommand_value_name()
.map(|s| s.as_str())
.unwrap_or_else(|| subcommand_heading(cmd))
.to_lowercase(),
));
line.push(roman(rhs));
@ -108,7 +109,7 @@ pub(crate) fn options(roff: &mut Roff, cmd: &clap::Command) {
let mut body = vec![];
if let Some(help) = opt.get_long_help().or_else(|| opt.get_help()) {
body.push(roman(help));
body.push(roman(help.as_str()));
}
roff.control("TP", []);

View file

@ -1,4 +1,4 @@
pub fn basic_command(name: &'static str) -> clap::Command<'static> {
pub fn basic_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.arg(
clap::Arg::new("config")
@ -21,7 +21,7 @@ pub fn basic_command(name: &'static str) -> clap::Command<'static> {
)
}
pub fn feature_sample_command(name: &'static str) -> clap::Command<'static> {
pub fn feature_sample_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.propagate_version(true)
@ -51,7 +51,7 @@ pub fn feature_sample_command(name: &'static str) -> clap::Command<'static> {
)
}
pub fn special_commands_command(name: &'static str) -> clap::Command<'static> {
pub fn special_commands_command(name: &'static str) -> clap::Command {
feature_sample_command(name)
.subcommand(
clap::Command::new("some_cmd")
@ -66,7 +66,7 @@ pub fn special_commands_command(name: &'static str) -> clap::Command<'static> {
.subcommand(clap::Command::new("some-cmd-with-hyphens").alias("hyphen"))
}
pub fn quoting_command(name: &'static str) -> clap::Command<'static> {
pub fn quoting_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.arg(
@ -116,7 +116,7 @@ pub fn quoting_command(name: &'static str) -> clap::Command<'static> {
])
}
pub fn aliases_command(name: &'static str) -> clap::Command<'static> {
pub fn aliases_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.version("3.0")
.about("testing bash completions")
@ -141,7 +141,7 @@ pub fn aliases_command(name: &'static str) -> clap::Command<'static> {
.arg(clap::Arg::new("positional"))
}
pub fn sub_subcommands_command(name: &'static str) -> clap::Command<'static> {
pub fn sub_subcommands_command(name: &'static str) -> clap::Command {
feature_sample_command(name).subcommand(
clap::Command::new("some_cmd")
.about("top level subcommand")
@ -159,7 +159,7 @@ pub fn sub_subcommands_command(name: &'static str) -> clap::Command<'static> {
)
}
pub fn value_hint_command(name: &'static str) -> clap::Command<'static> {
pub fn value_hint_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.trailing_var_arg(true)
.arg(
@ -243,7 +243,7 @@ pub fn value_hint_command(name: &'static str) -> clap::Command<'static> {
)
}
pub fn hidden_option_command(name: &'static str) -> clap::Command<'static> {
pub fn hidden_option_command(name: &'static str) -> clap::Command {
clap::Command::new(name)
.arg(
clap::Arg::new("config")
@ -258,7 +258,7 @@ pub fn hidden_option_command(name: &'static str) -> clap::Command<'static> {
)
}
pub fn env_value_command(name: &'static str) -> clap::Command<'static> {
pub fn env_value_command(name: &'static str) -> clap::Command {
clap::Command::new(name).arg(
clap::Arg::new("config")
.short('c')

View file

@ -35,7 +35,7 @@ impl FromArgMatches for CliArgs {
}
impl Args for CliArgs {
fn augment_args(cmd: Command<'_>) -> Command<'_> {
fn augment_args(cmd: Command) -> Command {
cmd.arg(
Arg::new("foo")
.short('f')
@ -55,7 +55,7 @@ impl Args for CliArgs {
.action(ArgAction::Set),
)
}
fn augment_args_for_update(cmd: Command<'_>) -> Command<'_> {
fn augment_args_for_update(cmd: Command) -> Command {
cmd.arg(
Arg::new("foo")
.short('f')

View file

@ -50,12 +50,12 @@ impl FromArgMatches for CliSub {
}
impl Subcommand for CliSub {
fn augment_subcommands(cmd: Command<'_>) -> Command<'_> {
fn augment_subcommands(cmd: Command) -> Command {
cmd.subcommand(AddArgs::augment_args(Command::new("add")))
.subcommand(RemoveArgs::augment_args(Command::new("remove")))
.subcommand_required(true)
}
fn augment_subcommands_for_update(cmd: Command<'_>) -> Command<'_> {
fn augment_subcommands_for_update(cmd: Command) -> Command {
cmd.subcommand(AddArgs::augment_args(Command::new("add")))
.subcommand(RemoveArgs::augment_args(Command::new("remove")))
.subcommand_required(true)

View file

@ -8,7 +8,7 @@ fn main() {
println!("{:#?}", values);
}
fn cli() -> Command<'static> {
fn cli() -> Command {
command!()
.group(ArgGroup::new("tests").multiple(true))
.next_help_heading("TESTS")

View file

@ -3,7 +3,7 @@ use std::path::PathBuf;
use clap::{arg, Command};
fn cli() -> Command<'static> {
fn cli() -> Command {
Command::new("git")
.about("A fictional versioning CLI")
.subcommand_required(true)
@ -37,7 +37,7 @@ fn cli() -> Command<'static> {
)
}
fn push_args() -> Vec<clap::Arg<'static>> {
fn push_args() -> Vec<clap::Arg> {
vec![arg!(-m --message <MESSAGE>).required(false)]
}

View file

@ -3,7 +3,7 @@ use std::process::exit;
use clap::{value_parser, Arg, ArgAction, Command};
fn applet_commands() -> [Command<'static>; 2] {
fn applet_commands() -> [Command; 2] {
[
Command::new("true").about("does nothing successfully"),
Command::new("false").about("does nothing unsuccessfully"),

View file

@ -48,7 +48,7 @@ fn respond(line: &str) -> Result<bool, String> {
Ok(false)
}
fn cli() -> Command<'static> {
fn cli() -> Command {
// strip out usage
const PARSER_TEMPLATE: &str = "\
{all-args}

View file

@ -10,7 +10,7 @@ fn main() {
println!("PORT = {}", port);
}
fn cmd() -> clap::Command<'static> {
fn cmd() -> clap::Command {
command!() // requires `cargo` feature
.arg(
arg!(<PORT>)

View file

@ -16,9 +16,10 @@ use crate::builder::ArgPredicate;
use crate::builder::IntoResettable;
use crate::builder::PossibleValue;
use crate::builder::ValueRange;
use crate::util::Id;
use crate::util::OsStr;
use crate::ArgAction;
use crate::Id;
use crate::OsStr;
use crate::Str;
use crate::ValueHint;
use crate::INTERNAL_ERROR_MSG;
@ -51,10 +52,10 @@ use crate::INTERNAL_ERROR_MSG;
/// ```
#[allow(missing_debug_implementations)]
#[derive(Default, Clone)]
pub struct Arg<'help> {
pub struct Arg {
pub(crate) id: Id,
pub(crate) help: Option<&'help str>,
pub(crate) long_help: Option<&'help str>,
pub(crate) help: Option<Str>,
pub(crate) long_help: Option<Str>,
pub(crate) action: Option<ArgAction>,
pub(crate) value_parser: Option<super::ValueParser>,
pub(crate) blacklist: Vec<Id>,
@ -67,11 +68,11 @@ pub struct Arg<'help> {
pub(crate) r_unless: Vec<Id>,
pub(crate) r_unless_all: Vec<Id>,
pub(crate) short: Option<char>,
pub(crate) long: Option<&'help str>,
pub(crate) aliases: Vec<(&'help str, bool)>, // (name, visible)
pub(crate) long: Option<Str>,
pub(crate) aliases: Vec<(Str, bool)>, // (name, visible)
pub(crate) short_aliases: Vec<(char, bool)>, // (name, visible)
pub(crate) disp_ord: Option<usize>,
pub(crate) val_names: Vec<&'help str>,
pub(crate) val_names: Vec<Str>,
pub(crate) num_vals: Option<ValueRange>,
pub(crate) val_delim: Option<char>,
pub(crate) default_vals: Vec<OsStr>,
@ -79,14 +80,14 @@ pub struct Arg<'help> {
pub(crate) default_missing_vals: Vec<OsStr>,
#[cfg(feature = "env")]
pub(crate) env: Option<(OsStr, Option<OsString>)>,
pub(crate) terminator: Option<&'help str>,
pub(crate) terminator: Option<Str>,
pub(crate) index: Option<usize>,
pub(crate) help_heading: Option<Option<&'help str>>,
pub(crate) help_heading: Option<Option<Str>>,
pub(crate) value_hint: Option<ValueHint>,
}
/// # Basic API
impl<'help> Arg<'help> {
impl Arg {
/// Create a new [`Arg`] with a unique name.
///
/// The name is used to check whether or not the argument was used at
@ -181,8 +182,8 @@ impl<'help> Arg<'help> {
/// ```
#[inline]
#[must_use]
pub fn long(mut self, l: &'help str) -> Self {
self.long = Some(l);
pub fn long(mut self, l: impl Into<Str>) -> Self {
self.long = Some(l.into());
self
}
@ -206,7 +207,7 @@ impl<'help> Arg<'help> {
/// assert_eq!(m.get_one::<String>("test").unwrap(), "cool");
/// ```
#[must_use]
pub fn alias<S: Into<&'help str>>(mut self, name: S) -> Self {
pub fn alias(mut self, name: impl Into<Str>) -> Self {
self.aliases.push((name.into(), false));
self
}
@ -260,7 +261,7 @@ impl<'help> Arg<'help> {
/// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
/// ```
#[must_use]
pub fn aliases(mut self, names: impl IntoIterator<Item = impl Into<&'help str>>) -> Self {
pub fn aliases(mut self, names: impl IntoIterator<Item = impl Into<Str>>) -> Self {
self.aliases
.extend(names.into_iter().map(|x| (x.into(), false)));
self
@ -316,7 +317,7 @@ impl<'help> Arg<'help> {
/// ```
/// [`Command::alias`]: Arg::alias()
#[must_use]
pub fn visible_alias<S: Into<&'help str>>(mut self, name: S) -> Self {
pub fn visible_alias(mut self, name: impl Into<Str>) -> Self {
self.aliases.push((name.into(), true));
self
}
@ -367,10 +368,7 @@ impl<'help> Arg<'help> {
/// ```
/// [`Command::aliases`]: Arg::aliases()
#[must_use]
pub fn visible_aliases(
mut self,
names: impl IntoIterator<Item = impl Into<&'help str>>,
) -> Self {
pub fn visible_aliases(mut self, names: impl IntoIterator<Item = impl Into<Str>>) -> Self {
self.aliases
.extend(names.into_iter().map(|n| (n.into(), true)));
self
@ -781,7 +779,7 @@ impl<'help> Arg<'help> {
}
/// # Value Handling
impl<'help> Arg<'help> {
impl Arg {
/// Specify how to react to an argument when parsing it.
///
/// [ArgAction][crate::ArgAction] controls things like
@ -1077,7 +1075,7 @@ impl<'help> Arg<'help> {
/// [`Arg::action(ArgAction::Set)`]: Arg::action()
#[inline]
#[must_use]
pub fn value_name(self, name: &'help str) -> Self {
pub fn value_name(self, name: impl Into<Str>) -> Self {
self.value_names([name])
}
@ -1135,7 +1133,7 @@ impl<'help> Arg<'help> {
/// [`Arg::action(ArgAction::Set)`]: Arg::action()
/// [`Arg::num_args(1..)`]: Arg::num_args()
#[must_use]
pub fn value_names(mut self, names: impl IntoIterator<Item = impl Into<&'help str>>) -> Self {
pub fn value_names(mut self, names: impl IntoIterator<Item = impl Into<Str>>) -> Self {
self.val_names = names.into_iter().map(|s| s.into()).collect();
self
}
@ -1424,8 +1422,8 @@ impl<'help> Arg<'help> {
/// [`num_args`]: Arg::num_args()
#[inline]
#[must_use]
pub fn value_terminator(mut self, term: &'help str) -> Self {
self.terminator = Some(term);
pub fn value_terminator(mut self, term: impl Into<Str>) -> Self {
self.terminator = Some(term.into());
self
}
@ -1573,7 +1571,7 @@ impl<'help> Arg<'help> {
/// For POSIX style `--color`:
/// ```rust
/// # use clap::{Command, Arg, parser::ValueSource};
/// fn cli() -> Command<'static> {
/// fn cli() -> Command {
/// Command::new("prog")
/// .arg(Arg::new("color").long("color")
/// .value_name("WHEN")
@ -1611,7 +1609,7 @@ impl<'help> Arg<'help> {
/// For bool literals:
/// ```rust
/// # use clap::{Command, Arg, parser::ValueSource, value_parser};
/// fn cli() -> Command<'static> {
/// fn cli() -> Command {
/// Command::new("prog")
/// .arg(Arg::new("create").long("create")
/// .value_name("BOOL")
@ -1857,7 +1855,7 @@ impl<'help> Arg<'help> {
}
/// # Help
impl<'help> Arg<'help> {
impl Arg {
/// Sets the description of the argument for short help (`-h`).
///
/// Typically, this is a short (one line) description of the arg.
@ -1902,8 +1900,8 @@ impl<'help> Arg<'help> {
/// [`Arg::long_help`]: Arg::long_help()
#[inline]
#[must_use]
pub fn help(mut self, h: impl Into<Option<&'help str>>) -> Self {
self.help = h.into();
pub fn help(mut self, h: impl IntoResettable<Str>) -> Self {
self.help = h.into_resettable().into_option();
self
}
@ -1964,8 +1962,8 @@ impl<'help> Arg<'help> {
/// [`Arg::help`]: Arg::help()
#[inline]
#[must_use]
pub fn long_help(mut self, h: impl Into<Option<&'help str>>) -> Self {
self.long_help = h.into();
pub fn long_help(mut self, h: impl IntoResettable<Str>) -> Self {
self.long_help = h.into_resettable().into_option();
self
}
@ -2034,11 +2032,8 @@ impl<'help> Arg<'help> {
/// [current]: crate::Command::next_help_heading
#[inline]
#[must_use]
pub fn help_heading<O>(mut self, heading: O) -> Self
where
O: Into<Option<&'help str>>,
{
self.help_heading = Some(heading.into());
pub fn help_heading(mut self, heading: impl IntoResettable<Str>) -> Self {
self.help_heading = Some(heading.into_resettable().into_option());
self
}
@ -2414,7 +2409,7 @@ impl<'help> Arg<'help> {
}
/// # Advanced Argument Relations
impl<'help> Arg<'help> {
impl Arg {
/// The name of the [`ArgGroup`] the argument belongs to.
///
/// # Examples
@ -3535,7 +3530,7 @@ impl<'help> Arg<'help> {
}
/// # Reflection
impl<'help> Arg<'help> {
impl Arg {
/// Get the name of the argument
#[inline]
pub fn get_id(&self) -> &Id {
@ -3544,8 +3539,8 @@ impl<'help> Arg<'help> {
/// Get the help specified for this argument, if any
#[inline]
pub fn get_help(&self) -> Option<&'help str> {
self.help
pub fn get_help(&self) -> Option<&Str> {
self.help.as_ref()
}
/// Get the long help specified for this argument, if any
@ -3555,18 +3550,21 @@ impl<'help> Arg<'help> {
/// ```rust
/// # use clap::Arg;
/// let arg = Arg::new("foo").long_help("long help");
/// assert_eq!(Some("long help"), arg.get_long_help());
/// assert_eq!(Some("long help"), arg.get_long_help().map(|s| s.as_str()));
/// ```
///
#[inline]
pub fn get_long_help(&self) -> Option<&'help str> {
self.long_help
pub fn get_long_help(&self) -> Option<&Str> {
self.long_help.as_ref()
}
/// Get the help heading specified for this argument, if any
#[inline]
pub fn get_help_heading(&self) -> Option<&'help str> {
self.help_heading.unwrap_or_default()
pub fn get_help_heading(&self) -> Option<&Str> {
self.help_heading
.as_ref()
.map(|s| s.as_ref())
.unwrap_or_default()
}
/// Get the short option name for this argument, if any
@ -3616,13 +3614,13 @@ impl<'help> Arg<'help> {
/// Get the long option name for this argument, if any
#[inline]
pub fn get_long(&self) -> Option<&'help str> {
self.long
pub fn get_long(&self) -> Option<&Str> {
self.long.as_ref()
}
/// Get visible aliases for this argument, if any
#[inline]
pub fn get_visible_aliases(&self) -> Option<Vec<&'help str>> {
pub fn get_visible_aliases(&self) -> Option<Vec<&Str>> {
if self.aliases.is_empty() {
None
} else {
@ -3630,7 +3628,6 @@ impl<'help> Arg<'help> {
self.aliases
.iter()
.filter_map(|(s, v)| if *v { Some(s) } else { None })
.copied()
.collect(),
)
}
@ -3638,18 +3635,18 @@ impl<'help> Arg<'help> {
/// Get *all* aliases for this argument, if any, both visible and hidden.
#[inline]
pub fn get_all_aliases(&self) -> Option<Vec<&'help str>> {
pub fn get_all_aliases(&self) -> Option<Vec<&Str>> {
if self.aliases.is_empty() {
None
} else {
Some(self.aliases.iter().map(|(s, _)| s).copied().collect())
Some(self.aliases.iter().map(|(s, _)| s).collect())
}
}
/// Get the long option name and its visible aliases, if any
#[inline]
pub fn get_long_and_visible_aliases(&self) -> Option<Vec<&'help str>> {
let mut longs = match self.long {
pub fn get_long_and_visible_aliases(&self) -> Option<Vec<&Str>> {
let mut longs = match self.get_long() {
Some(long) => vec![long],
None => return None,
};
@ -3672,7 +3669,7 @@ impl<'help> Arg<'help> {
/// Get the names of values for this argument.
#[inline]
pub fn get_value_names(&self) -> Option<&[&'help str]> {
pub fn get_value_names(&self) -> Option<&[Str]> {
if self.val_names.is_empty() {
None
} else {
@ -3880,7 +3877,7 @@ impl<'help> Arg<'help> {
}
/// # Internally used only
impl<'help> Arg<'help> {
impl Arg {
pub(crate) fn _build(&mut self) {
if self.action.is_none() {
if self.num_vals == Some(ValueRange::EMPTY) {
@ -3984,38 +3981,38 @@ impl<'help> Arg<'help> {
}
}
impl<'help> From<&'_ Arg<'help>> for Arg<'help> {
fn from(a: &Arg<'help>) -> Self {
impl From<&'_ Arg> for Arg {
fn from(a: &Arg) -> Self {
a.clone()
}
}
impl<'help> PartialEq for Arg<'help> {
fn eq(&self, other: &Arg<'help>) -> bool {
impl PartialEq for Arg {
fn eq(&self, other: &Arg) -> bool {
self.get_id() == other.get_id()
}
}
impl<'help> PartialOrd for Arg<'help> {
impl PartialOrd for Arg {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<'help> Ord for Arg<'help> {
impl Ord for Arg {
fn cmp(&self, other: &Arg) -> Ordering {
self.id.cmp(&other.id)
}
}
impl<'help> Eq for Arg<'help> {}
impl Eq for Arg {}
impl<'help> Display for Arg<'help> {
impl Display for Arg {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
// Write the name such --long or -l
if let Some(l) = self.long {
if let Some(l) = self.get_long() {
write!(f, "--{}", l)?;
} else if let Some(s) = self.short {
} else if let Some(s) = self.get_short() {
write!(f, "-{}", s)?;
}
let mut need_closing_bracket = false;
@ -4056,7 +4053,7 @@ impl<'help> Display for Arg<'help> {
}
}
impl<'help> fmt::Debug for Arg<'help> {
impl fmt::Debug for Arg {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
let mut ds = f.debug_struct("Arg");
@ -4105,12 +4102,10 @@ pub(crate) fn render_arg_val(arg: &Arg) -> String {
let delim = " ";
let arg_name_storage;
let val_names = if arg.val_names.is_empty() {
arg_name_storage = [arg.get_id().as_str()];
&arg_name_storage
vec![arg.id.as_internal_str().to_owned()]
} else {
arg.val_names.as_slice()
arg.val_names.clone()
};
let mut extra_values = false;
@ -4193,10 +4188,10 @@ mod test {
fn flag_display_multiple_aliases() {
let mut f = Arg::new("flg").short('f').action(ArgAction::SetTrue);
f.aliases = vec![
("alias_not_visible", false),
("f2", true),
("f3", true),
("f4", true),
("alias_not_visible".into(), false),
("f2".into(), true),
("f3".into(), true),
("f4".into(), true),
];
f._build();

File diff suppressed because it is too large Load diff

View file

@ -67,7 +67,7 @@ pub(crate) fn assert_app(cmd: &Command) {
arg.get_id()
);
if let Some(s) = arg.short.as_ref() {
if let Some(s) = arg.get_short() {
short_flags.push(Flag::Arg(format!("-{}", s), arg.get_id().as_str()));
}
@ -78,7 +78,7 @@ pub(crate) fn assert_app(cmd: &Command) {
));
}
if let Some(l) = arg.long.as_ref() {
if let Some(l) = arg.get_long() {
assert!(!l.starts_with('-'), "Argument {}: long {:?} must not start with a `-`, that will be handled by the parser", arg.get_id(), l);
long_flags.push(Flag::Arg(format!("--{}", l), arg.get_id().as_str()));
}
@ -101,8 +101,8 @@ pub(crate) fn assert_app(cmd: &Command) {
}
// Long conflicts
if let Some(l) = arg.long {
if let Some((first, second)) = cmd.two_args_of(|x| x.long == Some(l)) {
if let Some(l) = arg.get_long() {
if let Some((first, second)) = cmd.two_args_of(|x| x.get_long() == Some(l)) {
panic!(
"Command {}: Long option names must be unique for each argument, \
but '--{}' is in use by both '{}' and '{}'{}",
@ -116,7 +116,7 @@ pub(crate) fn assert_app(cmd: &Command) {
}
// Short conflicts
if let Some(s) = arg.short {
if let Some(s) = arg.get_short() {
if let Some((first, second)) = cmd.two_args_of(|x| x.short == Some(s)) {
panic!(
"Command {}: Short option names must be unique for each argument, \
@ -356,7 +356,7 @@ pub(crate) fn assert_app(cmd: &Command) {
assert_app_flags(cmd);
}
fn duplicate_tip(cmd: &Command<'_>, first: &Arg<'_>, second: &Arg<'_>) -> &'static str {
fn duplicate_tip(cmd: &Command, first: &Arg, second: &Arg) -> &'static str {
if !cmd.is_disable_help_flag_set() && (first.id == Id::HELP || second.id == Id::HELP) {
" (call `cmd.disable_help_flag(true)` to remove the auto-generated `--help`)"
} else if !cmd.is_disable_version_flag_set()

View file

@ -151,9 +151,9 @@ impl PossibleValue {
/// Get the help specified for this argument, if any and the argument
/// value is not hidden
#[inline]
pub(crate) fn get_visible_help(&self) -> Option<&str> {
pub(crate) fn get_visible_help(&self) -> Option<&Str> {
if !self.hide {
self.help.as_deref()
self.help.as_ref()
} else {
None
}

View file

@ -19,6 +19,21 @@ impl<T> Resettable<T> {
}
}
impl<T> From<T> for Resettable<T> {
fn from(other: T) -> Self {
Self::Value(other)
}
}
impl<T> From<Option<T>> for Resettable<T> {
fn from(other: Option<T>) -> Self {
match other {
Some(inner) => Self::Value(inner),
None => Self::Reset,
}
}
}
/// Convert to the intended resettable type
pub trait IntoResettable<T> {
/// Convert to the intended resettable type
@ -34,6 +49,21 @@ impl IntoResettable<crate::OsStr> for Option<&'static str> {
}
}
impl IntoResettable<crate::Str> for Option<&'static str> {
fn into_resettable(self) -> Resettable<crate::Str> {
match self {
Some(s) => Resettable::Value(s.into()),
None => Resettable::Reset,
}
}
}
impl<T> IntoResettable<T> for Resettable<T> {
fn into_resettable(self) -> Resettable<T> {
self
}
}
impl<I: Into<crate::OsStr>> IntoResettable<crate::OsStr> for I {
fn into_resettable(self) -> Resettable<crate::OsStr> {
Resettable::Value(self.into())

View file

@ -9,7 +9,11 @@ fn propagate_version() {
.subcommand(Command::new("sub1"));
cmd._propagate();
assert_eq!(
cmd.get_subcommands().next().unwrap().get_version(),
cmd.get_subcommands()
.next()
.unwrap()
.get_version()
.map(|s| s.as_str()),
Some("1.1")
);
}

View file

@ -163,11 +163,11 @@ pub trait CommandFactory: Sized {
/// Build a [`Command`] that can instantiate `Self`.
///
/// See [`FromArgMatches::from_arg_matches_mut`] for instantiating `Self`.
fn command<'help>() -> Command<'help>;
fn command() -> Command;
/// Build a [`Command`] that can update `self`.
///
/// See [`FromArgMatches::update_from_arg_matches_mut`] for updating `self`.
fn command_for_update<'help>() -> Command<'help>;
fn command_for_update() -> Command;
}
/// Converts an instance of [`ArgMatches`] to a user-defined container.
@ -285,13 +285,13 @@ pub trait Args: FromArgMatches + Sized {
/// Append to [`Command`] so it can instantiate `Self`.
///
/// See also [`CommandFactory`].
fn augment_args(cmd: Command<'_>) -> Command<'_>;
fn augment_args(cmd: Command) -> Command;
/// Append to [`Command`] so it can update `self`.
///
/// This is used to implement `#[clap(flatten)]`
///
/// See also [`CommandFactory`].
fn augment_args_for_update(cmd: Command<'_>) -> Command<'_>;
fn augment_args_for_update(cmd: Command) -> Command;
}
/// Parse a sub-command into a user-defined enum.
@ -327,13 +327,13 @@ pub trait Subcommand: FromArgMatches + Sized {
/// Append to [`Command`] so it can instantiate `Self`.
///
/// See also [`CommandFactory`].
fn augment_subcommands(cmd: Command<'_>) -> Command<'_>;
fn augment_subcommands(cmd: Command) -> Command;
/// Append to [`Command`] so it can update `self`.
///
/// This is used to implement `#[clap(flatten)]`
///
/// See also [`CommandFactory`].
fn augment_subcommands_for_update(cmd: Command<'_>) -> Command<'_>;
fn augment_subcommands_for_update(cmd: Command) -> Command;
/// Test whether `Self` can parse a specific subcommand
fn has_subcommand(name: &str) -> bool;
}
@ -417,10 +417,10 @@ impl<T: Parser> Parser for Box<T> {
}
impl<T: CommandFactory> CommandFactory for Box<T> {
fn command<'help>() -> Command<'help> {
fn command<'help>() -> Command {
<T as CommandFactory>::command()
}
fn command_for_update<'help>() -> Command<'help> {
fn command_for_update<'help>() -> Command {
<T as CommandFactory>::command_for_update()
}
}
@ -441,19 +441,19 @@ impl<T: FromArgMatches> FromArgMatches for Box<T> {
}
impl<T: Args> Args for Box<T> {
fn augment_args(cmd: Command<'_>) -> Command<'_> {
fn augment_args(cmd: Command) -> Command {
<T as Args>::augment_args(cmd)
}
fn augment_args_for_update(cmd: Command<'_>) -> Command<'_> {
fn augment_args_for_update(cmd: Command) -> Command {
<T as Args>::augment_args_for_update(cmd)
}
}
impl<T: Subcommand> Subcommand for Box<T> {
fn augment_subcommands(cmd: Command<'_>) -> Command<'_> {
fn augment_subcommands(cmd: Command) -> Command {
<T as Subcommand>::augment_subcommands(cmd)
}
fn augment_subcommands_for_update(cmd: Command<'_>) -> Command<'_> {
fn augment_subcommands_for_update(cmd: Command) -> Command {
<T as Subcommand>::augment_subcommands_for_update(cmd)
}
fn has_subcommand(name: &str) -> bool {

View file

@ -1,8 +1,8 @@
use std::iter::Iterator;
use std::ops::Index;
use std::{ffi::OsStr, ffi::OsString};
use crate::Arg;
use crate::OsStr;
use crate::INTERNAL_ERROR_MSG;
#[derive(PartialEq, Eq, Debug, Clone)]
@ -12,9 +12,9 @@ pub(crate) struct Key {
}
#[derive(Default, PartialEq, Eq, Debug, Clone)]
pub(crate) struct MKeyMap<'help> {
pub(crate) struct MKeyMap {
/// All of the arguments.
args: Vec<Arg<'help>>,
args: Vec<Arg>,
// Cache part:
/// Will be set after `_build()`.
@ -24,7 +24,7 @@ pub(crate) struct MKeyMap<'help> {
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub(crate) enum KeyType {
Short(char),
Long(OsString),
Long(OsStr),
Position(usize),
}
@ -79,7 +79,7 @@ impl PartialEq<char> for KeyType {
}
}
impl<'help> MKeyMap<'help> {
impl MKeyMap {
/// If any arg has corresponding key in this map, we can search the key with
/// u64(for positional argument), char(for short flag), &str and OsString
/// (for long flag)
@ -96,14 +96,14 @@ impl<'help> MKeyMap<'help> {
}
/// Push an argument in the map.
pub(crate) fn push(&mut self, new_arg: Arg<'help>) {
pub(crate) fn push(&mut self, new_arg: Arg) {
self.args.push(new_arg);
}
/// Find the arg have corresponding key in this map, we can search the key
/// with u64(for positional argument), char(for short flag), &str and
/// OsString (for long flag)
pub(crate) fn get<K: ?Sized>(&self, key: &K) -> Option<&Arg<'help>>
pub(crate) fn get<K: ?Sized>(&self, key: &K) -> Option<&Arg>
where
KeyType: PartialEq<K>,
{
@ -124,12 +124,12 @@ impl<'help> MKeyMap<'help> {
}
/// Return iterators of all args.
pub(crate) fn args(&self) -> impl Iterator<Item = &Arg<'help>> {
pub(crate) fn args(&self) -> impl Iterator<Item = &Arg> {
self.args.iter()
}
/// Return mutable iterators of all args.
pub(crate) fn args_mut<'map>(&'map mut self) -> impl Iterator<Item = &'map mut Arg<'help>> {
pub(crate) fn args_mut(&mut self) -> impl Iterator<Item = &mut Arg> {
self.args.iter_mut()
}
@ -143,7 +143,7 @@ impl<'help> MKeyMap<'help> {
/// Remove an arg in the graph by Id, usually used by `mut_arg`. Return
/// `Some(arg)` if removed.
pub(crate) fn remove_by_name(&mut self, name: &str) -> Option<Arg<'help>> {
pub(crate) fn remove_by_name(&mut self, name: &str) -> Option<Arg> {
self.args
.iter()
.position(|arg| arg.id == name)
@ -152,8 +152,8 @@ impl<'help> MKeyMap<'help> {
}
}
impl<'help> Index<&'_ KeyType> for MKeyMap<'help> {
type Output = Arg<'help>;
impl Index<&'_ KeyType> for MKeyMap {
type Output = Arg;
fn index(&self, key: &KeyType) -> &Self::Output {
self.get(key).expect(INTERNAL_ERROR_MSG)
@ -166,12 +166,12 @@ fn append_keys(keys: &mut Vec<Key>, arg: &Arg, index: usize) {
let key = KeyType::Position(pos_index);
keys.push(Key { key, index });
} else {
if let Some(short) = arg.short {
if let Some(short) = arg.get_short() {
let key = KeyType::Short(short);
keys.push(Key { key, index });
}
if let Some(long) = arg.long {
let key = KeyType::Long(OsString::from(long));
if let Some(long) = arg.get_long() {
let key = KeyType::Long(long.into());
keys.push(Key { key, index });
}
@ -180,7 +180,7 @@ fn append_keys(keys: &mut Vec<Key>, arg: &Arg, index: usize) {
keys.push(Key { key, index });
}
for (long, _) in arg.aliases.iter() {
let key = KeyType::Long(OsString::from(long));
let key = KeyType::Long(long.into());
keys.push(Key { key, index });
}
}

View file

@ -10,6 +10,7 @@ use crate::builder::PossibleValue;
use crate::builder::{render_arg_val, Arg, Command};
use crate::output::{fmt::Colorizer, Usage};
use crate::util::FlatSet;
use crate::util::Str;
use crate::ArgAction;
// Third party
@ -18,17 +19,17 @@ use textwrap::core::display_width;
/// `clap` Help Writer.
///
/// Wraps a writer stream providing different methods to generate help for `clap` objects.
pub(crate) struct Help<'help, 'cmd, 'writer> {
pub(crate) struct Help<'cmd, 'writer> {
writer: HelpWriter<'writer>,
cmd: &'cmd Command<'help>,
usage: &'cmd Usage<'help, 'cmd>,
cmd: &'cmd Command,
usage: &'cmd Usage<'cmd>,
next_line_help: bool,
term_w: usize,
use_long: bool,
}
// Public Functions
impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
impl<'cmd, 'writer> Help<'cmd, 'writer> {
const DEFAULT_TEMPLATE: &'static str = "\
{before-help}{name} {version}\n\
{author-with-newline}{about-with-newline}\n\
@ -46,8 +47,8 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
/// Create a new `Help` instance.
pub(crate) fn new(
writer: HelpWriter<'writer>,
cmd: &'cmd Command<'help>,
usage: &'cmd Usage<'help, 'cmd>,
cmd: &'cmd Command,
usage: &'cmd Usage<'cmd>,
use_long: bool,
) -> Self {
debug!("Help::new cmd={}, use_long={}", cmd.get_name(), use_long);
@ -79,9 +80,9 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
debug!("Help::write_help");
if let Some(h) = self.cmd.get_override_help() {
self.none(h)?;
self.none(h.as_str())?;
} else if let Some(tmpl) = self.cmd.get_help_template() {
self.write_templated_help(tmpl)?;
self.write_templated_help(tmpl.as_str())?;
} else {
let pos = self
.cmd
@ -119,7 +120,7 @@ macro_rules! write_method {
}
// Methods to write Arg help.
impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
impl<'cmd, 'writer> Help<'cmd, 'writer> {
#[inline(never)]
fn good<T: Into<String> + AsRef<[u8]>>(&mut self, msg: T) -> io::Result<()> {
write_method!(self, msg, good)
@ -148,7 +149,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
}
/// Writes help for each argument in the order they were declared to the wrapped stream.
fn write_args_unsorted(&mut self, args: &[&Arg<'help>]) -> io::Result<()> {
fn write_args_unsorted(&mut self, args: &[&Arg]) -> io::Result<()> {
debug!("Help::write_args_unsorted");
// The shortest an arg can legally be is 2 (i.e. '-x')
let mut longest = 2;
@ -179,7 +180,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
}
/// Sorts arguments by length and display order and write their help to the wrapped stream.
fn write_args(&mut self, args: &[&Arg<'help>], _category: &str) -> io::Result<()> {
fn write_args(&mut self, args: &[&Arg], _category: &str) -> io::Result<()> {
debug!("Help::write_args {}", _category);
// The shortest an arg can legally be is 2 (i.e. '-x')
let mut longest = 2;
@ -209,11 +210,11 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
// by arg name).
// Example order: -a, -b, -B, -s, --select-file, --select-folder, -x
let key = if let Some(x) = arg.short {
let key = if let Some(x) = arg.get_short() {
let mut s = x.to_ascii_lowercase().to_string();
s.push(if x.is_ascii_lowercase() { '0' } else { '1' });
s
} else if let Some(x) = arg.long {
} else if let Some(x) = arg.get_long() {
x.to_string()
} else {
let mut s = '{'.to_string();
@ -236,7 +237,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
/// Writes help for an argument to the wrapped stream.
fn write_arg(
&mut self,
arg: &Arg<'help>,
arg: &Arg,
last_arg: bool,
next_line_help: bool,
longest: usize,
@ -249,12 +250,22 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
self.align_to_about(arg, next_line_help, longest)?;
let about = if self.use_long {
arg.long_help.or(arg.help).unwrap_or("")
arg.get_long_help()
.or_else(|| arg.get_help())
.unwrap_or_default()
} else {
arg.help.or(arg.long_help).unwrap_or("")
arg.get_help()
.or_else(|| arg.get_long_help())
.unwrap_or_default()
};
self.help(Some(arg), about, spec_vals, next_line_help, longest)?;
self.help(
Some(arg),
about.as_str(),
spec_vals,
next_line_help,
longest,
)?;
if !last_arg {
self.none("\n")?;
@ -266,12 +277,12 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
}
/// Writes argument's short command to the wrapped stream.
fn short(&mut self, arg: &Arg<'help>) -> io::Result<()> {
fn short(&mut self, arg: &Arg) -> io::Result<()> {
debug!("Help::short");
self.none(TAB)?;
if let Some(s) = arg.short {
if let Some(s) = arg.get_short() {
self.good(format!("-{}", s))
} else if !arg.is_positional() {
self.none(TAB)
@ -281,9 +292,9 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
}
/// Writes argument's long command to the wrapped stream.
fn long(&mut self, arg: &Arg<'help>) -> io::Result<()> {
fn long(&mut self, arg: &Arg) -> io::Result<()> {
debug!("Help::long");
if let Some(long) = arg.long {
if let Some(long) = arg.get_long() {
if arg.short.is_some() {
self.none(", ")?;
}
@ -293,7 +304,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
}
/// Writes argument's possible values to the wrapped stream.
fn val(&mut self, arg: &Arg<'help>) -> io::Result<()> {
fn val(&mut self, arg: &Arg) -> io::Result<()> {
debug!("Help::val: arg={}", arg.get_id());
let mut need_closing_bracket = false;
if arg.is_takes_value_set() && !arg.is_positional() {
@ -329,7 +340,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
/// Write alignment padding between arg's switches/values and its about message.
fn align_to_about(
&mut self,
arg: &Arg<'help>,
arg: &Arg,
next_line_help: bool,
longest: usize,
) -> io::Result<()> {
@ -409,7 +420,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
/// Writes argument's help to the wrapped stream.
fn help(
&mut self,
arg: Option<&Arg<'help>>,
arg: Option<&Arg>,
about: &str,
spec_vals: &str,
next_line_help: bool,
@ -484,7 +495,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
.expect("Only called with possible value");
let help_longest = possible_vals
.iter()
.filter_map(|f| f.get_visible_help().map(display_width))
.filter_map(|f| f.get_visible_help().map(|s| display_width(s.as_str())))
.max()
.expect("Only called with possible value with help");
// should new line
@ -540,7 +551,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
}
/// Will use next line help on writing args.
fn will_args_wrap(&self, args: &[&Arg<'help>], longest: usize) -> bool {
fn will_args_wrap(&self, args: &[&Arg], longest: usize) -> bool {
args.iter()
.filter(|arg| should_show_arg(self.use_long, *arg))
.any(|arg| {
@ -549,14 +560,14 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
})
}
fn arg_next_line_help(&self, arg: &Arg<'help>, spec_vals: &str, longest: usize) -> bool {
fn arg_next_line_help(&self, arg: &Arg, spec_vals: &str, longest: usize) -> bool {
if self.next_line_help || arg.is_next_line_help_set() || self.use_long {
// setting_next_line
true
} else {
// force_next_line
let h = arg.help.unwrap_or("");
let h_w = display_width(h) + display_width(spec_vals);
let h = arg.get_help().unwrap_or_default();
let h_w = display_width(h.as_str()) + display_width(spec_vals);
let taken = longest + 12;
self.term_w >= taken
&& (taken as f32 / self.term_w as f32) > 0.40
@ -617,7 +628,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
.aliases
.iter()
.filter(|&als| als.1) // visible
.map(|&als| als.0) // name
.map(|als| als.0.as_str()) // name
.collect::<Vec<_>>()
.join(", ");
@ -661,7 +672,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
spec_vals.push(format!("[possible values: {}]", pvs));
}
let connector = if self.use_long { "\n" } else { " " };
let prefix = if !spec_vals.is_empty() && !a.get_help().unwrap_or("").is_empty() {
let prefix = if !spec_vals.is_empty() && !a.get_help().unwrap_or_default().is_empty() {
if self.use_long {
"\n\n"
} else {
@ -717,11 +728,11 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
}
/// Methods to write a single subcommand
impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
impl<'cmd, 'writer> Help<'cmd, 'writer> {
fn write_subcommand(
&mut self,
sc_str: &str,
cmd: &Command<'help>,
cmd: &Command,
next_line_help: bool,
longest: usize,
) -> io::Result<()> {
@ -732,7 +743,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
let about = cmd
.get_about()
.or_else(|| cmd.get_long_about())
.unwrap_or("");
.unwrap_or_default();
self.subcmd(sc_str, next_line_help, longest)?;
self.help(None, about, spec_vals, next_line_help, longest)
@ -769,18 +780,13 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
spec_vals.join(" ")
}
fn subcommand_next_line_help(
&self,
cmd: &Command<'help>,
spec_vals: &str,
longest: usize,
) -> bool {
fn subcommand_next_line_help(&self, cmd: &Command, spec_vals: &str, longest: usize) -> bool {
if self.next_line_help | self.use_long {
// setting_next_line
true
} else {
// force_next_line
let h = cmd.get_about().unwrap_or("");
let h = cmd.get_about().unwrap_or_default();
let h_w = display_width(h) + display_width(spec_vals);
let taken = longest + 12;
self.term_w >= taken
@ -802,7 +808,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
}
// Methods to write Parser help.
impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
impl<'cmd, 'writer> Help<'cmd, 'writer> {
/// Writes help for all arguments (options, flags, args, subcommands)
/// including titles of a Parser Object to the wrapped stream.
pub(crate) fn write_all_args(&mut self) -> io::Result<()> {
@ -872,10 +878,12 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
self.none("\n\n")?;
}
let default_help_heading = Str::from("SUBCOMMANDS");
self.warning(
self.cmd
.get_subcommand_help_heading()
.unwrap_or("SUBCOMMANDS"),
.unwrap_or(&default_help_heading)
.as_str(),
)?;
self.warning(":\n")?;
@ -888,12 +896,9 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
/// Will use next line help on writing subcommands.
fn will_subcommands_wrap<'a>(
&self,
subcommands: impl IntoIterator<Item = &'a Command<'help>>,
subcommands: impl IntoIterator<Item = &'a Command>,
longest: usize,
) -> bool
where
'help: 'a,
{
) -> bool {
subcommands
.into_iter()
.filter(|&subcommand| should_show_subcommand(subcommand))
@ -904,7 +909,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
}
/// Writes help for subcommands of a Parser Object to the wrapped stream.
fn write_subcommands(&mut self, cmd: &Command<'help>) -> io::Result<()> {
fn write_subcommands(&mut self, cmd: &Command) -> io::Result<()> {
debug!("Help::write_subcommands");
// The shortest an arg can legally be is 2 (i.e. '-x')
let mut longest = 2;
@ -978,7 +983,7 @@ impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
}
// Methods to write Parser help using templates.
impl<'help, 'cmd, 'writer> Help<'help, 'cmd, 'writer> {
impl<'cmd, 'writer> Help<'cmd, 'writer> {
/// Write help to stream for the parser in the format defined by the template.
///
/// For details about the template language see [`Command::help_template`].

View file

@ -4,15 +4,18 @@ use crate::parser::ArgMatcher;
use crate::util::ChildGraph;
use crate::util::FlatSet;
use crate::util::Id;
use crate::util::Str;
use crate::INTERNAL_ERROR_MSG;
pub(crate) struct Usage<'help, 'cmd> {
cmd: &'cmd Command<'help>,
static DEFAULT_SUB_VALUE_NAME: Str = Str::from_static_ref("SUBCOMMAND");
pub(crate) struct Usage<'cmd> {
cmd: &'cmd Command,
required: Option<&'cmd ChildGraph<Id>>,
}
impl<'help, 'cmd> Usage<'help, 'cmd> {
pub(crate) fn new(cmd: &'cmd Command<'help>) -> Self {
impl<'cmd> Usage<'cmd> {
pub(crate) fn new(cmd: &'cmd Command) -> Self {
Usage {
cmd,
required: None,
@ -38,7 +41,7 @@ impl<'help, 'cmd> Usage<'help, 'cmd> {
pub(crate) fn create_usage_no_title(&self, used: &[Id]) -> String {
debug!("Usage::create_usage_no_title");
if let Some(u) = self.cmd.get_override_usage() {
String::from(u)
String::from(u.as_str())
} else if used.is_empty() {
self.create_help_usage(true)
} else {
@ -53,8 +56,8 @@ impl<'help, 'cmd> Usage<'help, 'cmd> {
let name = self
.cmd
.get_usage_name()
.or_else(|| self.cmd.get_bin_name())
.unwrap_or_else(|| self.cmd.get_name());
.or_else(|| self.cmd.get_bin_name().map(|s| s.as_str()))
.unwrap_or_else(|| self.cmd.get_name().as_str());
usage.push_str(name);
let req_string = if incl_reqs {
self.get_required_usage_from(&[], None, false)
@ -129,7 +132,10 @@ impl<'help, 'cmd> Usage<'help, 'cmd> {
if self.cmd.has_visible_subcommands() && incl_reqs
|| self.cmd.is_allow_external_subcommands_set()
{
let placeholder = self.cmd.get_subcommand_value_name().unwrap_or("SUBCOMMAND");
let placeholder = 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()
{
@ -171,13 +177,17 @@ impl<'help, 'cmd> Usage<'help, 'cmd> {
usage.push_str(
self.cmd
.get_usage_name()
.or_else(|| self.cmd.get_bin_name())
.unwrap_or_else(|| self.cmd.get_name()),
.or_else(|| self.cmd.get_bin_name().map(|s| s.as_str()))
.unwrap_or_else(|| self.cmd.get_name().as_str()),
);
usage.push_str(&*r_string);
if self.cmd.is_subcommand_required_set() {
usage.push_str(" <");
usage.push_str(self.cmd.get_subcommand_value_name().unwrap_or("SUBCOMMAND"));
usage.push_str(
self.cmd
.get_subcommand_value_name()
.unwrap_or(&DEFAULT_SUB_VALUE_NAME),
);
usage.push('>');
}
usage.shrink_to_fit();
@ -301,7 +311,9 @@ impl<'help, 'cmd> Usage<'help, 'cmd> {
debug!("Usage::needs_options_tag:iter: f={}", f.get_id());
// Don't print `[OPTIONS]` just for help or version
if f.long == Some("help") || f.long == Some("version") {
if f.get_long().map(|s| s.as_str()) == Some("help")
|| f.get_long().map(|s| s.as_str()) == Some("version")
{
debug!("Usage::needs_options_tag:iter Option is built-in");
continue;
}

View file

@ -32,7 +32,7 @@ impl ArgMatcher {
#[cfg(debug_assertions)]
valid_subcommands: _cmd
.get_subcommands()
.map(|sc| sc.get_name().to_owned())
.map(|sc| sc.get_name().clone())
.collect(),
..Default::default()
},

View file

@ -37,7 +37,7 @@ pub(crate) fn did_you_mean_flag<'a, 'help, I, T>(
arg: &str,
remaining_args: &[&str],
longs: I,
subcommands: impl IntoIterator<Item = &'a mut Command<'help>>,
subcommands: impl IntoIterator<Item = &'a mut Command>,
) -> Option<(String, Option<String>)>
where
'help: 'a,
@ -64,7 +64,7 @@ where
let subcommand_name = subcommand.get_name();
let candidate = did_you_mean(arg, longs).pop()?;
let score = remaining_args.iter().position(|x| *x == subcommand_name)?;
let score = remaining_args.iter().position(|x| *subcommand_name == *x)?;
Some((score, (candidate, Some(subcommand_name.to_string()))))
})
.min_by_key(|(x, _)| *x)

View file

@ -13,6 +13,7 @@ use crate::parser::MatchesError;
use crate::parser::ValueSource;
use crate::util::FlatMap;
use crate::util::Id;
use crate::Str;
use crate::INTERNAL_ERROR_MSG;
/// Container for parse results.
@ -65,7 +66,7 @@ pub struct ArgMatches {
#[cfg(debug_assertions)]
pub(crate) valid_args: Vec<Id>,
#[cfg(debug_assertions)]
pub(crate) valid_subcommands: Vec<String>,
pub(crate) valid_subcommands: Vec<Str>,
pub(crate) args: FlatMap<Id, MatchedArg>,
pub(crate) subcommand: Option<Box<SubCommand>>,
}
@ -777,7 +778,7 @@ impl ArgMatches {
/// }
/// ```
/// [subcommand]: crate::Command::subcommand
pub fn remove_subcommand(&mut self) -> Option<(String, ArgMatches)> {
pub fn remove_subcommand(&mut self) -> Option<(Str, ArgMatches)> {
self.subcommand.take().map(|sc| (sc.name, sc.matches))
}
@ -862,8 +863,8 @@ impl ArgMatches {
pub fn is_valid_subcommand(&self, _name: &str) -> bool {
#[cfg(debug_assertions)]
{
let _name = _name.to_owned();
_name == String::default() || self.valid_subcommands.contains(&_name)
let _name = Str::from(_name.to_owned());
_name == "" || self.valid_subcommands.contains(&_name)
}
#[cfg(not(debug_assertions))]
{
@ -1072,8 +1073,8 @@ impl ArgMatches {
fn get_subcommand(&self, name: &str) -> Option<&SubCommand> {
#[cfg(debug_assertions)]
{
let name = name.to_owned();
if name == String::default() || self.valid_subcommands.contains(&name) {
let name = Str::from(name.to_owned());
if name == "" || self.valid_subcommands.contains(&name) {
} else {
panic!("`{}` is not a name of a subcommand.", name);
}
@ -1091,7 +1092,7 @@ impl ArgMatches {
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct SubCommand {
pub(crate) name: String,
pub(crate) name: Str,
pub(crate) matches: ArgMatches,
}

View file

@ -21,10 +21,11 @@ use crate::parser::{ArgMatcher, SubCommand};
use crate::parser::{Validator, ValueSource};
use crate::util::Id;
use crate::ArgAction;
use crate::Str;
use crate::{INTERNAL_ERROR_MSG, INVALID_UTF8};
pub(crate) struct Parser<'help, 'cmd> {
cmd: &'cmd mut Command<'help>,
pub(crate) struct Parser<'cmd> {
cmd: &'cmd mut Command,
cur_idx: Cell<usize>,
/// Index of the previous flag subcommand in a group of flags.
flag_subcmd_at: Option<usize>,
@ -34,8 +35,8 @@ pub(crate) struct Parser<'help, 'cmd> {
}
// Initializing Methods
impl<'help, 'cmd> Parser<'help, 'cmd> {
pub(crate) fn new(cmd: &'cmd mut Command<'help>) -> Self {
impl<'cmd> Parser<'cmd> {
pub(crate) fn new(cmd: &'cmd mut Command) -> Self {
Parser {
cmd,
cur_idx: Cell::new(0),
@ -46,7 +47,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
}
// Parsing Methods
impl<'help, 'cmd> Parser<'help, 'cmd> {
impl<'cmd> Parser<'cmd> {
// The actual parsing function
#[allow(clippy::cognitive_complexity)]
pub(crate) fn get_matches_with(
@ -417,7 +418,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
{
// Get external subcommand name
let sc_name = match arg_os.to_value() {
Ok(s) => s.to_string(),
Ok(s) => Str::from(s.to_owned()),
Err(_) => {
let _ = self.resolve_pending(matcher);
return Err(ClapError::invalid_utf8(
@ -508,6 +509,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
self.cmd
.get_bin_name()
.unwrap_or_else(|| self.cmd.get_name())
.as_str()
.to_owned(),
Usage::new(self.cmd).create_usage_with_title(&[]),
);
@ -563,7 +565,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
}
// Checks if the arg matches a long flag subcommand name, or any of its aliases (if defined)
fn possible_long_flag_subcommand(&self, arg: &str) -> Option<&str> {
fn possible_long_flag_subcommand(&self, arg: &str) -> Option<&Str> {
debug!("Parser::possible_long_flag_subcommand: arg={:?}", arg);
if self.cmd.is_infer_subcommands_set() {
let options = self
@ -697,7 +699,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
}
}
matcher.subcommand(SubCommand {
name: sc.get_name().to_owned(),
name: sc.get_name().clone(),
matches: sc_matcher.into_inner(),
});
}
@ -738,21 +740,18 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
}
let arg = if let Some(arg) = self.cmd.get_keymap().get(long_arg) {
debug!(
"Parser::parse_long_arg: Found valid arg or flag '{}'",
arg.to_string()
);
debug!("Parser::parse_long_arg: Found valid arg or flag '{}'", arg);
Some((long_arg, arg))
} else if self.cmd.is_infer_long_args_set() {
self.cmd.get_arguments().find_map(|a| {
if let Some(long) = a.long {
if let Some(long) = a.get_long() {
if long.starts_with(long_arg) {
return Some((long, a));
return Some((long.as_str(), a));
}
}
a.aliases
.iter()
.find_map(|(alias, _)| alias.starts_with(long_arg).then(|| (*alias, a)))
.find_map(|(alias, _)| alias.starts_with(long_arg).then(|| (alias.as_str(), a)))
})
} else {
None
@ -963,7 +962,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
&self,
ident: Identifier,
attached_value: Option<&RawOsStr>,
arg: &Arg<'help>,
arg: &Arg,
matcher: &mut ArgMatcher,
has_eq: bool,
) -> ClapResult<ParseResult> {
@ -1025,8 +1024,13 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
}
}
fn check_terminator(&self, arg: &Arg<'help>, val: &RawOsStr) -> Option<ParseResult> {
if Some(val) == arg.terminator.map(RawOsStr::from_str) {
fn check_terminator(&self, arg: &Arg, val: &RawOsStr) -> Option<ParseResult> {
if Some(val)
== arg
.terminator
.as_ref()
.map(|s| RawOsStr::from_str(s.as_str()))
{
debug!("Parser::check_terminator: terminator={:?}", arg.terminator);
Some(ParseResult::ValuesDone)
} else {
@ -1036,7 +1040,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
fn push_arg_values(
&self,
arg: &Arg<'help>,
arg: &Arg,
raw_vals: Vec<OsString>,
matcher: &mut ArgMatcher,
) -> ClapResult<()> {
@ -1094,7 +1098,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
&self,
ident: Option<Identifier>,
source: ValueSource,
arg: &Arg<'help>,
arg: &Arg,
mut raw_vals: Vec<OsString>,
mut trailing_idx: Option<usize>,
matcher: &mut ArgMatcher,
@ -1249,7 +1253,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
}
}
fn verify_num_args(&self, arg: &Arg<'help>, raw_vals: &[OsString]) -> ClapResult<()> {
fn verify_num_args(&self, arg: &Arg, raw_vals: &[OsString]) -> ClapResult<()> {
if self.cmd.is_ignore_errors_set() {
return Ok(());
}
@ -1305,7 +1309,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
Ok(())
}
fn remove_overrides(&self, arg: &Arg<'help>, matcher: &mut ArgMatcher) {
fn remove_overrides(&self, arg: &Arg, matcher: &mut ArgMatcher) {
debug!("Parser::remove_overrides: id={:?}", arg.id);
for override_id in &arg.overrides {
debug!("Parser::remove_overrides:iter:{:?}: removing", override_id);
@ -1369,7 +1373,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
Ok(())
}
fn add_default_value(&self, arg: &Arg<'help>, matcher: &mut ArgMatcher) -> ClapResult<()> {
fn add_default_value(&self, arg: &Arg, matcher: &mut ArgMatcher) -> ClapResult<()> {
if !arg.default_vals_ifs.is_empty() {
debug!("Parser::add_default_value: has conditional defaults");
if !matcher.contains(&arg.id) {
@ -1446,7 +1450,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
Ok(())
}
fn start_custom_arg(&self, matcher: &mut ArgMatcher, arg: &Arg<'help>, source: ValueSource) {
fn start_custom_arg(&self, matcher: &mut ArgMatcher, arg: &Arg, source: ValueSource) {
if source == ValueSource::CommandLine {
// With each new occurrence, remove overrides from prior occurrences
self.remove_overrides(arg, matcher);
@ -1458,7 +1462,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
}
/// Increase occurrence of specific argument and the grouped arg it's in.
fn start_occurrence_of_arg(&self, matcher: &mut ArgMatcher, arg: &Arg<'help>) {
fn start_occurrence_of_arg(&self, matcher: &mut ArgMatcher, arg: &Arg) {
// With each new occurrence, remove overrides from prior occurrences
self.remove_overrides(arg, matcher);
@ -1471,7 +1475,7 @@ impl<'help, 'cmd> Parser<'help, 'cmd> {
}
// Error, Help, and Version Methods
impl<'help, 'cmd> Parser<'help, 'cmd> {
impl<'cmd> Parser<'cmd> {
/// Is only used for the long flag(which is the only one needs fuzzy searching)
fn did_you_mean_error(
&mut self,

View file

@ -10,13 +10,13 @@ use crate::util::FlatSet;
use crate::util::Id;
use crate::INTERNAL_ERROR_MSG;
pub(crate) struct Validator<'help, 'cmd> {
cmd: &'cmd Command<'help>,
pub(crate) struct Validator<'cmd> {
cmd: &'cmd Command,
required: ChildGraph<Id>,
}
impl<'help, 'cmd> Validator<'help, 'cmd> {
pub(crate) fn new(cmd: &'cmd Command<'help>) -> Self {
impl<'cmd> Validator<'cmd> {
pub(crate) fn new(cmd: &'cmd Command) -> Self {
let required = cmd.required_graph();
Validator { cmd, required }
}
@ -306,7 +306,7 @@ impl<'help, 'cmd> Validator<'help, 'cmd> {
fn is_missing_required_ok(
&self,
a: &Arg<'help>,
a: &Arg,
matcher: &ArgMatcher,
conflicts: &mut Conflicts,
) -> bool {
@ -335,7 +335,7 @@ impl<'help, 'cmd> Validator<'help, 'cmd> {
}
// Failing a required unless means, the arg's "unless" wasn't present, and neither were they
fn fails_arg_required_unless(&self, a: &Arg<'help>, matcher: &ArgMatcher) -> bool {
fn fails_arg_required_unless(&self, a: &Arg, matcher: &ArgMatcher) -> bool {
debug!("Validator::fails_arg_required_unless: a={:?}", a.get_id());
let exists = |id| matcher.check_explicit(id, &ArgPredicate::IsPresent);
@ -455,7 +455,7 @@ impl Conflicts {
}
}
pub(crate) fn get_possible_values_cli(a: &Arg<'_>) -> Vec<PossibleValue> {
pub(crate) fn get_possible_values_cli(a: &Arg) -> Vec<PossibleValue> {
if !a.is_takes_value_set() {
vec![]
} else {

View file

@ -21,6 +21,10 @@ impl Id {
pub fn as_str(&self) -> &str {
self.0.as_str()
}
pub(crate) fn as_internal_str(&self) -> &Str {
&self.0
}
}
impl From<&'_ Id> for Id {
@ -65,6 +69,18 @@ impl From<&'_ &'static str> for Id {
}
}
impl From<Id> for Str {
fn from(name: Id) -> Self {
name.0
}
}
impl From<Id> for String {
fn from(name: Id) -> Self {
Str::from(name).into()
}
}
impl std::fmt::Display for Id {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

View file

@ -106,6 +106,18 @@ impl From<&'_ &'static str> for OsStr {
}
}
impl From<OsStr> for std::ffi::OsString {
fn from(name: OsStr) -> Self {
name.name.into_os_string()
}
}
impl From<OsStr> for std::path::PathBuf {
fn from(name: OsStr) -> Self {
std::ffi::OsString::from(name).into()
}
}
impl std::fmt::Debug for OsStr {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@ -221,6 +233,13 @@ impl Inner {
Self::Owned(s) => s.as_ref(),
}
}
fn into_os_string(self) -> std::ffi::OsString {
match self {
Self::Static(s) => std::ffi::OsString::from(s),
Self::Owned(s) => std::ffi::OsString::from(s),
}
}
}
impl Default for Inner {

View file

@ -70,6 +70,30 @@ impl From<&'_ &'static str> for Str {
}
}
impl From<Str> for String {
fn from(name: Str) -> Self {
name.name.into_string()
}
}
impl From<Str> for Vec<u8> {
fn from(name: Str) -> Self {
String::from(name).into()
}
}
impl From<Str> for std::ffi::OsString {
fn from(name: Str) -> Self {
String::from(name).into()
}
}
impl From<Str> for std::path::PathBuf {
fn from(name: Str) -> Self {
String::from(name).into()
}
}
impl std::fmt::Display for Str {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@ -206,6 +230,13 @@ impl Inner {
Self::Owned(s) => s.as_ref(),
}
}
fn into_string(self) -> String {
match self {
Self::Static(s) => String::from(s),
Self::Owned(s) => String::from(s),
}
}
}
impl Default for Inner {

View file

@ -30,7 +30,7 @@ USAGE:
For more information try --help
";
fn cmd() -> Command<'static> {
fn cmd() -> Command {
Command::new("prog")
.arg(
Arg::new("a")

View file

@ -2,7 +2,7 @@ use super::utils;
use clap::{arg, builder::PossibleValue, error::ErrorKind, Arg, ArgAction, ArgGroup, Command};
fn setup() -> Command<'static> {
fn setup() -> Command {
Command::new("test")
.author("Kevin K.")
.about("tests stuff")
@ -1523,7 +1523,7 @@ OPTIONS:
utils::assert_output(app1, "default --help", ESCAPED_DEFAULT_VAL, false);
}
fn issue_1112_setup() -> Command<'static> {
fn issue_1112_setup() -> Command {
Command::new("test")
.version("1.3")
.disable_help_flag(true)
@ -2728,7 +2728,10 @@ fn display_name_explicit() {
.bin_name("app.exe")
.display_name("app.display");
cmd.build();
assert_eq!(cmd.get_display_name(), Some("app.display"));
assert_eq!(
cmd.get_display_name().map(|s| s.as_str()),
Some("app.display")
);
}
#[test]
@ -2736,7 +2739,10 @@ fn display_name_subcommand_default() {
let mut cmd = Command::new("parent").subcommand(Command::new("child").bin_name("child.exe"));
cmd.build();
assert_eq!(
cmd.find_subcommand("child").unwrap().get_display_name(),
cmd.find_subcommand("child")
.unwrap()
.get_display_name()
.map(|s| s.as_str()),
Some("parent-child")
);
}
@ -2750,7 +2756,10 @@ fn display_name_subcommand_explicit() {
);
cmd.build();
assert_eq!(
cmd.find_subcommand("child").unwrap().get_display_name(),
cmd.find_subcommand("child")
.unwrap()
.get_display_name()
.map(|s| s.as_str()),
Some("child.display")
);
}

View file

@ -1,4 +1,5 @@
#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::redundant_clone)]
mod action;
mod app_settings;

View file

@ -1,6 +1,6 @@
use clap::{Arg, ArgAction, ArgMatches, Command};
fn get_app() -> Command<'static> {
fn get_app() -> Command {
Command::new("myprog")
.arg(
Arg::new("GLOBAL_ARG")
@ -20,7 +20,7 @@ fn get_app() -> Command<'static> {
.subcommand(Command::new("outer").subcommand(Command::new("inner")))
}
fn get_matches(cmd: Command<'static>, argv: &'static str) -> ArgMatches {
fn get_matches(cmd: Command, argv: &'static str) -> ArgMatches {
cmd.try_get_matches_from(argv.split(' ').collect::<Vec<_>>())
.unwrap()
}

View file

@ -1036,7 +1036,7 @@ USAGE:
For more information try --help
";
fn issue_1158_app() -> Command<'static> {
fn issue_1158_app() -> Command {
Command::new("example")
.arg(
arg!(-c --config <FILE> "Custom config file.")

View file

@ -451,7 +451,7 @@ For more information try --help
#[test]
fn busybox_like_multicall() {
fn applet_commands() -> [Command<'static>; 2] {
fn applet_commands() -> [Command; 2] {
[Command::new("true"), Command::new("false")]
}
let cmd = Command::new("busybox")

View file

@ -124,7 +124,7 @@ fn template_author_version() {
// ----------
fn get_app() -> Command<'static> {
fn get_app() -> Command {
Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")

View file

@ -36,7 +36,7 @@ pub fn assert_output(l: Command, args: &str, expected: &str, stderr: bool) {
// Legacy tests from the python script days
pub fn complex_app() -> Command<'static> {
pub fn complex_app() -> Command {
let opt3_vals = ["fast", "slow"];
let pos3_vals = ["vi", "emacs"];

View file

@ -1,18 +1,18 @@
use clap::{error::ErrorKind, ArgAction, Command};
fn common() -> Command<'static> {
fn common() -> Command {
Command::new("foo")
}
fn with_version() -> Command<'static> {
fn with_version() -> Command {
common().version("3.0")
}
fn with_long_version() -> Command<'static> {
fn with_long_version() -> Command {
common().long_version("3.0 (abcdefg)")
}
fn with_subcommand() -> Command<'static> {
fn with_subcommand() -> Command {
with_version().subcommand(Command::new("bar").subcommand(Command::new("baz")))
}

View file

@ -233,8 +233,11 @@ fn doc_comment_about_handles_both_abouts() {
}
let cmd = Opts::command();
assert_eq!(cmd.get_about(), Some("Opts doc comment summary"));
assert_eq!(
cmd.get_about().map(|s| s.as_str()),
Some("Opts doc comment summary")
);
// clap will fallback to `about` on `None`. The main care about is not providing a `Sub` doc
// comment.
assert_eq!(cmd.get_long_about(), None);
assert_eq!(cmd.get_long_about().map(|s| s.as_str()), None);
}

View file

@ -94,7 +94,11 @@ fn inferred_help() {
let mut cmd = Opt::command();
cmd.build();
let arg = cmd.get_arguments().find(|a| a.get_id() == "help").unwrap();
assert_eq!(arg.get_help(), Some("Foo"), "Incorrect help");
assert_eq!(
arg.get_help().map(|s| s.as_str()),
Some("Foo"),
"Incorrect help"
);
assert!(matches!(arg.get_action(), clap::ArgAction::Help));
}
@ -114,7 +118,11 @@ fn inferred_version() {
.get_arguments()
.find(|a| a.get_id() == "version")
.unwrap();
assert_eq!(arg.get_help(), Some("Foo"), "Incorrect help");
assert_eq!(
arg.get_help().map(|s| s.as_str()),
Some("Foo"),
"Incorrect help"
);
assert!(matches!(arg.get_action(), clap::ArgAction::Version));
}

View file

@ -18,7 +18,12 @@ fn arg_help_heading_applied() {
.get_arguments()
.find(|a| a.get_id() == "should_be_in_section_a")
.unwrap();
assert_eq!(should_be_in_section_a.get_help_heading(), Some("HEADING A"));
assert_eq!(
should_be_in_section_a
.get_help_heading()
.map(|s| s.as_str()),
Some("HEADING A")
);
let should_be_in_section_b = cmd
.get_arguments()
@ -46,14 +51,21 @@ fn app_help_heading_applied() {
.get_arguments()
.find(|a| a.get_id() == "should_be_in_section_a")
.unwrap();
assert_eq!(should_be_in_section_a.get_help_heading(), Some("HEADING A"));
assert_eq!(
should_be_in_section_a
.get_help_heading()
.map(|s| s.as_str()),
Some("HEADING A")
);
let should_be_in_default_section = cmd
.get_arguments()
.find(|a| a.get_id() == "should_be_in_default_section")
.unwrap();
assert_eq!(
should_be_in_default_section.get_help_heading(),
should_be_in_default_section
.get_help_heading()
.map(|s| s.as_str()),
Some("DEFAULT")
);
}
@ -123,13 +135,23 @@ fn app_help_heading_flattened() {
.get_arguments()
.find(|a| a.get_id() == "should_be_in_section_a")
.unwrap();
assert_eq!(should_be_in_section_a.get_help_heading(), Some("HEADING A"));
assert_eq!(
should_be_in_section_a
.get_help_heading()
.map(|s| s.as_str()),
Some("HEADING A")
);
let should_be_in_section_b = cmd
.get_arguments()
.find(|a| a.get_id() == "should_be_in_section_b")
.unwrap();
assert_eq!(should_be_in_section_b.get_help_heading(), Some("HEADING B"));
assert_eq!(
should_be_in_section_b
.get_help_heading()
.map(|s| s.as_str()),
Some("HEADING B")
);
let should_be_in_default_section = cmd
.get_arguments()
@ -143,7 +165,10 @@ fn app_help_heading_flattened() {
.get_arguments()
.find(|a| a.get_id() == "should_be_in_sub_a")
.unwrap();
assert_eq!(should_be_in_sub_a.get_help_heading(), Some("SUB A"));
assert_eq!(
should_be_in_sub_a.get_help_heading().map(|s| s.as_str()),
Some("SUB A")
);
let sub_b_one = cmd.find_subcommand("sub-b-one").unwrap();
@ -151,7 +176,10 @@ fn app_help_heading_flattened() {
.get_arguments()
.find(|a| a.get_id() == "should_be_in_sub_b")
.unwrap();
assert_eq!(should_be_in_sub_b.get_help_heading(), Some("SUB B"));
assert_eq!(
should_be_in_sub_b.get_help_heading().map(|s| s.as_str()),
Some("SUB B")
);
let sub_c = cmd.find_subcommand("sub-c").unwrap();
let sub_c_one = sub_c.find_subcommand("sub-c-one").unwrap();
@ -160,7 +188,10 @@ fn app_help_heading_flattened() {
.get_arguments()
.find(|a| a.get_id() == "should_be_in_sub_c")
.unwrap();
assert_eq!(should_be_in_sub_c.get_help_heading(), Some("SUB C"));
assert_eq!(
should_be_in_sub_c.get_help_heading().map(|s| s.as_str()),
Some("SUB C")
);
}
#[test]
@ -184,7 +215,12 @@ fn flatten_field_with_help_heading() {
.get_arguments()
.find(|a| a.get_id() == "should_be_in_section_a")
.unwrap();
assert_eq!(should_be_in_section_a.get_help_heading(), Some("HEADING A"));
assert_eq!(
should_be_in_section_a
.get_help_heading()
.map(|s| s.as_str()),
Some("HEADING A")
);
}
// The challenge with this test is creating an error situation not caught by `clap`'s error checking

View file

@ -2,4 +2,4 @@ error[E0599]: no method named `non_existing_attribute` found for struct `Arg` in
--> tests/derive_ui/non_existent_attr.rs:14:19
|
14 | #[clap(short, non_existing_attribute = 1)]
| ^^^^^^^^^^^^^^^^^^^^^^ method not found in `Arg<'_>`
| ^^^^^^^^^^^^^^^^^^^^^^ method not found in `Arg`

View file

@ -3,8 +3,8 @@ mod arg {
fn name_explicit() {
let arg = clap::arg!(foo: --bar <NUM>);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_long(), Some("bar"));
assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice()));
assert_eq!(arg.get_long().map(|s| s.as_str()), Some("bar"));
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(arg.is_required_set());
}
@ -12,8 +12,8 @@ mod arg {
fn name_from_long() {
let arg = clap::arg!(--bar <NUM>);
assert_eq!(arg.get_id(), "bar");
assert_eq!(arg.get_long(), Some("bar"));
assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice()));
assert_eq!(arg.get_long().map(|s| s.as_str()), Some("bar"));
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(arg.is_required_set());
}
@ -21,8 +21,8 @@ mod arg {
fn name_from_value() {
let arg = clap::arg!(<NUM>);
assert_eq!(arg.get_id(), "NUM");
assert_eq!(arg.get_long(), None);
assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice()));
assert_eq!(arg.get_long().map(|s| s.as_str()), None);
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(arg.is_required_set());
}
@ -46,7 +46,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(foo: -'b');
assert_eq!(arg.get_id(), "foo");
@ -54,7 +54,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(foo: -b ...);
assert_eq!(arg.get_id(), "foo");
@ -62,7 +62,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Count));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(foo: -b "How to use it");
assert_eq!(arg.get_id(), "foo");
@ -70,46 +70,46 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), Some("How to use it"));
assert_eq!(arg.get_help().map(|s| s.as_str()), Some("How to use it"));
}
#[test]
fn short_and_long() {
let arg = clap::arg!(foo: -b --hello);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_long(), Some("hello"));
assert_eq!(arg.get_long().map(|s| s.as_str()), Some("hello"));
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(foo: -'b' --hello);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_long(), Some("hello"));
assert_eq!(arg.get_long().map(|s| s.as_str()), Some("hello"));
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(foo: -b --hello ...);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_long(), Some("hello"));
assert_eq!(arg.get_long().map(|s| s.as_str()), Some("hello"));
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::Count));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(foo: -b --hello "How to use it");
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_long(), Some("hello"));
assert_eq!(arg.get_long().map(|s| s.as_str()), Some("hello"));
assert_eq!(arg.get_short(), Some('b'));
assert!(matches!(arg.get_action(), clap::ArgAction::SetTrue));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), Some("How to use it"));
assert_eq!(arg.get_help().map(|s| s.as_str()), Some("How to use it"));
}
#[test]
@ -186,7 +186,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(foo: -'b' <NUM>);
assert_eq!(arg.get_id(), "foo");
@ -194,7 +194,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(foo: -b <NUM> ...);
assert_eq!(arg.get_id(), "foo");
@ -202,7 +202,7 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Append));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(foo: -b <NUM> "How to use it");
assert_eq!(arg.get_id(), "foo");
@ -210,58 +210,58 @@ mod arg {
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), Some("How to use it"));
assert_eq!(arg.get_help().map(|s| s.as_str()), Some("How to use it"));
}
#[test]
fn positional() {
let arg = clap::arg!(<NUM>);
assert_eq!(arg.get_id(), "NUM");
assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice()));
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!([NUM]);
assert_eq!(arg.get_id(), "NUM");
assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice()));
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(!arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(<NUM>);
assert_eq!(arg.get_id(), "NUM");
assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice()));
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(foo: <NUM>);
assert_eq!(arg.get_id(), "foo");
assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice()));
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(<NUM> ...);
assert_eq!(arg.get_id(), "NUM");
assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice()));
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(matches!(arg.get_action(), clap::ArgAction::Append));
assert_eq!(arg.get_num_args(), Some((1..).into()));
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), None);
assert_eq!(arg.get_help().map(|s| s.as_str()), None);
let arg = clap::arg!(<NUM> "How to use it");
assert_eq!(arg.get_id(), "NUM");
assert_eq!(arg.get_value_names(), Some(vec!["NUM"].as_slice()));
assert_eq!(arg.get_value_names(), Some(vec!["NUM".into()].as_slice()));
assert!(matches!(arg.get_action(), clap::ArgAction::Set));
assert_eq!(arg.get_num_args(), None);
assert!(arg.is_required_set());
assert_eq!(arg.get_help(), Some("How to use it"));
assert_eq!(arg.get_help().map(|s| s.as_str()), Some("How to use it"));
}
#[test]