Skip to content

Commit

Permalink
refactor(complete): stop using generate utils in dynamic
Browse files Browse the repository at this point in the history
  • Loading branch information
ModProg committed Aug 1, 2023
1 parent ca855c6 commit bacc5ce
Showing 1 changed file with 92 additions and 7 deletions.
99 changes: 92 additions & 7 deletions clap_complete/src/dynamic/completer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,91 @@ use std::ffi::OsString;

use clap_lex::OsStrExt as _;

/// Gets all the long options, their visible aliases and flags of a [`clap::Command`].
/// Includes `help` and `version` depending on the [`clap::Command`] settings.
pub fn longs_and_visible_aliases(p: &clap::Command) -> Vec<String> {
debug!("longs: name={}", p.get_name());

p.get_arguments()
.filter_map(|a| {
if !a.is_positional() {
if a.get_visible_aliases().is_some() && a.get_long().is_some() {
let mut visible_aliases: Vec<_> = a
.get_visible_aliases()
.unwrap()
.into_iter()
.map(|s| s.to_string())
.collect();
visible_aliases.push(a.get_long().unwrap().to_string());
Some(visible_aliases)
} else if a.get_visible_aliases().is_none() && a.get_long().is_some() {
Some(vec![a.get_long().unwrap().to_string()])
} else {
None
}
} else {
None
}
})
.flatten()
.collect()
}

/// Gets all the short options, their visible aliases and flags of a [`clap::Command`].
/// Includes `h` and `V` depending on the [`clap::Command`] settings.
pub fn shorts_and_visible_aliases(p: &clap::Command) -> Vec<char> {
debug!("shorts: name={}", p.get_name());

p.get_arguments()
.filter_map(|a| {
if !a.is_positional() {
if a.get_visible_short_aliases().is_some() && a.get_short().is_some() {
let mut shorts_and_visible_aliases = a.get_visible_short_aliases().unwrap();
shorts_and_visible_aliases.push(a.get_short().unwrap());
Some(shorts_and_visible_aliases)
} else if a.get_visible_short_aliases().is_none() && a.get_short().is_some() {
Some(vec![a.get_short().unwrap()])
} else {
None
}
} else {
None
}
})
.flatten()
.collect()
}

/// Get the possible values for completion
pub fn possible_values(a: &clap::Arg) -> Option<Vec<clap::builder::PossibleValue>> {
if !a.get_num_args().expect("built").takes_values() {
None
} else {
a.get_value_parser()
.possible_values()
.map(|pvs| pvs.collect())
}
}

/// Gets subcommands of [`clap::Command`] in the form of `("name", "bin_name")`.
///
/// Subcommand `rustup toolchain install` would be converted to
/// `("install", "rustup toolchain install")`.
pub fn subcommands(p: &clap::Command) -> Vec<String> {
debug!("subcommands: name={}", p.get_name());
debug!("subcommands: Has subcommands...{:?}", p.has_subcommands());

let mut subcmds = vec![];

for sc in p.get_subcommands() {
debug!("subcommands:iter: name={}", sc.get_name(),);

subcmds.push(sc.get_name().to_string());
}

subcmds
}

/// Shell-specific completions
pub trait Completer {
/// The recommended file name for the registration code
Expand Down Expand Up @@ -117,7 +202,7 @@ fn complete_arg(
}
} else {
completions.extend(
crate::generator::utils::longs_and_visible_aliases(cmd)
longs_and_visible_aliases(cmd)
.into_iter()
.filter_map(|f| f.starts_with(flag).then(|| format!("--{f}").into())),
);
Expand All @@ -126,7 +211,7 @@ fn complete_arg(
} else if arg.is_escape() || arg.is_stdio() || arg.is_empty() {
// HACK: Assuming knowledge of is_escape / is_stdio
completions.extend(
crate::generator::utils::longs_and_visible_aliases(cmd)
longs_and_visible_aliases(cmd)
.into_iter()
.map(|f| format!("--{f}").into()),
);
Expand All @@ -140,7 +225,7 @@ fn complete_arg(
};
// HACK: Assuming knowledge of is_stdio
completions.extend(
crate::generator::utils::shorts_and_visible_aliases(cmd)
shorts_and_visible_aliases(cmd)
.into_iter()
// HACK: Need better `OsStr` manipulation
.map(|f| format!("{}{}", dash_or_arg, f).into()),
Expand Down Expand Up @@ -170,7 +255,7 @@ fn complete_arg_value(
let mut values = Vec::new();
debug!("complete_arg_value: arg={arg:?}, value={value:?}");

if let Some(possible_values) = crate::generator::utils::possible_values(arg) {
if let Some(possible_values) = possible_values(arg) {
if let Ok(value) = value {
values.extend(possible_values.into_iter().filter_map(|p| {
let name = p.get_name();
Expand Down Expand Up @@ -275,10 +360,10 @@ fn complete_subcommand(value: &str, cmd: &clap::Command) -> Vec<OsString> {
value
);

let mut scs = crate::generator::utils::subcommands(cmd)
let mut scs = subcommands(cmd)
.into_iter()
.filter(|x| x.0.starts_with(value))
.map(|x| OsString::from(&x.0))
.filter(|x| x.starts_with(value))
.map(OsString::from)
.collect::<Vec<_>>();
scs.sort();
scs.dedup();
Expand Down

0 comments on commit bacc5ce

Please sign in to comment.