refactor(parser): Track subcommands with Box<str>

The overall hope is to allow a `&'static str`-only version of clap, so
we need to move off of `Str` where dynamic strings are required.  We
need it here for subcommands due to external subcommands.

This had minimal impact on code size (567.2 to 567.5 KiB)
This commit is contained in:
Ed Page 2022-09-16 14:01:50 -05:00
parent 1365b08849
commit 1e13109a26
4 changed files with 9 additions and 8 deletions

View file

@ -491,7 +491,7 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream {
};
quote! {
if #subcommand_name_var == #sub_name && !#sub_arg_matches_var.contains_id("") {
if #subcommand_name_var.as_ref() == #sub_name && !#sub_arg_matches_var.contains_id("") {
return ::std::result::Result::Ok(Self :: #variant_name #constructor_block)
}
}
@ -522,7 +522,7 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream {
let wildcard = match ext_subcmd {
Some((span, var_name, str_ty)) => quote_spanned! { span=>
::std::result::Result::Ok(Self::#var_name(
::std::iter::once(#str_ty::from(#subcommand_name_var))
::std::iter::once(#str_ty::from(#subcommand_name_var.as_ref()))
.chain(
#sub_arg_matches_var
.remove_many::<#str_ty>("")

View file

@ -3167,6 +3167,7 @@ impl Command {
}
#[inline]
#[cfg(debug_assertions)]
pub(crate) fn get_name_str(&self) -> &Str {
&self.name
}

View file

@ -6,6 +6,7 @@ use std::iter::{Cloned, Flatten, Map};
use std::slice::Iter;
// Internal
#[cfg(debug_assertions)]
use crate::builder::Str;
use crate::parser::AnyValue;
use crate::parser::AnyValueId;
@ -839,7 +840,7 @@ impl ArgMatches {
/// }
/// ```
/// [subcommand]: crate::Command::subcommand
pub fn remove_subcommand(&mut self) -> Option<(Str, ArgMatches)> {
pub fn remove_subcommand(&mut self) -> Option<(Box<str>, ArgMatches)> {
self.subcommand.take().map(|sc| (sc.name, sc.matches))
}
@ -1138,7 +1139,7 @@ impl ArgMatches {
}
if let Some(ref sc) = self.subcommand {
if sc.name == name {
if sc.name.as_ref() == name {
return Some(sc);
}
}
@ -1149,7 +1150,7 @@ impl ArgMatches {
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct SubCommand {
pub(crate) name: Str,
pub(crate) name: Box<str>,
pub(crate) matches: ArgMatches,
}

View file

@ -9,7 +9,6 @@ use clap_lex::RawOsStr;
use clap_lex::RawOsString;
// Internal
use crate::builder::Str;
use crate::builder::{Arg, Command};
use crate::error::Error as ClapError;
use crate::error::Result as ClapResult;
@ -418,7 +417,7 @@ impl<'cmd> Parser<'cmd> {
{
// Get external subcommand name
let sc_name = match arg_os.to_value() {
Ok(s) => Str::from(s.to_owned()),
Ok(s) => Box::from(s),
Err(_) => {
let _ = self.resolve_pending(matcher);
return Err(ClapError::invalid_utf8(
@ -702,7 +701,7 @@ impl<'cmd> Parser<'cmd> {
}
}
matcher.subcommand(SubCommand {
name: sc.get_name_str().clone(),
name: Box::from(sc.get_name()),
matches: sc_matcher.into_inner(),
});
}