Skip to content

Commit

Permalink
Merge pull request #5476 from pzmarzly/issue-4265
Browse files Browse the repository at this point in the history
feat(complete): generate completions for visible aliases
  • Loading branch information
epage authored Jun 6, 2024
2 parents f087c39 + 5000d58 commit d87dee6
Show file tree
Hide file tree
Showing 15 changed files with 461 additions and 292 deletions.
7 changes: 7 additions & 0 deletions clap_builder/src/builder/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3441,6 +3441,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
Original file line number Diff line number Diff line change
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()));
}
}

subcmds
Expand Down
35 changes: 22 additions & 13 deletions clap_complete/src/shells/elvish.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 {
debug!("subcommand_details:iter: bin_name={bin_name}");

ret.push(format!(
Expand Down
Loading

0 comments on commit d87dee6

Please sign in to comment.