Repository: clap-rs/clap (language: rust)

Issue:
Subcommand aliases not included in completion scripts
### Please complete the following tasks

- [X] I have searched the [discussions](https://github.com/clap-rs/clap/discussions)
- [X] I have searched the [open](https://github.com/clap-rs/clap/issues) and [rejected](https://github.com/clap-rs/clap/issues?q=is%3Aissue+label%3AS-wont-fix+is%3Aclosed) issues

### Rust Version

1.63.0

### Clap Version

3.2.22

### Minimal reproducible code

```rust
use std::io::{stdout, Write};
use clap;
use clap::CommandFactory;

#[derive(clap::Parser, Clone, Debug)]
enum App {
    #[clap(alias = "bar")]
    Foo(FooArgs),
}

#[derive(clap::Args, Clone, Debug)]
struct FooArgs {
    my_flag: bool,
}

fn main() {
    let mut app = App::command().disable_help_flag(true).disable_help_subcommand(true);
    let mut buf = vec![];
    clap_complete::generate(clap_complete::Shell::Bash, &mut app, "test", &mut buf);
    stdout().write_all(&mut buf).unwrap();
}
```


### Steps to reproduce the bug with the above code

Run the program to print out a completion script for Bash

### Actual Behaviour

Sourcing the completion script and then running `test <TAB>` will not suggest `bar` and `test bar <TAB>` will not suggest `--my-flag`.

### Expected Behaviour

`test bar <TAB>` should suggest `--my-flag`. I'm not sure if I think `test <TAB>` should suggest both `foo` and `bar`; perhaps the current behavior of not suggesting aliases is best?

The same bug exists in the Fish completion script. I haven't tried others (or checked the code).

I actually noticed the bug because my tool has `jj log` command and a `jj operation/op log` command, and I ran `jj op log <TAB>`, which suggested arguments that are for `jj log`. That's because the `op` (an alias for `operation`) is ignored and completion is run for `jj log` instead.

### Additional Context

_No response_

### Debug Output

_No response_
feat(complete): support command alias completions
<!--
Thanks for helping out!

Please link the appropriate issue from your PR.

If you don't have an issue, we'd recommend starting with one first so the PR can focus on the
implementation (unless its an obvious bug or documentation fix that will have
little conversation).
-->
Fixes #4265 

first time contributor here! this is probably very naive!

this might be a good temporary "hack" while we wait for #3951 and #3166. if that's a problem maybe a feature flag can be introduced, because tools with a lot of very common aliases (like [`jj`](https://github.com/martinvonz/jj)) barely get any completion support right now


Discussion / hints:
`alias` is hidden in `--help` and you need `visible_alias` to show up in `--help`.

We've had some back and forth on whether things that are hidden from help should show up in completions
- https://github.com/clap-rs/clap/issues/2541
- https://github.com/clap-rs/clap/issues/1335

When we resolve https://github.com/clap-rs/clap/issues/3166, my thought is to handle this according to https://github.com/clap-rs/clap/issues/3951
> `alias` is hidden in `--help` and you need `visible_alias` to show up in `--help`.

That makes sense, but it doesn't seem to affect the completion script.

Are you open to a PR to add visible aliases to the completion scripts if I can figure out how?
Yes

Supports visible aliases:
- zsh: https://github.com/clap-rs/clap/blob/master/clap_complete/src/shells/zsh.rs#L170

Doesn't
- bash: https://github.com/clap-rs/clap/blob/master/clap_complete/src/shells/bash.rs#L104
- elvish: https://github.com/clap-rs/clap/blob/master/clap_complete/src/shells/elvish.rs#L122
- fish: https://github.com/clap-rs/clap/blob/master/clap_complete/src/shells/fish.rs#L135
- powershell: https://github.com/clap-rs/clap/blob/master/clap_complete/src/shells/powershell.rs#L151
I've noticed a few other bugs while working on this. Do you prefer that I file separate bugs for those? Looking at past release notes, it doesn't look like you require a bug for each fix, but I don't mind creating them if you prefer.
Separate issues are good in case
- There is discussion around the requirements (I prefer PRs to be focused on the implementation)
- In case not all of them get resolved together

I would at least ask for separate commits for each one.  If a change is likely to have more discussion, having that in a separate PR helps.
> Supports visible aliases:
>    * zsh: https://github.com/clap-rs/clap/blob/master/clap_complete/src/shells/zsh.rs#L170

Although the zsh completion supports listing the aliases for `test <TAB>`, there is currently still the bug with `test bar <TAB>` not suggesting `--my-flag` (or anything else, for that matter).


Fix patch:
diff --git a/clap_builder/src/builder/command.rs b/clap_builder/src/builder/command.rs
index 3674948b4f4..aca4313f24b 100644
--- a/clap_builder/src/builder/command.rs
+++ b/clap_builder/src/builder/command.rs
@@ -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> {
diff --git a/clap_complete/src/generator/utils.rs b/clap_complete/src/generator/utils.rs
index 6ea10d2ab20..a9dd3173b88 100644
--- a/clap_complete/src/generator/utils.rs
+++ b/clap_complete/src/generator/utils.rs
@@ -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
diff --git a/clap_complete/src/shells/elvish.rs b/clap_complete/src/shells/elvish.rs
index 170576ad1a6..eb81e78b1c1 100644
--- a/clap_complete/src/shells/elvish.rs
+++ b/clap_complete/src/shells/elvish.rs
@@ -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();
@@ -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
diff --git a/clap_complete/src/shells/fish.rs b/clap_complete/src/shells/fish.rs
index 1ce27390812..24c44aec3d5 100644
--- a/clap_complete/src/shells/fish.rs
+++ b/clap_complete/src/shells/fish.rs
@@ -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 ")
@@ -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);
+        }
     }
 }
 
