Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(complete): generate completions for visible aliases #5476

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions clap_builder/src/builder/command.rs
Expand Up @@ -3438,6 +3438,13 @@ impl Command {
&self.name
}

/// Get all known names of the cmd (i.e. primary name and visible aliases).
pub fn get_name_and_visible_aliases(&self) -> Vec<&str> {
let mut names = vec![self.name.as_str()];
names.extend(self.get_visible_aliases());
names
}

/// Get the version of the cmd.
#[inline]
pub fn get_version(&self) -> Option<&str> {
Expand Down
9 changes: 8 additions & 1 deletion clap_complete/src/generator/utils.rs
Expand Up @@ -47,8 +47,15 @@ pub fn subcommands(p: &Command) -> Vec<(String, String)> {
sc.get_name(),
sc_bin_name
);

subcmds.push((sc.get_name().to_string(), sc_bin_name.to_string()));

for alias in sc.get_visible_aliases() {
debug!(
"subcommands:iter: alias={}, bin_name={}",
alias, sc_bin_name
);
subcmds.push((alias.to_string(), sc_bin_name.to_string()));
pzmarzly marked this conversation as resolved.
Show resolved Hide resolved
}
}

subcmds
Expand Down
35 changes: 22 additions & 13 deletions clap_complete/src/shells/elvish.rs
Expand Up @@ -67,10 +67,13 @@ fn escape_help<T: ToString>(help: Option<&StyledStr>, data: T) -> String {
fn generate_inner(p: &Command, previous_command_name: &str) -> String {
debug!("generate_inner");

let command_name = if previous_command_name.is_empty() {
p.get_bin_name().expect(INTERNAL_ERROR_MSG).to_string()
let command_names = if previous_command_name.is_empty() {
vec![p.get_bin_name().expect(INTERNAL_ERROR_MSG).to_string()]
} else {
format!("{};{}", previous_command_name, &p.get_name())
p.get_name_and_visible_aliases()
.into_iter()
.map(|name| format!("{};{}", previous_command_name, name))
.collect()
};

let mut completions = String::new();
Expand Down Expand Up @@ -113,23 +116,29 @@ fn generate_inner(p: &Command, previous_command_name: &str) -> String {
}

for subcommand in p.get_subcommands() {
let data = &subcommand.get_name();
let tooltip = escape_help(subcommand.get_about(), data);
for name in subcommand.get_name_and_visible_aliases() {
let tooltip = escape_help(subcommand.get_about(), name);

completions.push_str(&preamble);
completions.push_str(format!("{data} '{tooltip}'").as_str());
completions.push_str(&preamble);
completions.push_str(format!("{name} '{tooltip}'").as_str());
}
}

let mut subcommands_cases = format!(
r"
let mut subcommands_cases = String::new();
for command_name in &command_names {
subcommands_cases.push_str(&format!(
r"
&'{}'= {{{}
}}",
&command_name, completions
);
&command_name, completions
));
}

for subcommand in p.get_subcommands() {
let subcommand_subcommands_cases = generate_inner(subcommand, &command_name);
subcommands_cases.push_str(&subcommand_subcommands_cases);
for command_name in &command_names {
let subcommand_subcommands_cases = generate_inner(subcommand, command_name);
subcommands_cases.push_str(&subcommand_subcommands_cases);
}
}

subcommands_cases
Expand Down
29 changes: 17 additions & 12 deletions clap_complete/src/shells/fish.rs
Expand Up @@ -75,7 +75,8 @@ fn gen_fish_inner(
.map(|command| format!("__fish_seen_subcommand_from {command}"))
.chain(
cmd.get_subcommands()
.map(|command| format!("not __fish_seen_subcommand_from {command}"))
.flat_map(Command::get_name_and_visible_aliases)
.map(|name| format!("not __fish_seen_subcommand_from {name}"))
)
.collect::<Vec<_>>()
.join("; and ")
Expand Down Expand Up @@ -135,24 +136,28 @@ fn gen_fish_inner(
}

for subcommand in cmd.get_subcommands() {
let mut template = basic_template.clone();
for subcommand_name in subcommand.get_name_and_visible_aliases() {
let mut template = basic_template.clone();

template.push_str(" -f");
template.push_str(format!(" -a \"{}\"", &subcommand.get_name()).as_str());
template.push_str(" -f");
template.push_str(format!(" -a \"{}\"", subcommand_name).as_str());

if let Some(data) = subcommand.get_about() {
template.push_str(format!(" -d '{}'", escape_help(data)).as_str());
}
if let Some(data) = subcommand.get_about() {
template.push_str(format!(" -d '{}'", escape_help(data)).as_str());
}

buffer.push_str(template.as_str());
buffer.push('\n');
buffer.push_str(template.as_str());
buffer.push('\n');
}
}

// generate options of subcommands
for subcommand in cmd.get_subcommands() {
let mut parent_commands: Vec<_> = parent_commands.into();
parent_commands.push(subcommand.get_name());
gen_fish_inner(root_command, &parent_commands, subcommand, buffer);
for subcommand_name in subcommand.get_name_and_visible_aliases() {
let mut parent_commands: Vec<_> = parent_commands.into();
parent_commands.push(subcommand_name);
gen_fish_inner(root_command, &parent_commands, subcommand, buffer);
}
}
}

Expand Down
41 changes: 24 additions & 17 deletions clap_complete/src/shells/powershell.rs
Expand Up @@ -72,10 +72,13 @@ fn escape_help<T: ToString>(help: Option<&StyledStr>, data: T) -> String {
fn generate_inner(p: &Command, previous_command_name: &str) -> String {
debug!("generate_inner");

let command_name = if previous_command_name.is_empty() {
p.get_bin_name().expect(INTERNAL_ERROR_MSG).to_string()
let command_names = if previous_command_name.is_empty() {
vec![p.get_bin_name().expect(INTERNAL_ERROR_MSG).to_string()]
} else {
format!("{};{}", previous_command_name, &p.get_name())
p.get_name_and_visible_aliases()
.into_iter()
.map(|name| format!("{};{}", previous_command_name, name))
.collect()
};

let mut completions = String::new();
Expand All @@ -90,27 +93,31 @@ fn generate_inner(p: &Command, previous_command_name: &str) -> String {
}

for subcommand in p.get_subcommands() {
let data = &subcommand.get_name();
let tooltip = escape_help(subcommand.get_about(), data);

completions.push_str(&preamble);
completions.push_str(
format!("'{data}', '{data}', [CompletionResultType]::ParameterValue, '{tooltip}')")
.as_str(),
);
for name in subcommand.get_name_and_visible_aliases() {
let tooltip = escape_help(subcommand.get_about(), name);
completions.push_str(&preamble);
completions.push_str(&format!(
"'{name}', '{name}', [CompletionResultType]::ParameterValue, '{tooltip}')"
));
}
}

let mut subcommands_cases = format!(
r"
let mut subcommands_cases = String::new();
for command_name in &command_names {
subcommands_cases.push_str(&format!(
r"
'{}' {{{}
break
}}",
&command_name, completions
);
command_name, completions
));
}

for subcommand in p.get_subcommands() {
let subcommand_subcommands_cases = generate_inner(subcommand, &command_name);
subcommands_cases.push_str(&subcommand_subcommands_cases);
for command_name in &command_names {
let subcommand_subcommands_cases = generate_inner(subcommand, command_name);
subcommands_cases.push_str(&subcommand_subcommands_cases);
}
}

subcommands_cases
Expand Down
11 changes: 7 additions & 4 deletions clap_complete/src/shells/zsh.rs
Expand Up @@ -110,12 +110,15 @@ _{bin_name_underscore}_commands() {{
ret.push(parent_text);

// Next we start looping through all the children, grandchildren, etc.
let mut all_subcommands = utils::all_subcommands(p);
let mut all_subcommand_bins: Vec<_> = utils::all_subcommands(p)
.into_iter()
.map(|(_sc_name, bin_name)| bin_name)
.collect();

all_subcommands.sort();
all_subcommands.dedup();
all_subcommand_bins.sort();
all_subcommand_bins.dedup();

for (_, ref bin_name) in &all_subcommands {
for bin_name in &all_subcommand_bins {
pzmarzly marked this conversation as resolved.
Show resolved Hide resolved
debug!("subcommand_details:iter: bin_name={bin_name}");

ret.push(format!(
Expand Down