diff options
Diffstat (limited to 'vendor/clap_complete/src/shells')
-rw-r--r-- | vendor/clap_complete/src/shells/bash.rs | 76 | ||||
-rw-r--r-- | vendor/clap_complete/src/shells/elvish.rs | 16 | ||||
-rw-r--r-- | vendor/clap_complete/src/shells/fish.rs | 29 | ||||
-rw-r--r-- | vendor/clap_complete/src/shells/powershell.rs | 16 | ||||
-rw-r--r-- | vendor/clap_complete/src/shells/shell.rs | 80 | ||||
-rw-r--r-- | vendor/clap_complete/src/shells/zsh.rs | 45 |
6 files changed, 169 insertions, 93 deletions
diff --git a/vendor/clap_complete/src/shells/bash.rs b/vendor/clap_complete/src/shells/bash.rs index 08bf1190c..e110537e5 100644 --- a/vendor/clap_complete/src/shells/bash.rs +++ b/vendor/clap_complete/src/shells/bash.rs @@ -31,8 +31,8 @@ impl Generator for Bash { for i in ${{COMP_WORDS[@]}} do - case \"${{i}}\" in - \"$1\") + case \"${{cmd}},${{i}}\" in + \",$1\") cmd=\"{cmd}\" ;;{subcmds} *) @@ -75,26 +75,52 @@ complete -F _{name} -o bashdefault -o default {name} fn all_subcommands(cmd: &Command) -> String { debug!("all_subcommands"); - let mut subcmds = vec![String::new()]; - let mut scs = utils::all_subcommands(cmd) - .iter() - .map(|x| x.0.clone()) - .collect::<Vec<_>>(); - - scs.sort(); - scs.dedup(); + fn add_command( + parent_fn_name: &str, + cmd: &Command, + subcmds: &mut Vec<(String, String, String)>, + ) { + let fn_name = format!( + "{parent_fn_name}__{cmd_name}", + parent_fn_name = parent_fn_name, + cmd_name = cmd.get_name().to_string().replace('-', "__") + ); + subcmds.push(( + parent_fn_name.to_string(), + cmd.get_name().to_string(), + fn_name.clone(), + )); + for alias in cmd.get_visible_aliases() { + subcmds.push(( + parent_fn_name.to_string(), + alias.to_string(), + fn_name.clone(), + )); + } + for subcmd in cmd.get_subcommands() { + add_command(&fn_name, subcmd, subcmds); + } + } + let mut subcmds = vec![]; + let fn_name = cmd.get_name().replace('-', "__"); + for subcmd in cmd.get_subcommands() { + add_command(&fn_name, subcmd, &mut subcmds); + } + subcmds.sort(); - subcmds.extend(scs.iter().map(|sc| { - format!( - "{name}) - cmd+=\"__{fn_name}\" + let mut cases = vec![String::new()]; + for (parent_fn_name, name, fn_name) in subcmds { + cases.push(format!( + "{parent_fn_name},{name}) + cmd=\"{fn_name}\" ;;", - name = sc, - fn_name = sc.replace('-', "__") - ) - })); + parent_fn_name = parent_fn_name, + name = name, + fn_name = fn_name, + )); + } - subcmds.join("\n ") + cases.join("\n ") } fn subcommand_details(cmd: &Command) -> String { @@ -125,9 +151,9 @@ fn subcommand_details(cmd: &Command) -> String { return 0 ;;", subcmd = sc.replace('-', "__"), - sc_opts = all_options_for_path(cmd, &*sc), + sc_opts = all_options_for_path(cmd, sc), level = sc.split("__").map(|_| 1).sum::<u64>(), - opts_details = option_details_for_path(cmd, &*sc) + opts_details = option_details_for_path(cmd, sc) ) })); @@ -174,12 +200,12 @@ fn option_details_for_path(cmd: &Command, path: &str) -> String { fn vals_for(o: &Arg) -> String { debug!("vals_for: o={}", o.get_id()); - if let Some(vals) = o.get_possible_values() { + if let Some(vals) = crate::generator::utils::possible_values(o) { format!( "$(compgen -W \"{}\" -- \"${{cur}}\")", vals.iter() - .filter(|pv| pv.is_hide_set()) - .map(PossibleValue::get_name) + .filter(|pv| !pv.is_hide_set()) + .map(|n| n.get_name()) .collect::<Vec<_>>() .join(" ") ) @@ -201,7 +227,7 @@ fn all_options_for_path(cmd: &Command, path: &str) -> String { write!(&mut opts, "--{} ", long).unwrap(); } for pos in p.get_positionals() { - if let Some(vals) = pos.get_possible_values() { + if let Some(vals) = utils::possible_values(pos) { for value in vals { write!(&mut opts, "{} ", value.get_name()).unwrap(); } diff --git a/vendor/clap_complete/src/shells/elvish.rs b/vendor/clap_complete/src/shells/elvish.rs index 959372087..07da28348 100644 --- a/vendor/clap_complete/src/shells/elvish.rs +++ b/vendor/clap_complete/src/shells/elvish.rs @@ -1,5 +1,6 @@ use std::io::Write; +use clap::builder::StyledStr; use clap::*; use crate::generator::{utils, Generator}; @@ -19,8 +20,7 @@ impl Generator for Elvish { .get_bin_name() .expect("crate::generate should have set the bin_name"); - let mut names = vec![]; - let subcommands_cases = generate_inner(cmd, "", &mut names); + let subcommands_cases = generate_inner(cmd, ""); let result = format!( r#" @@ -59,18 +59,14 @@ fn escape_string(string: &str) -> String { string.replace('\'', "''") } -fn get_tooltip<T: ToString>(help: Option<&str>, data: T) -> String { +fn get_tooltip<T: ToString>(help: Option<&StyledStr>, data: T) -> String { match help { - Some(help) => escape_string(help), + Some(help) => escape_string(&help.to_string()), _ => data.to_string(), } } -fn generate_inner<'help>( - p: &Command<'help>, - previous_command_name: &str, - names: &mut Vec<&'help str>, -) -> String { +fn generate_inner(p: &Command, previous_command_name: &str) -> String { debug!("generate_inner"); let command_name = if previous_command_name.is_empty() { @@ -134,7 +130,7 @@ fn generate_inner<'help>( ); for subcommand in p.get_subcommands() { - let subcommand_subcommands_cases = generate_inner(subcommand, &command_name, names); + let subcommand_subcommands_cases = generate_inner(subcommand, &command_name); subcommands_cases.push_str(&subcommand_subcommands_cases); } diff --git a/vendor/clap_complete/src/shells/fish.rs b/vendor/clap_complete/src/shells/fish.rs index 9b516084b..fd2f3a4f8 100644 --- a/vendor/clap_complete/src/shells/fish.rs +++ b/vendor/clap_complete/src/shells/fish.rs @@ -27,8 +27,13 @@ impl Generator for Fish { } // Escape string inside single quotes -fn escape_string(string: &str) -> String { - string.replace('\\', "\\\\").replace('\'', "\\'") +fn escape_string(string: &str, escape_comma: bool) -> String { + let string = string.replace('\\', "\\\\").replace('\'', "\\'"); + if escape_comma { + string.replace(',', "\\,") + } else { + string + } } fn gen_fish_inner( @@ -88,12 +93,13 @@ fn gen_fish_inner( if let Some(longs) = option.get_long_and_visible_aliases() { for long in longs { - template.push_str(format!(" -l {}", escape_string(long)).as_str()); + template.push_str(format!(" -l {}", escape_string(long, false)).as_str()); } } if let Some(data) = option.get_help() { - template.push_str(format!(" -d '{}'", escape_string(data)).as_str()); + template + .push_str(format!(" -d '{}'", escape_string(&data.to_string(), false)).as_str()); } template.push_str(value_completion(option).as_str()); @@ -113,12 +119,13 @@ fn gen_fish_inner( if let Some(longs) = flag.get_long_and_visible_aliases() { for long in longs { - template.push_str(format!(" -l {}", escape_string(long)).as_str()); + template.push_str(format!(" -l {}", escape_string(long, false)).as_str()); } } if let Some(data) = flag.get_help() { - template.push_str(format!(" -d '{}'", escape_string(data)).as_str()); + template + .push_str(format!(" -d '{}'", escape_string(&data.to_string(), false)).as_str()); } buffer.push_str(template.as_str()); @@ -132,7 +139,7 @@ fn gen_fish_inner( template.push_str(format!(" -a \"{}\"", &subcommand.get_name()).as_str()); if let Some(data) = subcommand.get_about() { - template.push_str(format!(" -d '{}'", escape_string(data)).as_str()) + template.push_str(format!(" -d '{}'", escape_string(&data.to_string(), false)).as_str()) } buffer.push_str(template.as_str()); @@ -148,11 +155,11 @@ fn gen_fish_inner( } fn value_completion(option: &Arg) -> String { - if !option.is_takes_value_set() { + if !option.get_num_args().expect("built").takes_values() { return "".to_string(); } - if let Some(data) = option.get_possible_values() { + if let Some(data) = crate::generator::utils::possible_values(option) { // We return the possible values with their own empty description e.g. {a\t,b\t} // this makes sure that a and b don't get the description of the option or argument format!( @@ -163,8 +170,8 @@ fn value_completion(option: &Arg) -> String { } else { Some(format!( "{}\t{}", - escape_string(value.get_name()).as_str(), - escape_string(value.get_help().unwrap_or_default()).as_str() + escape_string(value.get_name(), true).as_str(), + escape_string(&value.get_help().unwrap_or_default().to_string(), true) )) }) .collect::<Vec<_>>() diff --git a/vendor/clap_complete/src/shells/powershell.rs b/vendor/clap_complete/src/shells/powershell.rs index d35e61c7d..0d3a2a55f 100644 --- a/vendor/clap_complete/src/shells/powershell.rs +++ b/vendor/clap_complete/src/shells/powershell.rs @@ -1,5 +1,6 @@ use std::io::Write; +use clap::builder::StyledStr; use clap::*; use crate::generator::{utils, Generator}; @@ -19,8 +20,7 @@ impl Generator for PowerShell { .get_bin_name() .expect("crate::generate should have set the bin_name"); - let mut names = vec![]; - let subcommands_cases = generate_inner(cmd, "", &mut names); + let subcommands_cases = generate_inner(cmd, ""); let result = format!( r#" @@ -64,18 +64,14 @@ fn escape_string(string: &str) -> String { string.replace('\'', "''") } -fn get_tooltip<T: ToString>(help: Option<&str>, data: T) -> String { +fn get_tooltip<T: ToString>(help: Option<&StyledStr>, data: T) -> String { match help { - Some(help) => escape_string(help), + Some(help) => escape_string(&help.to_string()), _ => data.to_string(), } } -fn generate_inner<'help>( - p: &Command<'help>, - previous_command_name: &str, - names: &mut Vec<&'help str>, -) -> String { +fn generate_inner(p: &Command, previous_command_name: &str) -> String { debug!("generate_inner"); let command_name = if previous_command_name.is_empty() { @@ -170,7 +166,7 @@ fn generate_inner<'help>( ); for subcommand in p.get_subcommands() { - let subcommand_subcommands_cases = generate_inner(subcommand, &command_name, names); + let subcommand_subcommands_cases = generate_inner(subcommand, &command_name); subcommands_cases.push_str(&subcommand_subcommands_cases); } diff --git a/vendor/clap_complete/src/shells/shell.rs b/vendor/clap_complete/src/shells/shell.rs index 63063bb7c..f6e70f575 100644 --- a/vendor/clap_complete/src/shells/shell.rs +++ b/vendor/clap_complete/src/shells/shell.rs @@ -1,7 +1,9 @@ use std::fmt::Display; +use std::path::Path; use std::str::FromStr; -use clap::{ArgEnum, PossibleValue}; +use clap::builder::PossibleValue; +use clap::ValueEnum; use crate::shells; use crate::Generator; @@ -22,15 +24,6 @@ pub enum Shell { Zsh, } -impl Shell { - /// Report all `possible_values` - pub fn possible_values() -> impl Iterator<Item = PossibleValue<'static>> { - Shell::value_variants() - .iter() - .filter_map(ArgEnum::to_possible_value) - } -} - impl Display for Shell { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.to_possible_value() @@ -54,7 +47,7 @@ impl FromStr for Shell { } // Hand-rolled so it can work even when `derive` feature is disabled -impl ArgEnum for Shell { +impl ValueEnum for Shell { fn value_variants<'a>() -> &'a [Self] { &[ Shell::Bash, @@ -65,7 +58,7 @@ impl ArgEnum for Shell { ] } - fn to_possible_value<'a>(&self) -> Option<PossibleValue<'a>> { + fn to_possible_value<'a>(&self) -> Option<PossibleValue> { Some(match self { Shell::Bash => PossibleValue::new("bash"), Shell::Elvish => PossibleValue::new("elvish"), @@ -97,3 +90,66 @@ impl Generator for Shell { } } } + +impl Shell { + /// Parse a shell from a path to the executable for the shell + /// + /// # Examples + /// + /// ``` + /// use clap_complete::shells::Shell; + /// + /// assert_eq!(Shell::from_shell_path("/bin/bash"), Some(Shell::Bash)); + /// assert_eq!(Shell::from_shell_path("/usr/bin/zsh"), Some(Shell::Zsh)); + /// assert_eq!(Shell::from_shell_path("/opt/my_custom_shell"), None); + /// ``` + pub fn from_shell_path<P: AsRef<Path>>(path: P) -> Option<Shell> { + parse_shell_from_path(path.as_ref()) + } + + /// Determine the user's current shell from the environment + /// + /// This will read the SHELL environment variable and try to determine which shell is in use + /// from that. + /// + /// If SHELL is not set, then on windows, it will default to powershell, and on + /// other OSes it will return `None`. + /// + /// If SHELL is set, but contains a value that doesn't correspond to one of the supported shell + /// types, then return `None`. + /// + /// # Example: + /// + /// ```no_run + /// # use clap::Command; + /// use clap_complete::{generate, shells::Shell}; + /// # fn build_cli() -> Command { + /// # Command::new("compl") + /// # } + /// let mut cmd = build_cli(); + /// generate(Shell::from_env().unwrap_or(Shell::Bash), &mut cmd, "myapp", &mut std::io::stdout()); + /// ``` + pub fn from_env() -> Option<Shell> { + if let Some(env_shell) = std::env::var_os("SHELL") { + Shell::from_shell_path(env_shell) + } else if cfg!(windows) { + Some(Shell::PowerShell) + } else { + None + } + } +} + +// use a separate function to avoid having to monomorphize the entire function due +// to from_shell_path being generic +fn parse_shell_from_path(path: &Path) -> Option<Shell> { + let name = path.file_stem()?.to_str()?; + match name { + "bash" => Some(Shell::Bash), + "zsh" => Some(Shell::Zsh), + "fish" => Some(Shell::Fish), + "elvish" => Some(Shell::Elvish), + "powershell" | "powershell_ise" => Some(Shell::PowerShell), + _ => None, + } +} diff --git a/vendor/clap_complete/src/shells/zsh.rs b/vendor/clap_complete/src/shells/zsh.rs index 2b64739ce..580de77a2 100644 --- a/vendor/clap_complete/src/shells/zsh.rs +++ b/vendor/clap_complete/src/shells/zsh.rs @@ -153,12 +153,10 @@ 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().to_string()) ); - if !text.is_empty() { - ret.push(text); - } + ret.push(text); } // The subcommands @@ -234,7 +232,7 @@ fn get_subcommands_of(parent: &Command) -> String { ); let mut segments = vec![format!("({})", name)]; let subcommand_args = get_args_of( - parser_of(parent, &*bin_name).expect(INTERNAL_ERROR_MSG), + parser_of(parent, bin_name).expect(INTERNAL_ERROR_MSG), Some(parent), ); @@ -243,7 +241,7 @@ fn get_subcommands_of(parent: &Command) -> String { } // Get the help text of all child subcommands. - let children = get_subcommands_of(parser_of(parent, &*bin_name).expect(INTERNAL_ERROR_MSG)); + let children = get_subcommands_of(parser_of(parent, bin_name).expect(INTERNAL_ERROR_MSG)); if !children.is_empty() { segments.push(children); @@ -280,13 +278,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(&String::new()) { + if bin_name == parent.get_bin_name().unwrap_or_default() { return Some(parent); } @@ -359,7 +354,7 @@ fn get_args_of(parent: &Command, p_global: Option<&Command>) -> String { // Uses either `possible_vals` or `value_hint` to give hints about possible argument values fn value_completion(arg: &Arg) -> Option<String> { - if let Some(values) = &arg.get_possible_values() { + if let Some(values) = crate::generator::utils::possible_values(arg) { if values .iter() .any(|value| !value.is_hide_set() && value.get_help().is_some()) @@ -375,7 +370,8 @@ fn value_completion(arg: &Arg) -> Option<String> { Some(format!( r#"{name}\:"{tooltip}""#, name = escape_value(value.get_name()), - tooltip = value.get_help().map(escape_help).unwrap_or_default() + tooltip = + escape_help(&value.get_help().unwrap_or_default().to_string()), )) } }) @@ -388,7 +384,7 @@ fn value_completion(arg: &Arg) -> Option<String> { values .iter() .filter(|pv| !pv.is_hide_set()) - .map(PossibleValue::get_name) + .map(|n| n.get_name()) .collect::<Vec<_>>() .join(" ") )) @@ -448,10 +444,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 = escape_help(&o.get_help().unwrap_or_default().to_string()); let conflicts = arg_conflicts(p, o, p_global); - let multiple = if o.is_multiple_occurrences_set() { + let multiple = if let ArgAction::Count | ArgAction::Append = o.get_action() { "*" } else { "" @@ -465,10 +461,7 @@ fn write_opts_of(p: &Command, p_global: Option<&Command>) -> String { Some(val) => format!(":{}:{}", vn, val), None => format!(":{}: ", vn), }; - let vc = match o.get_num_vals() { - Some(num_vals) => vc.repeat(num_vals), - None => vc, - }; + let vc = vc.repeat(o.get_num_args().expect("built").min_values()); if let Some(shorts) = o.get_short_and_visible_aliases() { for short in shorts { @@ -551,10 +544,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 = escape_help(&f.get_help().unwrap_or_default().to_string()); let conflicts = arg_conflicts(p, &f, p_global); - let multiple = if f.is_multiple_occurrences_set() { + let multiple = if let ArgAction::Count | ArgAction::Append = f.get_action() { "*" } else { "" @@ -632,7 +625,8 @@ fn write_positionals_of(p: &Command) -> String { for arg in p.get_positionals() { debug!("write_positionals_of:iter: arg={}", arg.get_id()); - let cardinality = if arg.is_multiple_values_set() || arg.is_multiple_occurrences_set() { + let num_args = arg.get_num_args().expect("built"); + let cardinality = if num_args.max_values() > 1 { "*:" } else if !arg.is_required_set() { ":" @@ -646,12 +640,13 @@ fn write_positionals_of(p: &Command) -> String { name = arg.get_id(), help = arg .get_help() - .map_or("".to_owned(), |v| " -- ".to_owned() + v) + .map(|s| s.to_string()) + .map_or("".to_owned(), |v| " -- ".to_owned() + &v) .replace('[', "\\[") .replace(']', "\\]") .replace('\'', "'\\''") .replace(':', "\\:"), - value_completion = value_completion(arg).unwrap_or_else(|| "".to_string()) + value_completion = value_completion(arg).unwrap_or_default() ); debug!("write_positionals_of:iter: Wrote...{}", a); |