diff --git a/clap_complete/src/shells/powershell.rs b/clap_complete/src/shells/powershell.rs
index c5e3c0ba73a..0c84c5fdbfb 100644
--- a/clap_complete/src/shells/powershell.rs
+++ b/clap_complete/src/shells/powershell.rs
@@ -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();
@@ -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
diff --git a/clap_complete/src/shells/zsh.rs b/clap_complete/src/shells/zsh.rs
index 65c26d783cf..f6ca8dd86a9 100644
--- a/clap_complete/src/shells/zsh.rs
+++ b/clap_complete/src/shells/zsh.rs
@@ -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!(


Test patch:
diff --git a/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive b/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive
index 7308976aac8..91a856c744e 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive
@@ -472,155 +472,150 @@ _exhaustive__action_commands() {
     local commands; commands=()
     _describe -t commands 'exhaustive action commands' commands "$@"
 }
-(( $+functions[_exhaustive__help__action_commands] )) ||
-_exhaustive__help__action_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive help action commands' commands "$@"
-}
 (( $+functions[_exhaustive__alias_commands] )) ||
 _exhaustive__alias_commands() {
     local commands; commands=()
     _describe -t commands 'exhaustive alias commands' commands "$@"
 }
+(( $+functions[_exhaustive__complete_commands] )) ||
+_exhaustive__complete_commands() {
+    local commands; commands=()
+    _describe -t commands 'exhaustive complete commands' commands "$@"
+}
+(( $+functions[_exhaustive__help_commands] )) ||
+_exhaustive__help_commands() {
+    local commands; commands=(
+'action:' \
+'quote:' \
+'value:' \
+'pacman:' \
+'last:' \
+'alias:' \
+'hint:' \
+'complete:Register shell completions for this program' \
+'help:Print this message or the help of the given subcommand(s)' \
+    )
+    _describe -t commands 'exhaustive help commands' commands "$@"
+}
+(( $+functions[_exhaustive__help__action_commands] )) ||
+_exhaustive__help__action_commands() {
+    local commands; commands=()
+    _describe -t commands 'exhaustive help action commands' commands "$@"
+}
 (( $+functions[_exhaustive__help__alias_commands] )) ||
 _exhaustive__help__alias_commands() {
     local commands; commands=()
     _describe -t commands 'exhaustive help alias commands' commands "$@"
 }
-(( $+functions[_exhaustive__help__quote__cmd-backslash_commands] )) ||
-_exhaustive__help__quote__cmd-backslash_commands() {
+(( $+functions[_exhaustive__help__complete_commands] )) ||
+_exhaustive__help__complete_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive help quote cmd-backslash commands' commands "$@"
+    _describe -t commands 'exhaustive help complete commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote__cmd-backslash_commands] )) ||
-_exhaustive__quote__cmd-backslash_commands() {
+(( $+functions[_exhaustive__help__help_commands] )) ||
+_exhaustive__help__help_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive quote cmd-backslash commands' commands "$@"
+    _describe -t commands 'exhaustive help help commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote__help__cmd-backslash_commands] )) ||
-_exhaustive__quote__help__cmd-backslash_commands() {
+(( $+functions[_exhaustive__help__hint_commands] )) ||
+_exhaustive__help__hint_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive quote help cmd-backslash commands' commands "$@"
+    _describe -t commands 'exhaustive help hint commands' commands "$@"
 }
-(( $+functions[_exhaustive__help__quote__cmd-backticks_commands] )) ||
-_exhaustive__help__quote__cmd-backticks_commands() {
+(( $+functions[_exhaustive__help__last_commands] )) ||
+_exhaustive__help__last_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive help quote cmd-backticks commands' commands "$@"
+    _describe -t commands 'exhaustive help last commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote__cmd-backticks_commands] )) ||
-_exhaustive__quote__cmd-backticks_commands() {
+(( $+functions[_exhaustive__help__pacman_commands] )) ||
+_exhaustive__help__pacman_commands() {
+    local commands; commands=(
+'one:' \
+'two:' \
+    )
+    _describe -t commands 'exhaustive help pacman commands' commands "$@"
+}
+(( $+functions[_exhaustive__help__pacman__one_commands] )) ||
+_exhaustive__help__pacman__one_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive quote cmd-backticks commands' commands "$@"
+    _describe -t commands 'exhaustive help pacman one commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote__help__cmd-backticks_commands] )) ||
-_exhaustive__quote__help__cmd-backticks_commands() {
+(( $+functions[_exhaustive__help__pacman__two_commands] )) ||
+_exhaustive__help__pacman__two_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive quote help cmd-backticks commands' commands "$@"
+    _describe -t commands 'exhaustive help pacman two commands' commands "$@"
 }
-(( $+functions[_exhaustive__help__quote__cmd-brackets_commands] )) ||
-_exhaustive__help__quote__cmd-brackets_commands() {
+(( $+functions[_exhaustive__help__quote_commands] )) ||
+_exhaustive__help__quote_commands() {
+    local commands; commands=(
+'cmd-single-quotes:Can be '\''always'\'', '\''auto'\'', or '\''never'\''' \
+'cmd-double-quotes:Can be "always", "auto", or "never"' \
+'cmd-backticks:For more information see \`echo test\`' \
+'cmd-backslash:Avoid '\''\\n'\''' \
+'cmd-brackets:List packages \[filter\]' \
+'cmd-expansions:Execute the shell command with \$SHELL' \
+'escape-help:\\tab	"'\'' New Line' \
+    )
+    _describe -t commands 'exhaustive help quote commands' commands "$@"
+}
+(( $+functions[_exhaustive__help__quote__cmd-backslash_commands] )) ||
+_exhaustive__help__quote__cmd-backslash_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive help quote cmd-brackets commands' commands "$@"
+    _describe -t commands 'exhaustive help quote cmd-backslash commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote__cmd-brackets_commands] )) ||
-_exhaustive__quote__cmd-brackets_commands() {
+(( $+functions[_exhaustive__help__quote__cmd-backticks_commands] )) ||
+_exhaustive__help__quote__cmd-backticks_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive quote cmd-brackets commands' commands "$@"
+    _describe -t commands 'exhaustive help quote cmd-backticks commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote__help__cmd-brackets_commands] )) ||
-_exhaustive__quote__help__cmd-brackets_commands() {
+(( $+functions[_exhaustive__help__quote__cmd-brackets_commands] )) ||
+_exhaustive__help__quote__cmd-brackets_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive quote help cmd-brackets commands' commands "$@"
+    _describe -t commands 'exhaustive help quote cmd-brackets commands' commands "$@"
 }
 (( $+functions[_exhaustive__help__quote__cmd-double-quotes_commands] )) ||
 _exhaustive__help__quote__cmd-double-quotes_commands() {
     local commands; commands=()
     _describe -t commands 'exhaustive help quote cmd-double-quotes commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote__cmd-double-quotes_commands] )) ||
-_exhaustive__quote__cmd-double-quotes_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive quote cmd-double-quotes commands' commands "$@"
-}
-(( $+functions[_exhaustive__quote__help__cmd-double-quotes_commands] )) ||
-_exhaustive__quote__help__cmd-double-quotes_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive quote help cmd-double-quotes commands' commands "$@"
-}
 (( $+functions[_exhaustive__help__quote__cmd-expansions_commands] )) ||
 _exhaustive__help__quote__cmd-expansions_commands() {
     local commands; commands=()
     _describe -t commands 'exhaustive help quote cmd-expansions commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote__cmd-expansions_commands] )) ||
-_exhaustive__quote__cmd-expansions_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive quote cmd-expansions commands' commands "$@"
-}
-(( $+functions[_exhaustive__quote__help__cmd-expansions_commands] )) ||
-_exhaustive__quote__help__cmd-expansions_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive quote help cmd-expansions commands' commands "$@"
-}
 (( $+functions[_exhaustive__help__quote__cmd-single-quotes_commands] )) ||
 _exhaustive__help__quote__cmd-single-quotes_commands() {
     local commands; commands=()
     _describe -t commands 'exhaustive help quote cmd-single-quotes commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote__cmd-single-quotes_commands] )) ||
-_exhaustive__quote__cmd-single-quotes_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive quote cmd-single-quotes commands' commands "$@"
-}
-(( $+functions[_exhaustive__quote__help__cmd-single-quotes_commands] )) ||
-_exhaustive__quote__help__cmd-single-quotes_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive quote help cmd-single-quotes commands' commands "$@"
-}
-(( $+functions[_exhaustive__complete_commands] )) ||
-_exhaustive__complete_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive complete commands' commands "$@"
-}
-(( $+functions[_exhaustive__help__complete_commands] )) ||
-_exhaustive__help__complete_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive help complete commands' commands "$@"
-}
 (( $+functions[_exhaustive__help__quote__escape-help_commands] )) ||
 _exhaustive__help__quote__escape-help_commands() {
     local commands; commands=()
     _describe -t commands 'exhaustive help quote escape-help commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote__escape-help_commands] )) ||
-_exhaustive__quote__escape-help_commands() {
+(( $+functions[_exhaustive__help__value_commands] )) ||
+_exhaustive__help__value_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive quote escape-help commands' commands "$@"
+    _describe -t commands 'exhaustive help value commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote__help__escape-help_commands] )) ||
-_exhaustive__quote__help__escape-help_commands() {
+(( $+functions[_exhaustive__hint_commands] )) ||
+_exhaustive__hint_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive quote help escape-help commands' commands "$@"
+    _describe -t commands 'exhaustive hint commands' commands "$@"
 }
-(( $+functions[_exhaustive__help_commands] )) ||
-_exhaustive__help_commands() {
+(( $+functions[_exhaustive__last_commands] )) ||
+_exhaustive__last_commands() {
+    local commands; commands=()
+    _describe -t commands 'exhaustive last commands' commands "$@"
+}
+(( $+functions[_exhaustive__pacman_commands] )) ||
+_exhaustive__pacman_commands() {
     local commands; commands=(
-'action:' \
-'quote:' \
-'value:' \
-'pacman:' \
-'last:' \
-'alias:' \
-'hint:' \
-'complete:Register shell completions for this program' \
+'one:' \
+'two:' \
 'help:Print this message or the help of the given subcommand(s)' \
     )
-    _describe -t commands 'exhaustive help commands' commands "$@"
-}
-(( $+functions[_exhaustive__help__help_commands] )) ||
-_exhaustive__help__help_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive help help commands' commands "$@"
+    _describe -t commands 'exhaustive pacman commands' commands "$@"
 }
 (( $+functions[_exhaustive__pacman__help_commands] )) ||
 _exhaustive__pacman__help_commands() {
@@ -636,8 +631,28 @@ _exhaustive__pacman__help__help_commands() {
     local commands; commands=()
     _describe -t commands 'exhaustive pacman help help commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote__help_commands] )) ||
-_exhaustive__quote__help_commands() {
+(( $+functions[_exhaustive__pacman__help__one_commands] )) ||
+_exhaustive__pacman__help__one_commands() {
+    local commands; commands=()
+    _describe -t commands 'exhaustive pacman help one commands' commands "$@"
+}
+(( $+functions[_exhaustive__pacman__help__two_commands] )) ||
+_exhaustive__pacman__help__two_commands() {
+    local commands; commands=()
+    _describe -t commands 'exhaustive pacman help two commands' commands "$@"
+}
+(( $+functions[_exhaustive__pacman__one_commands] )) ||
+_exhaustive__pacman__one_commands() {
+    local commands; commands=()
+    _describe -t commands 'exhaustive pacman one commands' commands "$@"
+}
+(( $+functions[_exhaustive__pacman__two_commands] )) ||
+_exhaustive__pacman__two_commands() {
+    local commands; commands=()
+    _describe -t commands 'exhaustive pacman two commands' commands "$@"
+}
+(( $+functions[_exhaustive__quote_commands] )) ||
+_exhaustive__quote_commands() {
     local commands; commands=(
 'cmd-single-quotes:Can be '\''always'\'', '\''auto'\'', or '\''never'\''' \
 'cmd-double-quotes:Can be "always", "auto", or "never"' \
@@ -648,80 +663,45 @@ _exhaustive__quote__help_commands() {
 'escape-help:\\tab	"'\'' New Line' \
 'help:Print this message or the help of the given subcommand(s)' \
     )
-    _describe -t commands 'exhaustive quote help commands' commands "$@"
-}
-(( $+functions[_exhaustive__quote__help__help_commands] )) ||
-_exhaustive__quote__help__help_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive quote help help commands' commands "$@"
+    _describe -t commands 'exhaustive quote commands' commands "$@"
 }
-(( $+functions[_exhaustive__help__hint_commands] )) ||
-_exhaustive__help__hint_commands() {
+(( $+functions[_exhaustive__quote__cmd-backslash_commands] )) ||
+_exhaustive__quote__cmd-backslash_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive help hint commands' commands "$@"
+    _describe -t commands 'exhaustive quote cmd-backslash commands' commands "$@"
 }
-(( $+functions[_exhaustive__hint_commands] )) ||
-_exhaustive__hint_commands() {
+(( $+functions[_exhaustive__quote__cmd-backticks_commands] )) ||
+_exhaustive__quote__cmd-backticks_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive hint commands' commands "$@"
+    _describe -t commands 'exhaustive quote cmd-backticks commands' commands "$@"
 }
-(( $+functions[_exhaustive__help__last_commands] )) ||
-_exhaustive__help__last_commands() {
+(( $+functions[_exhaustive__quote__cmd-brackets_commands] )) ||
+_exhaustive__quote__cmd-brackets_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive help last commands' commands "$@"
+    _describe -t commands 'exhaustive quote cmd-brackets commands' commands "$@"
 }
-(( $+functions[_exhaustive__last_commands] )) ||
-_exhaustive__last_commands() {
+(( $+functions[_exhaustive__quote__cmd-double-quotes_commands] )) ||
+_exhaustive__quote__cmd-double-quotes_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive last commands' commands "$@"
+    _describe -t commands 'exhaustive quote cmd-double-quotes commands' commands "$@"
 }
-(( $+functions[_exhaustive__help__pacman__one_commands] )) ||
-_exhaustive__help__pacman__one_commands() {
+(( $+functions[_exhaustive__quote__cmd-expansions_commands] )) ||
+_exhaustive__quote__cmd-expansions_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive help pacman one commands' commands "$@"
+    _describe -t commands 'exhaustive quote cmd-expansions commands' commands "$@"
 }
-(( $+functions[_exhaustive__pacman__help__one_commands] )) ||
-_exhaustive__pacman__help__one_commands() {
+(( $+functions[_exhaustive__quote__cmd-single-quotes_commands] )) ||
+_exhaustive__quote__cmd-single-quotes_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive pacman help one commands' commands "$@"
+    _describe -t commands 'exhaustive quote cmd-single-quotes commands' commands "$@"
 }
-(( $+functions[_exhaustive__pacman__one_commands] )) ||
-_exhaustive__pacman__one_commands() {
+(( $+functions[_exhaustive__quote__escape-help_commands] )) ||
+_exhaustive__quote__escape-help_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive pacman one commands' commands "$@"
-}
-(( $+functions[_exhaustive__help__pacman_commands] )) ||
-_exhaustive__help__pacman_commands() {
-    local commands; commands=(
-'one:' \
-'two:' \
-    )
-    _describe -t commands 'exhaustive help pacman commands' commands "$@"
-}
-(( $+functions[_exhaustive__pacman_commands] )) ||
-_exhaustive__pacman_commands() {
-    local commands; commands=(
-'one:' \
-'two:' \
-'help:Print this message or the help of the given subcommand(s)' \
-    )
-    _describe -t commands 'exhaustive pacman commands' commands "$@"
-}
-(( $+functions[_exhaustive__help__quote_commands] )) ||
-_exhaustive__help__quote_commands() {
-    local commands; commands=(
-'cmd-single-quotes:Can be '\''always'\'', '\''auto'\'', or '\''never'\''' \
-'cmd-double-quotes:Can be "always", "auto", or "never"' \
-'cmd-backticks:For more information see \`echo test\`' \
-'cmd-backslash:Avoid '\''\\n'\''' \
-'cmd-brackets:List packages \[filter\]' \
-'cmd-expansions:Execute the shell command with \$SHELL' \
-'escape-help:\\tab	"'\'' New Line' \
-    )
-    _describe -t commands 'exhaustive help quote commands' commands "$@"
+    _describe -t commands 'exhaustive quote escape-help commands' commands "$@"
 }
-(( $+functions[_exhaustive__quote_commands] )) ||
-_exhaustive__quote_commands() {
+(( $+functions[_exhaustive__quote__help_commands] )) ||
+_exhaustive__quote__help_commands() {
     local commands; commands=(
 'cmd-single-quotes:Can be '\''always'\'', '\''auto'\'', or '\''never'\''' \
 'cmd-double-quotes:Can be "always", "auto", or "never"' \
@@ -732,27 +712,47 @@ _exhaustive__quote_commands() {
 'escape-help:\\tab	"'\'' New Line' \
 'help:Print this message or the help of the given subcommand(s)' \
     )
-    _describe -t commands 'exhaustive quote commands' commands "$@"
+    _describe -t commands 'exhaustive quote help commands' commands "$@"
 }
-(( $+functions[_exhaustive__help__pacman__two_commands] )) ||
-_exhaustive__help__pacman__two_commands() {
+(( $+functions[_exhaustive__quote__help__cmd-backslash_commands] )) ||
+_exhaustive__quote__help__cmd-backslash_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive help pacman two commands' commands "$@"
+    _describe -t commands 'exhaustive quote help cmd-backslash commands' commands "$@"
 }
-(( $+functions[_exhaustive__pacman__help__two_commands] )) ||
-_exhaustive__pacman__help__two_commands() {
+(( $+functions[_exhaustive__quote__help__cmd-backticks_commands] )) ||
+_exhaustive__quote__help__cmd-backticks_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive pacman help two commands' commands "$@"
+    _describe -t commands 'exhaustive quote help cmd-backticks commands' commands "$@"
 }
-(( $+functions[_exhaustive__pacman__two_commands] )) ||
-_exhaustive__pacman__two_commands() {
+(( $+functions[_exhaustive__quote__help__cmd-brackets_commands] )) ||
+_exhaustive__quote__help__cmd-brackets_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive pacman two commands' commands "$@"
+    _describe -t commands 'exhaustive quote help cmd-brackets commands' commands "$@"
 }
-(( $+functions[_exhaustive__help__value_commands] )) ||
-_exhaustive__help__value_commands() {
+(( $+functions[_exhaustive__quote__help__cmd-double-quotes_commands] )) ||
+_exhaustive__quote__help__cmd-double-quotes_commands() {
     local commands; commands=()
-    _describe -t commands 'exhaustive help value commands' commands "$@"
+    _describe -t commands 'exhaustive quote help cmd-double-quotes commands' commands "$@"
+}
+(( $+functions[_exhaustive__quote__help__cmd-expansions_commands] )) ||
+_exhaustive__quote__help__cmd-expansions_commands() {
+    local commands; commands=()
+    _describe -t commands 'exhaustive quote help cmd-expansions commands' commands "$@"
+}
+(( $+functions[_exhaustive__quote__help__cmd-single-quotes_commands] )) ||
+_exhaustive__quote__help__cmd-single-quotes_commands() {
+    local commands; commands=()
+    _describe -t commands 'exhaustive quote help cmd-single-quotes commands' commands "$@"
+}
+(( $+functions[_exhaustive__quote__help__escape-help_commands] )) ||
+_exhaustive__quote__help__escape-help_commands() {
+    local commands; commands=()
+    _describe -t commands 'exhaustive quote help escape-help commands' commands "$@"
+}
+(( $+functions[_exhaustive__quote__help__help_commands] )) ||
+_exhaustive__quote__help__help_commands() {
+    local commands; commands=()
+    _describe -t commands 'exhaustive quote help help commands' commands "$@"
 }
 (( $+functions[_exhaustive__value_commands] )) ||
 _exhaustive__value_commands() {
diff --git a/clap_complete/tests/snapshots/quoting.zsh b/clap_complete/tests/snapshots/quoting.zsh
index 7e36d721b49..3017c4e1780 100644
--- a/clap_complete/tests/snapshots/quoting.zsh
+++ b/clap_complete/tests/snapshots/quoting.zsh
@@ -137,61 +137,31 @@ _my-app__cmd-backslash_commands() {
     local commands; commands=()
     _describe -t commands 'my-app cmd-backslash commands' commands "$@"
 }
-(( $+functions[_my-app__help__cmd-backslash_commands] )) ||
-_my-app__help__cmd-backslash_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app help cmd-backslash commands' commands "$@"
-}
 (( $+functions[_my-app__cmd-backticks_commands] )) ||
 _my-app__cmd-backticks_commands() {
     local commands; commands=()
     _describe -t commands 'my-app cmd-backticks commands' commands "$@"
 }
-(( $+functions[_my-app__help__cmd-backticks_commands] )) ||
-_my-app__help__cmd-backticks_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app help cmd-backticks commands' commands "$@"
-}
 (( $+functions[_my-app__cmd-brackets_commands] )) ||
 _my-app__cmd-brackets_commands() {
     local commands; commands=()
     _describe -t commands 'my-app cmd-brackets commands' commands "$@"
 }
-(( $+functions[_my-app__help__cmd-brackets_commands] )) ||
-_my-app__help__cmd-brackets_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app help cmd-brackets commands' commands "$@"
-}
 (( $+functions[_my-app__cmd-double-quotes_commands] )) ||
 _my-app__cmd-double-quotes_commands() {
     local commands; commands=()
     _describe -t commands 'my-app cmd-double-quotes commands' commands "$@"
 }
-(( $+functions[_my-app__help__cmd-double-quotes_commands] )) ||
-_my-app__help__cmd-double-quotes_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app help cmd-double-quotes commands' commands "$@"
-}
 (( $+functions[_my-app__cmd-expansions_commands] )) ||
 _my-app__cmd-expansions_commands() {
     local commands; commands=()
     _describe -t commands 'my-app cmd-expansions commands' commands "$@"
 }
-(( $+functions[_my-app__help__cmd-expansions_commands] )) ||
-_my-app__help__cmd-expansions_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app help cmd-expansions commands' commands "$@"
-}
 (( $+functions[_my-app__cmd-single-quotes_commands] )) ||
 _my-app__cmd-single-quotes_commands() {
     local commands; commands=()
     _describe -t commands 'my-app cmd-single-quotes commands' commands "$@"
 }
-(( $+functions[_my-app__help__cmd-single-quotes_commands] )) ||
-_my-app__help__cmd-single-quotes_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app help cmd-single-quotes commands' commands "$@"
-}
 (( $+functions[_my-app__help_commands] )) ||
 _my-app__help_commands() {
     local commands; commands=(
@@ -205,6 +175,36 @@ _my-app__help_commands() {
     )
     _describe -t commands 'my-app help commands' commands "$@"
 }
+(( $+functions[_my-app__help__cmd-backslash_commands] )) ||
+_my-app__help__cmd-backslash_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app help cmd-backslash commands' commands "$@"
+}
+(( $+functions[_my-app__help__cmd-backticks_commands] )) ||
+_my-app__help__cmd-backticks_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app help cmd-backticks commands' commands "$@"
+}
+(( $+functions[_my-app__help__cmd-brackets_commands] )) ||
+_my-app__help__cmd-brackets_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app help cmd-brackets commands' commands "$@"
+}
+(( $+functions[_my-app__help__cmd-double-quotes_commands] )) ||
+_my-app__help__cmd-double-quotes_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app help cmd-double-quotes commands' commands "$@"
+}
+(( $+functions[_my-app__help__cmd-expansions_commands] )) ||
+_my-app__help__cmd-expansions_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app help cmd-expansions commands' commands "$@"
+}
+(( $+functions[_my-app__help__cmd-single-quotes_commands] )) ||
+_my-app__help__cmd-single-quotes_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app help cmd-single-quotes commands' commands "$@"
+}
 (( $+functions[_my-app__help__help_commands] )) ||
 _my-app__help__help_commands() {
     local commands; commands=()
diff --git a/clap_complete/tests/snapshots/special_commands.zsh b/clap_complete/tests/snapshots/special_commands.zsh
index 67d04bdae4b..4429003a020 100644
--- a/clap_complete/tests/snapshots/special_commands.zsh
+++ b/clap_complete/tests/snapshots/special_commands.zsh
@@ -142,36 +142,36 @@ _my-app__help__some-cmd-with-hyphens_commands() {
     local commands; commands=()
     _describe -t commands 'my-app help some-cmd-with-hyphens commands' commands "$@"
 }
-(( $+functions[_my-app__some-cmd-with-hyphens_commands] )) ||
-_my-app__some-cmd-with-hyphens_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app some-cmd-with-hyphens commands' commands "$@"
-}
 (( $+functions[_my-app__help__some-hidden-cmd_commands] )) ||
 _my-app__help__some-hidden-cmd_commands() {
     local commands; commands=()
     _describe -t commands 'my-app help some-hidden-cmd commands' commands "$@"
 }
-(( $+functions[_my-app__some-hidden-cmd_commands] )) ||
-_my-app__some-hidden-cmd_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app some-hidden-cmd commands' commands "$@"
-}
 (( $+functions[_my-app__help__some_cmd_commands] )) ||
 _my-app__help__some_cmd_commands() {
     local commands; commands=()
     _describe -t commands 'my-app help some_cmd commands' commands "$@"
 }
-(( $+functions[_my-app__some_cmd_commands] )) ||
-_my-app__some_cmd_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app some_cmd commands' commands "$@"
-}
 (( $+functions[_my-app__help__test_commands] )) ||
 _my-app__help__test_commands() {
     local commands; commands=()
     _describe -t commands 'my-app help test commands' commands "$@"
 }
+(( $+functions[_my-app__some-cmd-with-hyphens_commands] )) ||
+_my-app__some-cmd-with-hyphens_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app some-cmd-with-hyphens commands' commands "$@"
+}
+(( $+functions[_my-app__some-hidden-cmd_commands] )) ||
+_my-app__some-hidden-cmd_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app some-hidden-cmd commands' commands "$@"
+}
+(( $+functions[_my-app__some_cmd_commands] )) ||
+_my-app__some_cmd_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app some_cmd commands' commands "$@"
+}
 (( $+functions[_my-app__test_commands] )) ||
 _my-app__test_commands() {
     local commands; commands=()
diff --git a/clap_complete/tests/snapshots/sub_subcommands.bash b/clap_complete/tests/snapshots/sub_subcommands.bash
index ef1925b6f94..a6a4663503d 100644
--- a/clap_complete/tests/snapshots/sub_subcommands.bash
+++ b/clap_complete/tests/snapshots/sub_subcommands.bash
@@ -55,7 +55,7 @@ _my-app() {
 
     case "${cmd}" in
         my__app)
-            opts="-C -c -h -V --conf --config --help --version [file] first second test some_cmd help"
+            opts="-C -c -h -V --conf --config --help --version [file] first second test some_cmd some_cmd_alias help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -152,6 +152,20 @@ _my-app() {
             COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
             return 0
             ;;
+        my__app__some_cmd)
+            opts="-h -V --help --version sub_cmd help"
+            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+                return 0
+            fi
+            case "${prev}" in
+                *)
+                    COMPREPLY=()
+                    ;;
+            esac
+            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+            return 0
+            ;;
         my__app__some_cmd__help)
             opts="sub_cmd help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
diff --git a/clap_complete/tests/snapshots/sub_subcommands.elvish b/clap_complete/tests/snapshots/sub_subcommands.elvish
index d42e344c495..68b72f66f20 100644
--- a/clap_complete/tests/snapshots/sub_subcommands.elvish
+++ b/clap_complete/tests/snapshots/sub_subcommands.elvish
@@ -28,6 +28,7 @@ set edit:completion:arg-completer[my-app] = {|@words|
             cand --version 'Print version'
             cand test 'tests things'
             cand some_cmd 'top level subcommand'
+            cand some_cmd_alias 'top level subcommand'
             cand help 'Print this message or the help of the given subcommand(s)'
         }
         &'my-app;test'= {
@@ -45,6 +46,14 @@ set edit:completion:arg-completer[my-app] = {|@words|
             cand sub_cmd 'sub-subcommand'
             cand help 'Print this message or the help of the given subcommand(s)'
         }
+        &'my-app;some_cmd_alias'= {
+            cand -h 'Print help'
+            cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
+            cand sub_cmd 'sub-subcommand'
+            cand help 'Print this message or the help of the given subcommand(s)'
+        }
         &'my-app;some_cmd;sub_cmd'= {
             cand --config 'the other case to test'
             cand -h 'Print help (see more with ''--help'')'
@@ -52,6 +61,13 @@ set edit:completion:arg-completer[my-app] = {|@words|
             cand -V 'Print version'
             cand --version 'Print version'
         }
+        &'my-app;some_cmd_alias;sub_cmd'= {
+            cand --config 'the other case to test'
+            cand -h 'Print help (see more with ''--help'')'
+            cand --help 'Print help (see more with ''--help'')'
+            cand -V 'Print version'
+            cand --version 'Print version'
+        }
         &'my-app;some_cmd;help'= {
             cand sub_cmd 'sub-subcommand'
             cand help 'Print this message or the help of the given subcommand(s)'
@@ -60,6 +76,14 @@ set edit:completion:arg-completer[my-app] = {|@words|
         }
         &'my-app;some_cmd;help;help'= {
         }
+        &'my-app;some_cmd_alias;help'= {
+            cand sub_cmd 'sub-subcommand'
+            cand help 'Print this message or the help of the given subcommand(s)'
+        }
+        &'my-app;some_cmd_alias;help;sub_cmd'= {
+        }
+        &'my-app;some_cmd_alias;help;help'= {
+        }
         &'my-app;help'= {
             cand test 'tests things'
             cand some_cmd 'top level subcommand'
diff --git a/clap_complete/tests/snapshots/sub_subcommands.fish b/clap_complete/tests/snapshots/sub_subcommands.fish
index cec51a63a1f..644e37ad494 100644
--- a/clap_complete/tests/snapshots/sub_subcommands.fish
+++ b/clap_complete/tests/snapshots/sub_subcommands.fish
@@ -3,6 +3,7 @@ complete -c my-app -n "__fish_use_subcommand" -s h -l help -d 'Print help'
 complete -c my-app -n "__fish_use_subcommand" -s V -l version -d 'Print version'
 complete -c my-app -n "__fish_use_subcommand" -f -a "test" -d 'tests things'
 complete -c my-app -n "__fish_use_subcommand" -f -a "some_cmd" -d 'top level subcommand'
+complete -c my-app -n "__fish_use_subcommand" -f -a "some_cmd_alias" -d 'top level subcommand'
 complete -c my-app -n "__fish_use_subcommand" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
 complete -c my-app -n "__fish_seen_subcommand_from test" -l case -d 'the case to test' -r
 complete -c my-app -n "__fish_seen_subcommand_from test" -s h -l help -d 'Print help'
@@ -16,6 +17,15 @@ complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_sub
 complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -s V -l version -d 'Print version'
 complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "sub_cmd" -d 'sub-subcommand'
 complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
+complete -c my-app -n "__fish_seen_subcommand_from some_cmd_alias; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -s h -l help -d 'Print help'
+complete -c my-app -n "__fish_seen_subcommand_from some_cmd_alias; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -s V -l version -d 'Print version'
+complete -c my-app -n "__fish_seen_subcommand_from some_cmd_alias; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "sub_cmd" -d 'sub-subcommand'
+complete -c my-app -n "__fish_seen_subcommand_from some_cmd_alias; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
+complete -c my-app -n "__fish_seen_subcommand_from some_cmd_alias; and __fish_seen_subcommand_from sub_cmd" -l config -d 'the other case to test' -r -f -a "{Lest quotes\, aren\'t escaped.	'help,with,comma',Second to trigger display of options	''}"
+complete -c my-app -n "__fish_seen_subcommand_from some_cmd_alias; and __fish_seen_subcommand_from sub_cmd" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c my-app -n "__fish_seen_subcommand_from some_cmd_alias; and __fish_seen_subcommand_from sub_cmd" -s V -l version -d 'Print version'
+complete -c my-app -n "__fish_seen_subcommand_from some_cmd_alias; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "sub_cmd" -d 'sub-subcommand'
+complete -c my-app -n "__fish_seen_subcommand_from some_cmd_alias; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
 complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from help" -f -a "test" -d 'tests things'
 complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from help" -f -a "some_cmd" -d 'top level subcommand'
 complete -c my-app -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from test; and not __fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
diff --git a/clap_complete/tests/snapshots/sub_subcommands.ps1 b/clap_complete/tests/snapshots/sub_subcommands.ps1
index 3880c2442ae..1cdaf0627c3 100644
--- a/clap_complete/tests/snapshots/sub_subcommands.ps1
+++ b/clap_complete/tests/snapshots/sub_subcommands.ps1
@@ -31,6 +31,7 @@ Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock {
             [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
             [CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'tests things')
             [CompletionResult]::new('some_cmd', 'some_cmd', [CompletionResultType]::ParameterValue, 'top level subcommand')
+            [CompletionResult]::new('some_cmd_alias', 'some_cmd_alias', [CompletionResultType]::ParameterValue, 'top level subcommand')
             [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
             break
         }
@@ -51,6 +52,15 @@ Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock {
             [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
             break
         }
+        'my-app;some_cmd_alias' {
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('sub_cmd', 'sub_cmd', [CompletionResultType]::ParameterValue, 'sub-subcommand')
+            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
+            break
+        }
         'my-app;some_cmd;sub_cmd' {
             [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'the other case to test')
             [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
@@ -59,6 +69,14 @@ Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock {
             [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
             break
         }
+        'my-app;some_cmd_alias;sub_cmd' {
+            [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'the other case to test')
+            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
+            [CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
+            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
+            break
+        }
         'my-app;some_cmd;help' {
             [CompletionResult]::new('sub_cmd', 'sub_cmd', [CompletionResultType]::ParameterValue, 'sub-subcommand')
             [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
@@ -70,6 +88,17 @@ Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock {
         'my-app;some_cmd;help;help' {
             break
         }
+        'my-app;some_cmd_alias;help' {
+            [CompletionResult]::new('sub_cmd', 'sub_cmd', [CompletionResultType]::ParameterValue, 'sub-subcommand')
+            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
+            break
+        }
+        'my-app;some_cmd_alias;help;sub_cmd' {
+            break
+        }
+        'my-app;some_cmd_alias;help;help' {
+            break
+        }
         'my-app;help' {
             [CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'tests things')
             [CompletionResult]::new('some_cmd', 'some_cmd', [CompletionResultType]::ParameterValue, 'top level subcommand')
diff --git a/clap_complete/tests/snapshots/sub_subcommands.zsh b/clap_complete/tests/snapshots/sub_subcommands.zsh
index 720e72f1278..a931fefd619 100644
--- a/clap_complete/tests/snapshots/sub_subcommands.zsh
+++ b/clap_complete/tests/snapshots/sub_subcommands.zsh
@@ -97,6 +97,60 @@ esac
     ;;
 esac
 ;;
+(some_cmd_alias)
+_arguments "${_arguments_options[@]}" \
+'-h[Print help]' \
+'--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
+":: :_my-app__some_cmd_commands" \
+"*::: :->some_cmd" \
+&& ret=0
+
+    case $state in
+    (some_cmd)
+        words=($line[1] "${words[@]}")
+        (( CURRENT += 1 ))
+        curcontext="${curcontext%:*:*}:my-app-some_cmd-command-$line[1]:"
+        case $line[1] in
+            (sub_cmd)
+_arguments "${_arguments_options[@]}" \
+'--config=[the other case to test]: :((Lest\ quotes,\ aren'\''t\ escaped.\:"help,with,comma"
+Second\ to\ trigger\ display\ of\ options\:""))' \
+'-h[Print help (see more with '\''--help'\'')]' \
+'--help[Print help (see more with '\''--help'\'')]' \
+'-V[Print version]' \
+'--version[Print version]' \
+&& ret=0
+;;
+(help)
+_arguments "${_arguments_options[@]}" \
+":: :_my-app__some_cmd__help_commands" \
+"*::: :->help" \
+&& ret=0
+
+    case $state in
+    (help)
+        words=($line[1] "${words[@]}")
+        (( CURRENT += 1 ))
+        curcontext="${curcontext%:*:*}:my-app-some_cmd-help-command-$line[1]:"
+        case $line[1] in
+            (sub_cmd)
+_arguments "${_arguments_options[@]}" \
+&& ret=0
+;;
+(help)
+_arguments "${_arguments_options[@]}" \
+&& ret=0
+;;
+        esac
+    ;;
+esac
+;;
+        esac
+    ;;
+esac
+;;
 (help)
 _arguments "${_arguments_options[@]}" \
 ":: :_my-app__help_commands" \
@@ -170,19 +224,6 @@ _my-app__help__help_commands() {
     local commands; commands=()
     _describe -t commands 'my-app help help commands' commands "$@"
 }
-(( $+functions[_my-app__some_cmd__help_commands] )) ||
-_my-app__some_cmd__help_commands() {
-    local commands; commands=(
-'sub_cmd:sub-subcommand' \
-'help:Print this message or the help of the given subcommand(s)' \
-    )
-    _describe -t commands 'my-app some_cmd help commands' commands "$@"
-}
-(( $+functions[_my-app__some_cmd__help__help_commands] )) ||
-_my-app__some_cmd__help__help_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app some_cmd help help commands' commands "$@"
-}
 (( $+functions[_my-app__help__some_cmd_commands] )) ||
 _my-app__help__some_cmd_commands() {
     local commands; commands=(
@@ -190,6 +231,16 @@ _my-app__help__some_cmd_commands() {
     )
     _describe -t commands 'my-app help some_cmd commands' commands "$@"
 }
+(( $+functions[_my-app__help__some_cmd__sub_cmd_commands] )) ||
+_my-app__help__some_cmd__sub_cmd_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app help some_cmd sub_cmd commands' commands "$@"
+}
+(( $+functions[_my-app__help__test_commands] )) ||
+_my-app__help__test_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app help test commands' commands "$@"
+}
 (( $+functions[_my-app__some_cmd_commands] )) ||
 _my-app__some_cmd_commands() {
     local commands; commands=(
@@ -198,10 +249,18 @@ _my-app__some_cmd_commands() {
     )
     _describe -t commands 'my-app some_cmd commands' commands "$@"
 }
-(( $+functions[_my-app__help__some_cmd__sub_cmd_commands] )) ||
-_my-app__help__some_cmd__sub_cmd_commands() {
+(( $+functions[_my-app__some_cmd__help_commands] )) ||
+_my-app__some_cmd__help_commands() {
+    local commands; commands=(
+'sub_cmd:sub-subcommand' \
+'help:Print this message or the help of the given subcommand(s)' \
+    )
+    _describe -t commands 'my-app some_cmd help commands' commands "$@"
+}
+(( $+functions[_my-app__some_cmd__help__help_commands] )) ||
+_my-app__some_cmd__help__help_commands() {
     local commands; commands=()
-    _describe -t commands 'my-app help some_cmd sub_cmd commands' commands "$@"
+    _describe -t commands 'my-app some_cmd help help commands' commands "$@"
 }
 (( $+functions[_my-app__some_cmd__help__sub_cmd_commands] )) ||
 _my-app__some_cmd__help__sub_cmd_commands() {
@@ -213,11 +272,6 @@ _my-app__some_cmd__sub_cmd_commands() {
     local commands; commands=()
     _describe -t commands 'my-app some_cmd sub_cmd commands' commands "$@"
 }
-(( $+functions[_my-app__help__test_commands] )) ||
-_my-app__help__test_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app help test commands' commands "$@"
-}
 (( $+functions[_my-app__test_commands] )) ||
 _my-app__test_commands() {
     local commands; commands=()
diff --git a/clap_complete/tests/snapshots/subcommand_last.zsh b/clap_complete/tests/snapshots/subcommand_last.zsh
index 1dc63fe5eef..81f1572b055 100644
--- a/clap_complete/tests/snapshots/subcommand_last.zsh
+++ b/clap_complete/tests/snapshots/subcommand_last.zsh
@@ -86,21 +86,11 @@ _my-app__bar_commands() {
     local commands; commands=()
     _describe -t commands 'my-app bar commands' commands "$@"
 }
-(( $+functions[_my-app__help__bar_commands] )) ||
-_my-app__help__bar_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app help bar commands' commands "$@"
-}
 (( $+functions[_my-app__foo_commands] )) ||
 _my-app__foo_commands() {
     local commands; commands=()
     _describe -t commands 'my-app foo commands' commands "$@"
 }
-(( $+functions[_my-app__help__foo_commands] )) ||
-_my-app__help__foo_commands() {
-    local commands; commands=()
-    _describe -t commands 'my-app help foo commands' commands "$@"
-}
 (( $+functions[_my-app__help_commands] )) ||
 _my-app__help_commands() {
     local commands; commands=(
@@ -110,6 +100,16 @@ _my-app__help_commands() {
     )
     _describe -t commands 'my-app help commands' commands "$@"
 }
+(( $+functions[_my-app__help__bar_commands] )) ||
+_my-app__help__bar_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app help bar commands' commands "$@"
+}
+(( $+functions[_my-app__help__foo_commands] )) ||
+_my-app__help__foo_commands() {
+    local commands; commands=()
+    _describe -t commands 'my-app help foo commands' commands "$@"
+}
 (( $+functions[_my-app__help__help_commands] )) ||
 _my-app__help__help_commands() {
     local commands; commands=()