Repository: clap-rs/clap
Pull request #5854 (2024-12-22 22:25:39)

feat(mangen): Separate options based on `help_heading`
An implementation for #3363

Could also make this a flag on `Man`.

0xAdk: The extra headers are added after the "OPTIONS" heading as their own headings, I could've also used `.SS` like ripgrep does for it's option categories
![image](https://github.com/user-attachments/assets/6545d8f4-4ab5-401a-8029-d2ef85dea888)
 though imo it looked a little odd
epage: Thanks for putting this together!  I don't use man pages enough to say whether to do your approach or ripgreps but we can just go for one now and see what feedback we get.

Patch:
diff --git a/clap_complete/examples/exhaustive.rs b/clap_complete/examples/exhaustive.rs
index 1cc3be28..2c00a2c7 100644
--- a/clap_complete/examples/exhaustive.rs
+++ b/clap_complete/examples/exhaustive.rs
@@ -23,37 +23,24 @@ fn print_completions<G: Generator>(gen: G, cmd: &mut clap::Command) {
     generate(gen, cmd, cmd.get_name().to_string(), &mut std::io::stdout());
 }
 
-const EMPTY: [&str; 0] = [];
-
 #[allow(clippy::let_and_return)]
 fn cli() -> clap::Command {
     clap::Command::new("exhaustive")
+        .version("3.0")
+        .propagate_version(true)
         .args([
+            clap::Arg::new("global")
+                .long("global")
+                .global(true)
+                .action(clap::ArgAction::SetTrue)
+                .help("everywhere"),
             clap::Arg::new("generate")
                 .long("generate")
                 .value_name("SHELL")
                 .value_parser(clap::value_parser!(Shell))
                 .help("generate"),
-            clap::Arg::new("empty-choice")
-                .long("empty-choice")
-                .value_parser(EMPTY),
         ])
         .subcommands([
-            clap::Command::new("empty")
-                .disable_help_subcommand(true)
-                .disable_help_flag(true),
-            clap::Command::new("global")
-                .version("3.0")
-                .propagate_version(true)
-                .args([clap::Arg::new("global")
-                    .long("global")
-                    .global(true)
-                    .action(clap::ArgAction::SetTrue)
-                    .help("everywhere")])
-                .subcommands([
-                    clap::Command::new("one").subcommand(clap::Command::new("one-one")),
-                    clap::Command::new("two"),
-                ]),
             clap::Command::new("action").args([
                 clap::Arg::new("set-true")
                     .long("set-true")
diff --git a/clap_mangen/src/lib.rs b/clap_mangen/src/lib.rs
index 7b8d8af7..50b7dbac 100644
--- a/clap_mangen/src/lib.rs
+++ b/clap_mangen/src/lib.rs
@@ -244,8 +244,39 @@ impl Man {
     }
 
     fn _render_options_section(&self, roff: &mut Roff) {
-        roff.control("SH", ["OPTIONS"]);
-        render::options(roff, &self.cmd);
+        let help_headings = self
+            .cmd
+            .get_arguments()
+            .filter(|a| !a.is_hide_set())
+            .filter_map(|arg| arg.get_help_heading())
+            .fold(vec![], |mut acc, header| {
+                if !acc.contains(&header) {
+                    acc.push(header);
+                }
+
+                acc
+            });
+
+        let (args, mut args_with_heading) =
+            self.cmd
+                .get_arguments()
+                .filter(|a| !a.is_hide_set())
+                .partition::<Vec<_>, _>(|a| a.get_help_heading().is_none());
+
+        if !args.is_empty() {
+            roff.control("SH", ["OPTIONS"]);
+            render::options(roff, &args);
+        }
+
+        for heading in help_headings {
+            let args;
+            (args, args_with_heading) = args_with_heading
+                .into_iter()
+                .partition(|&a| a.get_help_heading() == Some(heading));
+
+            roff.control("SH", [heading.to_uppercase().as_str()]);
+            render::options(roff, &args);
+        }
     }
 
     /// Render the SUBCOMMANDS section into the writer.
diff --git a/clap_mangen/src/render.rs b/clap_mangen/src/render.rs
index 81d4e8c6..c48d13a4 100644
--- a/clap_mangen/src/render.rs
+++ b/clap_mangen/src/render.rs
@@ -88,9 +88,7 @@ pub(crate) fn synopsis(roff: &mut Roff, cmd: &clap::Command) {
     roff.text(line);
 }
 
-pub(crate) fn options(roff: &mut Roff, cmd: &clap::Command) {
-    let items: Vec<_> = cmd.get_arguments().filter(|i| !i.is_hide_set()).collect();
-
+pub(crate) fn options(roff: &mut Roff, items: &[&Arg]) {
     for opt in items.iter().filter(|a| !a.is_positional()) {
         let mut header = match (opt.get_short(), opt.get_long()) {
             (Some(short), Some(long)) => {


Test patch:
diff --git a/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc b/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
index 6fba6ddc..be558dec 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
@@ -20,12 +20,6 @@ _exhaustive() {
             exhaustive,alias)
                 cmd="exhaustive__alias"
                 ;;
-            exhaustive,empty)
-                cmd="exhaustive__empty"
-                ;;
-            exhaustive,global)
-                cmd="exhaustive__global"
-                ;;
             exhaustive,help)
                 cmd="exhaustive__help"
                 ;;
@@ -44,51 +38,12 @@ _exhaustive() {
             exhaustive,value)
                 cmd="exhaustive__value"
                 ;;
-            exhaustive__global,help)
-                cmd="exhaustive__global__help"
-                ;;
-            exhaustive__global,one)
-                cmd="exhaustive__global__one"
-                ;;
-            exhaustive__global,two)
-                cmd="exhaustive__global__two"
-                ;;
-            exhaustive__global__help,help)
-                cmd="exhaustive__global__help__help"
-                ;;
-            exhaustive__global__help,one)
-                cmd="exhaustive__global__help__one"
-                ;;
-            exhaustive__global__help,two)
-                cmd="exhaustive__global__help__two"
-                ;;
-            exhaustive__global__help__one,one-one)
-                cmd="exhaustive__global__help__one__one__one"
-                ;;
-            exhaustive__global__one,help)
-                cmd="exhaustive__global__one__help"
-                ;;
-            exhaustive__global__one,one-one)
-                cmd="exhaustive__global__one__one__one"
-                ;;
-            exhaustive__global__one__help,help)
-                cmd="exhaustive__global__one__help__help"
-                ;;
-            exhaustive__global__one__help,one-one)
-                cmd="exhaustive__global__one__help__one__one"
-                ;;
             exhaustive__help,action)
                 cmd="exhaustive__help__action"
                 ;;
             exhaustive__help,alias)
                 cmd="exhaustive__help__alias"
                 ;;
-            exhaustive__help,empty)
-                cmd="exhaustive__help__empty"
-                ;;
-            exhaustive__help,global)
-                cmd="exhaustive__help__global"
-                ;;
             exhaustive__help,help)
                 cmd="exhaustive__help__help"
                 ;;
@@ -107,15 +62,6 @@ _exhaustive() {
             exhaustive__help,value)
                 cmd="exhaustive__help__value"
                 ;;
-            exhaustive__help__global,one)
-                cmd="exhaustive__help__global__one"
-                ;;
-            exhaustive__help__global,two)
-                cmd="exhaustive__help__global__two"
-                ;;
-            exhaustive__help__global__one,one-one)
-                cmd="exhaustive__help__global__one__one__one"
-                ;;
             exhaustive__help__pacman,one)
                 cmd="exhaustive__help__pacman__one"
                 ;;
@@ -216,7 +162,7 @@ _exhaustive() {
 
     case "${cmd}" in
         exhaustive)
-            opts="-h --generate --empty-choice --help empty global action quote value pacman last alias hint help"
+            opts="-h -V --global --generate --help --version action quote value pacman last alias hint help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -226,10 +172,6 @@ _exhaustive() {
                     COMPREPLY=($(compgen -W "bash elvish fish powershell zsh" -- "${cur}"))
                     return 0
                     ;;
-                --empty-choice)
-                    COMPREPLY=($(compgen -W "" -- "${cur}"))
-                    return 0
-                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -238,7 +180,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__action)
-            opts="-h --set-true --set --count --choice --help"
+            opts="-h -V --set-true --set --count --choice --global --help --version"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -260,7 +202,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__alias)
-            opts="-F -f -O -o -h --flg --flag --opt --option --help [positional]"
+            opts="-F -f -O -o -h -V --flg --flag --opt --option --global --help --version [positional]"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -289,190 +231,8 @@ _exhaustive() {
             COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
             return 0
             ;;
-        exhaustive__empty)
-            opts=""
-            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
-            ;;
-        exhaustive__global)
-            opts="-h -V --global --help --version one two 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
-            ;;
-        exhaustive__global__help)
-            opts="one two help"
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__global__help__help)
-            opts=""
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__global__help__one)
-            opts="one-one"
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__global__help__one__one__one)
-            opts=""
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 5 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__global__help__two)
-            opts=""
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__global__one)
-            opts="-h -V --global --help --version one-one help"
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__global__one__help)
-            opts="one-one help"
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__global__one__help__help)
-            opts=""
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 5 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__global__one__help__one__one)
-            opts=""
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 5 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__global__one__one__one)
-            opts="-h -V --global --help --version"
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__global__two)
-            opts="-h -V --global --help --version"
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
         exhaustive__help)
-            opts="empty global action quote value pacman last alias hint help"
+            opts="action quote value pacman last alias hint help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -513,76 +273,6 @@ _exhaustive() {
             COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
             return 0
             ;;
-        exhaustive__help__empty)
-            opts=""
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__help__global)
-            opts="one two"
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__help__global__one)
-            opts="one-one"
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__help__global__one__one__one)
-            opts=""
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 5 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
-        exhaustive__help__global__two)
-            opts=""
-            if [[ ${cur} == -* || ${COMP_CWORD} -eq 4 ]] ; then
-                COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-                return 0
-            fi
-            case "${prev}" in
-                *)
-                    COMPREPLY=()
-                    ;;
-            esac
-            COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
-            return 0
-            ;;
         exhaustive__help__help)
             opts=""
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
@@ -794,7 +484,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__hint)
-            opts="-p -f -d -e -c -u -H -h --choice --unknown --other --path --file --dir --exe --cmd-name --cmd --user --host --url --email --help [command_with_args]..."
+            opts="-p -f -d -e -c -u -H -h -V --choice --unknown --other --path --file --dir --exe --cmd-name --cmd --user --host --url --email --global --help --version [command_with_args]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -919,7 +609,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__last)
-            opts="-h --help [first] [free]"
+            opts="-h -V --global --help --version [first] [free]"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -933,7 +623,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__pacman)
-            opts="-h --help one two help"
+            opts="-h -V --global --help --version one two help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1003,7 +693,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__pacman__one)
-            opts="-h --help"
+            opts="-h -V --global --help --version"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1017,7 +707,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__pacman__two)
-            opts="-h --help"
+            opts="-h -V --global --help --version"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1031,7 +721,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote)
-            opts="-h --single-quotes --double-quotes --backticks --backslash --brackets --expansions --choice --help cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help"
+            opts="-h -V --single-quotes --double-quotes --backticks --backslash --brackets --expansions --choice --global --help --version cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1049,7 +739,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__cmd__backslash)
-            opts="-h --help"
+            opts="-h -V --global --help --version"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1063,7 +753,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__cmd__backticks)
-            opts="-h --help"
+            opts="-h -V --global --help --version"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1077,7 +767,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__cmd__brackets)
-            opts="-h --help"
+            opts="-h -V --global --help --version"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1091,7 +781,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__cmd__double__quotes)
-            opts="-h --help"
+            opts="-h -V --global --help --version"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1105,7 +795,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__cmd__expansions)
-            opts="-h --help"
+            opts="-h -V --global --help --version"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1119,7 +809,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__cmd__single__quotes)
-            opts="-h --help"
+            opts="-h -V --global --help --version"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1133,7 +823,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__escape__help)
-            opts="-h --help"
+            opts="-h -V --global --help --version"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1273,7 +963,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__value)
-            opts="-h --delim --tuple --require-eq --help [term]..."
+            opts="-h -V --delim --tuple --require-eq --global --help --version [term]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
diff --git a/clap_complete/tests/snapshots/home/static/exhaustive/elvish/elvish/rc.elv b/clap_complete/tests/snapshots/home/static/exhaustive/elvish/elvish/rc.elv
index c164d230..afde72f4 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/elvish/elvish/rc.elv
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/elvish/elvish/rc.elv
@@ -21,11 +21,11 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
     var completions = [
         &'exhaustive'= {
             cand --generate 'generate'
-            cand --empty-choice 'empty-choice'
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
-            cand empty 'empty'
-            cand global 'global'
+            cand -V 'Print version'
+            cand --version 'Print version'
             cand action 'action'
             cand quote 'quote'
             cand value 'value'
@@ -35,70 +35,16 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
             cand hint 'hint'
             cand help 'Print this message or the help of the given subcommand(s)'
         }
-        &'exhaustive;empty'= {
-        }
-        &'exhaustive;global'= {
-            cand --global 'everywhere'
-            cand -h 'Print help'
-            cand --help 'Print help'
-            cand -V 'Print version'
-            cand --version 'Print version'
-            cand one 'one'
-            cand two 'two'
-            cand help 'Print this message or the help of the given subcommand(s)'
-        }
-        &'exhaustive;global;one'= {
-            cand --global 'everywhere'
-            cand -h 'Print help'
-            cand --help 'Print help'
-            cand -V 'Print version'
-            cand --version 'Print version'
-            cand one-one 'one-one'
-            cand help 'Print this message or the help of the given subcommand(s)'
-        }
-        &'exhaustive;global;one;one-one'= {
-            cand --global 'everywhere'
-            cand -h 'Print help'
-            cand --help 'Print help'
-            cand -V 'Print version'
-            cand --version 'Print version'
-        }
-        &'exhaustive;global;one;help'= {
-            cand one-one 'one-one'
-            cand help 'Print this message or the help of the given subcommand(s)'
-        }
-        &'exhaustive;global;one;help;one-one'= {
-        }
-        &'exhaustive;global;one;help;help'= {
-        }
-        &'exhaustive;global;two'= {
-            cand --global 'everywhere'
-            cand -h 'Print help'
-            cand --help 'Print help'
-            cand -V 'Print version'
-            cand --version 'Print version'
-        }
-        &'exhaustive;global;help'= {
-            cand one 'one'
-            cand two 'two'
-            cand help 'Print this message or the help of the given subcommand(s)'
-        }
-        &'exhaustive;global;help;one'= {
-            cand one-one 'one-one'
-        }
-        &'exhaustive;global;help;one;one-one'= {
-        }
-        &'exhaustive;global;help;two'= {
-        }
-        &'exhaustive;global;help;help'= {
-        }
         &'exhaustive;action'= {
             cand --set 'value'
             cand --choice 'enum'
             cand --set-true 'bool'
             cand --count 'number'
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;quote'= {
             cand --choice 'choice'
@@ -108,8 +54,11 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
             cand --backslash 'Avoid ''\n'''
             cand --brackets 'List packages [filter]'
             cand --expansions 'Execute the shell command with $SHELL'
+            cand --global 'everywhere'
             cand -h 'Print help (see more with ''--help'')'
             cand --help 'Print help (see more with ''--help'')'
+            cand -V 'Print version'
+            cand --version 'Print version'
             cand cmd-single-quotes 'Can be ''always'', ''auto'', or ''never'''
             cand cmd-double-quotes 'Can be "always", "auto", or "never"'
             cand cmd-backticks 'For more information see `echo test`'
@@ -120,32 +69,53 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
             cand help 'Print this message or the help of the given subcommand(s)'
         }
         &'exhaustive;quote;cmd-single-quotes'= {
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;quote;cmd-double-quotes'= {
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;quote;cmd-backticks'= {
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;quote;cmd-backslash'= {
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;quote;cmd-brackets'= {
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;quote;cmd-expansions'= {
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;quote;escape-help'= {
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;quote;help'= {
             cand cmd-single-quotes 'Can be ''always'', ''auto'', or ''never'''
@@ -177,23 +147,35 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
             cand --delim 'delim'
             cand --tuple 'tuple'
             cand --require-eq 'require-eq'
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;pacman'= {
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
             cand one 'one'
             cand two 'two'
             cand help 'Print this message or the help of the given subcommand(s)'
         }
         &'exhaustive;pacman;one'= {
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;pacman;two'= {
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;pacman;help'= {
             cand one 'one'
@@ -207,8 +189,11 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
         &'exhaustive;pacman;help;help'= {
         }
         &'exhaustive;last'= {
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;alias'= {
             cand -o 'cmd option'
@@ -219,8 +204,11 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
             cand -F 'cmd flag'
             cand --flag 'cmd flag'
             cand --flg 'cmd flag'
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;hint'= {
             cand --choice 'choice'
@@ -243,12 +231,13 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
             cand --host 'host'
             cand --url 'url'
             cand --email 'email'
+            cand --global 'everywhere'
             cand -h 'Print help'
             cand --help 'Print help'
+            cand -V 'Print version'
+            cand --version 'Print version'
         }
         &'exhaustive;help'= {
-            cand empty 'empty'
-            cand global 'global'
             cand action 'action'
             cand quote 'quote'
             cand value 'value'
@@ -258,19 +247,6 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
             cand hint 'hint'
             cand help 'Print this message or the help of the given subcommand(s)'
         }
-        &'exhaustive;help;empty'= {
-        }
-        &'exhaustive;help;global'= {
-            cand one 'one'
-            cand two 'two'
-        }
-        &'exhaustive;help;global;one'= {
-            cand one-one 'one-one'
-        }
-        &'exhaustive;help;global;one;one-one'= {
-        }
-        &'exhaustive;help;global;two'= {
-        }
         &'exhaustive;help;action'= {
         }
         &'exhaustive;help;quote'= {
diff --git a/clap_complete/tests/snapshots/home/static/exhaustive/fish/fish/completions/exhaustive.fish b/clap_complete/tests/snapshots/home/static/exhaustive/fish/fish/completions/exhaustive.fish
index 926edab8..82c56229 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/fish/fish/completions/exhaustive.fish
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/fish/fish/completions/exhaustive.fish
@@ -1,6 +1,6 @@
 # Print an optspec for argparse to handle cmd's options that are independent of any subcommand.
 function __fish_exhaustive_global_optspecs
-	string join \n generate= empty-choice= h/help
+	string join \n global generate= h/help V/version
 end
 
 function __fish_exhaustive_needs_command
@@ -25,10 +25,9 @@ function __fish_exhaustive_using_subcommand
 end
 
 complete -c exhaustive -n "__fish_exhaustive_needs_command" -l generate -d 'generate' -r -f -a "{bash\t'',elvish\t'',fish\t'',powershell\t'',zsh\t''}"
-complete -c exhaustive -n "__fish_exhaustive_needs_command" -l empty-choice -r -f -a "{}"
+complete -c exhaustive -n "__fish_exhaustive_needs_command" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_needs_command" -s h -l help -d 'Print help'
-complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "empty"
-complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "global"
+complete -c exhaustive -n "__fish_exhaustive_needs_command" -s V -l version -d 'Print version'
 complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "action"
 complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "quote"
 complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "value"
@@ -37,28 +36,13 @@ complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "last"
 complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "alias"
 complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "hint"
 complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and not __fish_seen_subcommand_from one two help" -l global -d 'everywhere'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and not __fish_seen_subcommand_from one two help" -s h -l help -d 'Print help'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and not __fish_seen_subcommand_from one two help" -s V -l version -d 'Print version'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and not __fish_seen_subcommand_from one two help" -f -a "one"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and not __fish_seen_subcommand_from one two help" -f -a "two"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and not __fish_seen_subcommand_from one two help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and __fish_seen_subcommand_from one" -l global -d 'everywhere'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and __fish_seen_subcommand_from one" -s h -l help -d 'Print help'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and __fish_seen_subcommand_from one" -s V -l version -d 'Print version'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and __fish_seen_subcommand_from one" -f -a "one-one"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and __fish_seen_subcommand_from one" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and __fish_seen_subcommand_from two" -l global -d 'everywhere'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and __fish_seen_subcommand_from two" -s h -l help -d 'Print help'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and __fish_seen_subcommand_from two" -s V -l version -d 'Print version'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and __fish_seen_subcommand_from help" -f -a "one"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and __fish_seen_subcommand_from help" -f -a "two"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand global; and __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand action" -l set -d 'value' -r
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand action" -l choice -d 'enum' -r -f -a "{first\t'',second\t''}"
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand action" -l set-true -d 'bool'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand action" -l count -d 'number'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand action" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand action" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand action" -s V -l version -d 'Print version'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -l choice -r -f -a "{another shell\t'something with a space',bash\t'bash (shell)',fish\t'fish shell',zsh\t'zsh shell'}"
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -l single-quotes -d 'Can be \'always\', \'auto\', or \'never\''
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -l double-quotes -d 'Can be "always", "auto", or "never"'
@@ -66,7 +50,9 @@ complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __f
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -l backslash -d 'Avoid \'\\n\''
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -l brackets -d 'List packages [filter]'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -l expansions -d 'Execute the shell command with $SHELL'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -s h -l help -d 'Print help (see more with \'--help\')'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -s V -l version -d 'Print version'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -f -a "cmd-single-quotes" -d 'Can be \'always\', \'auto\', or \'never\''
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -f -a "cmd-double-quotes" -d 'Can be "always", "auto", or "never"'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -f -a "cmd-backticks" -d 'For more information see `echo test`'
@@ -75,13 +61,27 @@ complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __f
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -f -a "cmd-expansions" -d 'Execute the shell command with $SHELL'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -f -a "escape-help" -d '\\tab	"\' New Line'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and not __fish_seen_subcommand_from cmd-single-quotes cmd-double-quotes cmd-backticks cmd-backslash cmd-brackets cmd-expansions escape-help help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-single-quotes" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-single-quotes" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-single-quotes" -s V -l version -d 'Print version'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-double-quotes" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-double-quotes" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-double-quotes" -s V -l version -d 'Print version'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-backticks" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-backticks" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-backticks" -s V -l version -d 'Print version'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-backslash" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-backslash" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-backslash" -s V -l version -d 'Print version'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-brackets" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-brackets" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-brackets" -s V -l version -d 'Print version'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-expansions" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-expansions" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from cmd-expansions" -s V -l version -d 'Print version'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from escape-help" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from escape-help" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from escape-help" -s V -l version -d 'Print version'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from help" -f -a "cmd-single-quotes" -d 'Can be \'always\', \'auto\', or \'never\''
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from help" -f -a "cmd-double-quotes" -d 'Can be "always", "auto", or "never"'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_seen_subcommand_from help" -f -a "cmd-backticks" -d 'For more information see `echo test`'
@@ -93,20 +93,32 @@ complete -c exhaustive -n "__fish_exhaustive_using_subcommand quote; and __fish_
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand value" -l delim -r
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand value" -l tuple -r
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand value" -l require-eq -r
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand value" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand value" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand value" -s V -l version -d 'Print version'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and not __fish_seen_subcommand_from one two help" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and not __fish_seen_subcommand_from one two help" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and not __fish_seen_subcommand_from one two help" -s V -l version -d 'Print version'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and not __fish_seen_subcommand_from one two help" -f -a "one"
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and not __fish_seen_subcommand_from one two help" -f -a "two"
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and not __fish_seen_subcommand_from one two help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and __fish_seen_subcommand_from one" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and __fish_seen_subcommand_from one" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and __fish_seen_subcommand_from one" -s V -l version -d 'Print version'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and __fish_seen_subcommand_from two" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and __fish_seen_subcommand_from two" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and __fish_seen_subcommand_from two" -s V -l version -d 'Print version'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and __fish_seen_subcommand_from help" -f -a "one"
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and __fish_seen_subcommand_from help" -f -a "two"
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand pacman; and __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand last" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand last" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand last" -s V -l version -d 'Print version'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand alias" -s o -s O -l option -l opt -d 'cmd option' -r
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand alias" -s f -s F -l flag -l flg -d 'cmd flag'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand alias" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand alias" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand alias" -s V -l version -d 'Print version'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -l choice -r -f -a "{bash\t'',fish\t'',zsh\t''}"
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -l unknown -r
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -l other -r -f
@@ -120,19 +132,17 @@ complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -s u -l user
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -s H -l host -r -f -a "(__fish_print_hostnames)"
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -l url -r -f
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -l email -r -f
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -s h -l help -d 'Print help'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from empty global action quote value pacman last alias hint help" -f -a "empty"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from empty global action quote value pacman last alias hint help" -f -a "global"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from empty global action quote value pacman last alias hint help" -f -a "action"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from empty global action quote value pacman last alias hint help" -f -a "quote"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from empty global action quote value pacman last alias hint help" -f -a "value"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from empty global action quote value pacman last alias hint help" -f -a "pacman"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from empty global action quote value pacman last alias hint help" -f -a "last"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from empty global action quote value pacman last alias hint help" -f -a "alias"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from empty global action quote value pacman last alias hint help" -f -a "hint"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from empty global action quote value pacman last alias hint help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and __fish_seen_subcommand_from global" -f -a "one"
-complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and __fish_seen_subcommand_from global" -f -a "two"
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand hint" -s V -l version -d 'Print version'
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "action"
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "quote"
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "value"
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "pacman"
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "last"
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "alias"
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "hint"
+complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and not __fish_seen_subcommand_from action quote value pacman last alias hint help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and __fish_seen_subcommand_from quote" -f -a "cmd-single-quotes" -d 'Can be \'always\', \'auto\', or \'never\''
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and __fish_seen_subcommand_from quote" -f -a "cmd-double-quotes" -d 'Can be "always", "auto", or "never"'
 complete -c exhaustive -n "__fish_exhaustive_using_subcommand help; and __fish_seen_subcommand_from quote" -f -a "cmd-backticks" -d 'For more information see `echo test`'
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 24733787..ad827ab1 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive
@@ -16,9 +16,11 @@ _exhaustive() {
     local context curcontext="$curcontext" state line
     _arguments "${_arguments_options[@]}" : \
 '--generate=[generate]:SHELL:(bash elvish fish powershell zsh)' \
-'--empty-choice=[]: :()' \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 ":: :_exhaustive_commands" \
 "*::: :->exhaustive" \
 && ret=0
@@ -28,146 +30,17 @@ _exhaustive() {
         (( CURRENT += 1 ))
         curcontext="${curcontext%:*:*}:exhaustive-command-$line[1]:"
         case $line[1] in
-            (empty)
-_arguments "${_arguments_options[@]}" : \
-&& ret=0
-;;
-(global)
-_arguments "${_arguments_options[@]}" : \
-'--global[everywhere]' \
-'-h[Print help]' \
-'--help[Print help]' \
-'-V[Print version]' \
-'--version[Print version]' \
-":: :_exhaustive__global_commands" \
-"*::: :->global" \
-&& ret=0
-
-    case $state in
-    (global)
-        words=($line[1] "${words[@]}")
-        (( CURRENT += 1 ))
-        curcontext="${curcontext%:*:*}:exhaustive-global-command-$line[1]:"
-        case $line[1] in
-            (one)
-_arguments "${_arguments_options[@]}" : \
-'--global[everywhere]' \
-'-h[Print help]' \
-'--help[Print help]' \
-'-V[Print version]' \
-'--version[Print version]' \
-":: :_exhaustive__global__one_commands" \
-"*::: :->one" \
-&& ret=0
-
-    case $state in
-    (one)
-        words=($line[1] "${words[@]}")
-        (( CURRENT += 1 ))
-        curcontext="${curcontext%:*:*}:exhaustive-global-one-command-$line[1]:"
-        case $line[1] in
-            (one-one)
-_arguments "${_arguments_options[@]}" : \
-'--global[everywhere]' \
-'-h[Print help]' \
-'--help[Print help]' \
-'-V[Print version]' \
-'--version[Print version]' \
-&& ret=0
-;;
-(help)
-_arguments "${_arguments_options[@]}" : \
-":: :_exhaustive__global__one__help_commands" \
-"*::: :->help" \
-&& ret=0
-
-    case $state in
-    (help)
-        words=($line[1] "${words[@]}")
-        (( CURRENT += 1 ))
-        curcontext="${curcontext%:*:*}:exhaustive-global-one-help-command-$line[1]:"
-        case $line[1] in
-            (one-one)
-_arguments "${_arguments_options[@]}" : \
-&& ret=0
-;;
-(help)
-_arguments "${_arguments_options[@]}" : \
-&& ret=0
-;;
-        esac
-    ;;
-esac
-;;
-        esac
-    ;;
-esac
-;;
-(two)
-_arguments "${_arguments_options[@]}" : \
-'--global[everywhere]' \
-'-h[Print help]' \
-'--help[Print help]' \
-'-V[Print version]' \
-'--version[Print version]' \
-&& ret=0
-;;
-(help)
-_arguments "${_arguments_options[@]}" : \
-":: :_exhaustive__global__help_commands" \
-"*::: :->help" \
-&& ret=0
-
-    case $state in
-    (help)
-        words=($line[1] "${words[@]}")
-        (( CURRENT += 1 ))
-        curcontext="${curcontext%:*:*}:exhaustive-global-help-command-$line[1]:"
-        case $line[1] in
-            (one)
-_arguments "${_arguments_options[@]}" : \
-":: :_exhaustive__global__help__one_commands" \
-"*::: :->one" \
-&& ret=0
-
-    case $state in
-    (one)
-        words=($line[1] "${words[@]}")
-        (( CURRENT += 1 ))
-        curcontext="${curcontext%:*:*}:exhaustive-global-help-one-command-$line[1]:"
-        case $line[1] in
-            (one-one)
-_arguments "${_arguments_options[@]}" : \
-&& ret=0
-;;
-        esac
-    ;;
-esac
-;;
-(two)
-_arguments "${_arguments_options[@]}" : \
-&& ret=0
-;;
-(help)
-_arguments "${_arguments_options[@]}" : \
-&& ret=0
-;;
-        esac
-    ;;
-esac
-;;
-        esac
-    ;;
-esac
-;;
-(action)
+            (action)
 _arguments "${_arguments_options[@]}" : \
 '--set=[value]: :_default' \
 '--choice=[enum]: :(first second)' \
 '--set-true[bool]' \
 '*--count[number]' \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 && ret=0
 ;;
 (quote)
@@ -182,8 +55,11 @@ zsh\:"zsh shell"))' \
 '--backslash[Avoid '\''\\n'\'']' \
 '--brackets[List packages \[filter\]]' \
 '--expansions[Execute the shell command with \$SHELL]' \
+'--global[everywhere]' \
 '-h[Print help (see more with '\''--help'\'')]' \
 '--help[Print help (see more with '\''--help'\'')]' \
+'-V[Print version]' \
+'--version[Print version]' \
 ":: :_exhaustive__quote_commands" \
 "*::: :->quote" \
 && ret=0
@@ -196,44 +72,65 @@ zsh\:"zsh shell"))' \
         case $line[1] in
             (cmd-single-quotes)
 _arguments "${_arguments_options[@]}" : \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 && ret=0
 ;;
 (cmd-double-quotes)
 _arguments "${_arguments_options[@]}" : \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 && ret=0
 ;;
 (cmd-backticks)
 _arguments "${_arguments_options[@]}" : \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 && ret=0
 ;;
 (cmd-backslash)
 _arguments "${_arguments_options[@]}" : \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 && ret=0
 ;;
 (cmd-brackets)
 _arguments "${_arguments_options[@]}" : \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 && ret=0
 ;;
 (cmd-expansions)
 _arguments "${_arguments_options[@]}" : \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 && ret=0
 ;;
 (escape-help)
 _arguments "${_arguments_options[@]}" : \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 && ret=0
 ;;
 (help)
@@ -293,15 +190,21 @@ _arguments "${_arguments_options[@]}" : \
 '--delim=[]: :_default' \
 '--tuple=[]: :_default: :_default' \
 '--require-eq=[]: :_default' \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 '*;::term:_default' \
 && ret=0
 ;;
 (pacman)
 _arguments "${_arguments_options[@]}" : \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 ":: :_exhaustive__pacman_commands" \
 "*::: :->pacman" \
 && ret=0
@@ -314,14 +217,20 @@ _arguments "${_arguments_options[@]}" : \
         case $line[1] in
             (one)
 _arguments "${_arguments_options[@]}" : \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 && ret=0
 ;;
 (two)
 _arguments "${_arguments_options[@]}" : \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 && ret=0
 ;;
 (help)
@@ -358,8 +267,11 @@ esac
 ;;
 (last)
 _arguments "${_arguments_options[@]}" : \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 '::first:_default' \
 '::free:_default' \
 && ret=0
@@ -374,8 +286,11 @@ _arguments "${_arguments_options[@]}" : \
 '-F[cmd flag]' \
 '--flag[cmd flag]' \
 '--flg[cmd flag]' \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 '::positional:_default' \
 && ret=0
 ;;
@@ -401,8 +316,11 @@ _arguments "${_arguments_options[@]}" : \
 '--host=[]: :_hosts' \
 '--url=[]: :_urls' \
 '--email=[]: :_email_addresses' \
+'--global[everywhere]' \
 '-h[Print help]' \
 '--help[Print help]' \
+'-V[Print version]' \
+'--version[Print version]' \
 '*::command_with_args:_cmdambivalent' \
 && ret=0
 ;;
@@ -418,51 +336,7 @@ _arguments "${_arguments_options[@]}" : \
         (( CURRENT += 1 ))
         curcontext="${curcontext%:*:*}:exhaustive-help-command-$line[1]:"
         case $line[1] in
-            (empty)
-_arguments "${_arguments_options[@]}" : \
-&& ret=0
-;;
-(global)
-_arguments "${_arguments_options[@]}" : \
-":: :_exhaustive__help__global_commands" \
-"*::: :->global" \
-&& ret=0
-
-    case $state in
-    (global)
-        words=($line[1] "${words[@]}")
-        (( CURRENT += 1 ))
-        curcontext="${curcontext%:*:*}:exhaustive-help-global-command-$line[1]:"
-        case $line[1] in
-            (one)
-_arguments "${_arguments_options[@]}" : \
-":: :_exhaustive__help__global__one_commands" \
-"*::: :->one" \
-&& ret=0
-
-    case $state in
-    (one)
-        words=($line[1] "${words[@]}")
-        (( CURRENT += 1 ))
-        curcontext="${curcontext%:*:*}:exhaustive-help-global-one-command-$line[1]:"
-        case $line[1] in
-            (one-one)
-_arguments "${_arguments_options[@]}" : \
-&& ret=0
-;;
-        esac
-    ;;
-esac
-;;
-(two)
-_arguments "${_arguments_options[@]}" : \
-&& ret=0
-;;
-        esac
-    ;;
-esac
-;;
-(action)
+            (action)
 _arguments "${_arguments_options[@]}" : \
 && ret=0
 ;;
@@ -566,8 +440,6 @@ esac
 (( $+functions[_exhaustive_commands] )) ||
 _exhaustive_commands() {
     local commands; commands=(
-'empty:' \
-'global:' \
 'action:' \
 'quote:' \
 'value:' \
@@ -589,92 +461,9 @@ _exhaustive__alias_commands() {
     local commands; commands=()
     _describe -t commands 'exhaustive alias commands' commands "$@"
 }
-(( $+functions[_exhaustive__empty_commands] )) ||
-_exhaustive__empty_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive empty commands' commands "$@"
-}
-(( $+functions[_exhaustive__global_commands] )) ||
-_exhaustive__global_commands() {
-    local commands; commands=(
-'one:' \
-'two:' \
-'help:Print this message or the help of the given subcommand(s)' \
-    )
-    _describe -t commands 'exhaustive global commands' commands "$@"
-}
-(( $+functions[_exhaustive__global__help_commands] )) ||
-_exhaustive__global__help_commands() {
-    local commands; commands=(
-'one:' \
-'two:' \
-'help:Print this message or the help of the given subcommand(s)' \
-    )
-    _describe -t commands 'exhaustive global help commands' commands "$@"
-}
-(( $+functions[_exhaustive__global__help__help_commands] )) ||
-_exhaustive__global__help__help_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive global help help commands' commands "$@"
-}
-(( $+functions[_exhaustive__global__help__one_commands] )) ||
-_exhaustive__global__help__one_commands() {
-    local commands; commands=(
-'one-one:' \
-    )
-    _describe -t commands 'exhaustive global help one commands' commands "$@"
-}
-(( $+functions[_exhaustive__global__help__one__one-one_commands] )) ||
-_exhaustive__global__help__one__one-one_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive global help one one-one commands' commands "$@"
-}
-(( $+functions[_exhaustive__global__help__two_commands] )) ||
-_exhaustive__global__help__two_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive global help two commands' commands "$@"
-}
-(( $+functions[_exhaustive__global__one_commands] )) ||
-_exhaustive__global__one_commands() {
-    local commands; commands=(
-'one-one:' \
-'help:Print this message or the help of the given subcommand(s)' \
-    )
-    _describe -t commands 'exhaustive global one commands' commands "$@"
-}
-(( $+functions[_exhaustive__global__one__help_commands] )) ||
-_exhaustive__global__one__help_commands() {
-    local commands; commands=(
-'one-one:' \
-'help:Print this message or the help of the given subcommand(s)' \
-    )
-    _describe -t commands 'exhaustive global one help commands' commands "$@"
-}
-(( $+functions[_exhaustive__global__one__help__help_commands] )) ||
-_exhaustive__global__one__help__help_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive global one help help commands' commands "$@"
-}
-(( $+functions[_exhaustive__global__one__help__one-one_commands] )) ||
-_exhaustive__global__one__help__one-one_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive global one help one-one commands' commands "$@"
-}
-(( $+functions[_exhaustive__global__one__one-one_commands] )) ||
-_exhaustive__global__one__one-one_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive global one one-one commands' commands "$@"
-}
-(( $+functions[_exhaustive__global__two_commands] )) ||
-_exhaustive__global__two_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive global two commands' commands "$@"
-}
 (( $+functions[_exhaustive__help_commands] )) ||
 _exhaustive__help_commands() {
     local commands; commands=(
-'empty:' \
-'global:' \
 'action:' \
 'quote:' \
 'value:' \
@@ -696,36 +485,6 @@ _exhaustive__help__alias_commands() {
     local commands; commands=()
     _describe -t commands 'exhaustive help alias commands' commands "$@"
 }
-(( $+functions[_exhaustive__help__empty_commands] )) ||
-_exhaustive__help__empty_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive help empty commands' commands "$@"
-}
-(( $+functions[_exhaustive__help__global_commands] )) ||
-_exhaustive__help__global_commands() {
-    local commands; commands=(
-'one:' \
-'two:' \
-    )
-    _describe -t commands 'exhaustive help global commands' commands "$@"
-}
-(( $+functions[_exhaustive__help__global__one_commands] )) ||
-_exhaustive__help__global__one_commands() {
-    local commands; commands=(
-'one-one:' \
-    )
-    _describe -t commands 'exhaustive help global one commands' commands "$@"
-}
-(( $+functions[_exhaustive__help__global__one__one-one_commands] )) ||
-_exhaustive__help__global__one__one-one_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive help global one one-one commands' commands "$@"
-}
-(( $+functions[_exhaustive__help__global__two_commands] )) ||
-_exhaustive__help__global__two_commands() {
-    local commands; commands=()
-    _describe -t commands 'exhaustive help global two commands' commands "$@"
-}
 (( $+functions[_exhaustive__help__help_commands] )) ||
 _exhaustive__help__help_commands() {
     local commands; commands=()
diff --git a/clap_complete/tests/testsuite/bash.rs b/clap_complete/tests/testsuite/bash.rs
index 9f7ef238..0f3f1bce 100644
--- a/clap_complete/tests/testsuite/bash.rs
+++ b/clap_complete/tests/testsuite/bash.rs
@@ -164,22 +164,12 @@ fn complete() {
     let input = "exhaustive \t\t";
     let expected = snapbox::str![[r#"
 % 
--h              --empty-choice  empty           action          value           last            hint
---generate      --help          global          quote           pacman          alias           help
+-h          --global    --help      action      value       last        hint        
+-V          --generate  --version   quote       pacman      alias       help        
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
 
-    let input = "exhaustive empty \t";
-    let expected = snapbox::str!["exhaustive empty        % exhaustive empty "];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-
-    let input = "exhaustive --empty=\t";
-    let expected = snapbox::str!["exhaustive --empty=     % exhaustive --empty="];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-
     // Issue 5239 (https://github.com/clap-rs/clap/issues/5239)
     let input = "exhaustive hint --file test\t";
     let expected = snapbox::str!["exhaustive hint --file test     % exhaustive hint --file tests/"];
@@ -270,8 +260,8 @@ fn complete_dynamic_env_toplevel() {
     let input = "exhaustive \t\t";
     let expected = snapbox::str![[r#"
 % 
-empty           action          value           last            hint            --generate      --help
-global          quote           pacman          alias           help            --empty-choice  
+action      value       last        hint        --global    --help      
+quote       pacman      alias       help        --generate  --version   
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -291,9 +281,9 @@ fn complete_dynamic_env_quoted_help() {
     let input = "exhaustive quote \t\t";
     let expected = snapbox::str![[r#"
 % 
-cmd-single-quotes  cmd-backslash      escape-help        --double-quotes    --brackets         --help
-cmd-double-quotes  cmd-brackets       help               --backticks        --expansions       
-cmd-backticks      cmd-expansions     --single-quotes    --backslash        --choice           
+cmd-single-quotes  cmd-backslash      escape-help        --global           --backslash        --choice
+cmd-double-quotes  cmd-brackets       help               --double-quotes    --brackets         --help
+cmd-backticks      cmd-expansions     --single-quotes    --backticks        --expansions       --version
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -346,37 +336,3 @@ another shell  bash           fish           zsh
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
 }
-
-#[test]
-#[cfg(all(unix, feature = "unstable-dynamic"))]
-#[cfg(feature = "unstable-shell-tests")]
-fn complete_dynamic_empty_subcommand() {
-    if !common::has_command(CMD) {
-        return;
-    }
-
-    let term = completest::Term::new();
-    let mut runtime = common::load_runtime::<RuntimeBuilder>("dynamic-env", "exhaustive");
-
-    let input = "exhaustive empty \t";
-    let expected = snapbox::str!["exhaustive empty        % exhaustive empty "];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-}
-
-#[test]
-#[cfg(all(unix, feature = "unstable-dynamic"))]
-#[cfg(feature = "unstable-shell-tests")]
-fn complete_dynamic_empty_option_value() {
-    if !common::has_command(CMD) {
-        return;
-    }
-
-    let term = completest::Term::new();
-    let mut runtime = common::load_runtime::<RuntimeBuilder>("dynamic-env", "exhaustive");
-
-    let input = "exhaustive --empty=\t";
-    let expected = snapbox::str!["exhaustive --empty=     % exhaustive --empty="];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-}
diff --git a/clap_complete/tests/testsuite/elvish.rs b/clap_complete/tests/testsuite/elvish.rs
index c9dc59b6..98f27e59 100644
--- a/clap_complete/tests/testsuite/elvish.rs
+++ b/clap_complete/tests/testsuite/elvish.rs
@@ -152,7 +152,7 @@ fn register_completion() {
 #[test]
 #[cfg(unix)]
 #[cfg(feature = "unstable-shell-tests")]
-fn complete() {
+fn complete_static_toplevel() {
     if !common::has_command(CMD) {
         return;
     }
@@ -162,38 +162,22 @@ fn complete() {
 
     let input = "exhaustive \t";
     let expected = snapbox::str![[r#"
-% exhaustive --empty-choice
+% exhaustive --generate
  COMPLETING argument  
---empty-choice empty-choice                                             
 --generate     generate                                                 
+--global       everywhere                                               
 --help         Print help                                               
+--version      Print version                                            
+-V             Print version                                            
 -h             Print help                                               
 action         action                                                   
 alias          alias                                                    
-empty          empty                                                    
-global         global                                                   
 help           Print this message or the help of the given subcommand(s)
 hint           hint                                                     
 last           last                                                     
 pacman         pacman                                                   
 quote          quote                                                    
 value          value                                                    
-"#]];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-
-    let input = "exhaustive empty \t";
-    let expected = snapbox::str![[r#"
-no candidates
-% exhaustive empty 
-"#]];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-
-    let input = "exhaustive --empty=\t";
-    let expected = snapbox::str![[r#"
-no candidates
-% exhaustive --empty=
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -219,10 +203,10 @@ fn complete_dynamic_env_toplevel() {
 
     let input = "exhaustive \t";
     let expected = snapbox::str![[r#"
-% exhaustive --empty-choice
+% exhaustive --generate
  COMPLETING argument  
---empty-choice  --help  alias  global  hint  pacman  value
---generate      action  empty  help    last  quote 
+--generate  --help     action  help  last    quote
+--global    --version  alias   hint  pacman  value
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -243,9 +227,9 @@ fn complete_dynamic_env_quoted_help() {
     let expected = snapbox::str![[r#"
 % exhaustive quote --backslash
  COMPLETING argument  
---backslash  --choice         --help           cmd-backticks      cmd-expansions     help
---backticks  --double-quotes  --single-quotes  cmd-brackets       cmd-single-quotes
---brackets   --expansions     cmd-backslash    cmd-double-quotes  escape-help      
+--backslash  --choice         --global         --version      cmd-brackets       cmd-single-quotes
+--backticks  --double-quotes  --help           cmd-backslash  cmd-double-quotes  escape-help      
+--brackets   --expansions     --single-quotes  cmd-backticks  cmd-expansions     help             
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -310,44 +294,3 @@ another shell
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
 }
-
-#[test]
-#[cfg(all(unix, feature = "unstable-dynamic"))]
-#[cfg(feature = "unstable-shell-tests")]
-fn complete_dynamic_empty_subcommand() {
-    if !common::has_command(CMD) {
-        return;
-    }
-
-    let term = completest::Term::new();
-    let mut runtime = common::load_runtime::<RuntimeBuilder>("dynamic-env", "exhaustive");
-
-    let input = "exhaustive empty \t\t";
-    let expected = snapbox::str![[r#"
-no candidates
-no candidates
-% exhaustive empty 
-"#]];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-}
-
-#[test]
-#[cfg(all(unix, feature = "unstable-dynamic"))]
-#[cfg(feature = "unstable-shell-tests")]
-fn complete_dynamic_empty_option_value() {
-    if !common::has_command(CMD) {
-        return;
-    }
-
-    let term = completest::Term::new();
-    let mut runtime = common::load_runtime::<RuntimeBuilder>("dynamic-env", "exhaustive");
-
-    let input = "exhaustive --empty=\t";
-    let expected = snapbox::str![[r#"
-no candidates
-% exhaustive --empty=
-"#]];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-}
diff --git a/clap_complete/tests/testsuite/fish.rs b/clap_complete/tests/testsuite/fish.rs
index a788debb..590faedc 100644
--- a/clap_complete/tests/testsuite/fish.rs
+++ b/clap_complete/tests/testsuite/fish.rs
@@ -163,26 +163,12 @@ fn complete() {
     let input = "exhaustive \t";
     let expected = snapbox::str![[r#"
 % exhaustive 
-action  empty   help  (Print this message or the help of the given subcommand(s))  last    quote
-alias   global  hint                                                               pacman  value
+action  help  (Print this message or the help of the given subcommand(s))  last    quote
+alias   hint                                                               pacman  value
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
 
-    let input = "exhaustive empty \t";
-    let expected = snapbox::str![[r#"
-% exhaustive empty 
-Cargo.toml    CONTRIBUTING.md  LICENSE-APACHE  README.md  tests/
-CHANGELOG.md  examples/        LICENSE-MIT     src/       
-"#]];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-
-    let input = "exhaustive --empty=\t";
-    let expected = snapbox::str!["% exhaustive --empty="];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-
     let input = "exhaustive quote --choice \t";
     let actual = runtime.complete(input, &term).unwrap();
     let expected = snapbox::str![[r#"
@@ -212,10 +198,10 @@ fn complete_dynamic_env_toplevel() {
 
     let input = "exhaustive \t\t";
     let expected = snapbox::str![[r#"
-% exhaustive empty 
-empty   quote   last   help  (Print this message or the help of the given subcommand(s))  --help  (Print help)
-global  value   alias  --generate                                             (generate)  
-action  pacman  hint   --empty-choice                                                     
+% exhaustive action 
+action  pacman  hint                                                               --generate      (generate)
+quote   last    help  (Print this message or the help of the given subcommand(s))  --help        (Print help)
+value   alias   --global                                             (everywhere)  --version  (Print version)
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -244,6 +230,7 @@ cmd-expansions            (Execute the shell command with $SHELL)
 escape-help                                             (/tab "')
 help  (Print this message or the help of the given subcommand(s))
 --single-quotes             (Can be 'always', 'auto', or 'never')
+--global                                             (everywhere)
 --double-quotes             (Can be "always", "auto", or "never")
 --backticks                (For more information see `echo test`)
 --backslash                                          (Avoid '/n')
@@ -251,6 +238,7 @@ help  (Print this message or the help of the given subcommand(s))
 --expansions              (Execute the shell command with $SHELL)
 --choice                                                         
 --help                      (Print help (see more with '--help'))
+--version                                         (Print version)
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -305,37 +293,3 @@ another shell  (something with a space)  bash  (bash (shell))  fish  (fish shell
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
 }
-
-#[test]
-#[cfg(all(unix, feature = "unstable-dynamic"))]
-#[cfg(feature = "unstable-shell-tests")]
-fn complete_dynamic_empty_subcommand() {
-    if !common::has_command(CMD) {
-        return;
-    }
-
-    let term = completest::Term::new();
-    let mut runtime = common::load_runtime::<RuntimeBuilder>("dynamic-env", "exhaustive");
-
-    let input = "exhaustive empty \t\t";
-    let expected = snapbox::str!["% exhaustive empty "];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-}
-
-#[test]
-#[cfg(all(unix, feature = "unstable-dynamic"))]
-#[cfg(feature = "unstable-shell-tests")]
-fn complete_dynamic_empty_option_value() {
-    if !common::has_command(CMD) {
-        return;
-    }
-
-    let term = completest::Term::new();
-    let mut runtime = common::load_runtime::<RuntimeBuilder>("dynamic-env", "exhaustive");
-
-    let input = "exhaustive --empty=\t";
-    let expected = snapbox::str!["% exhaustive --empty="];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-}
diff --git a/clap_complete/tests/testsuite/zsh.rs b/clap_complete/tests/testsuite/zsh.rs
index 13d6a53e..757c33f1 100644
--- a/clap_complete/tests/testsuite/zsh.rs
+++ b/clap_complete/tests/testsuite/zsh.rs
@@ -164,22 +164,11 @@ fn complete() {
     let input = "exhaustive \t";
     let expected = snapbox::str![[r#"
 % exhaustive
-help                                                      -- Print this message or the help of the given subcommand(s)
-hint                                                      
-pacman  action  global  alias  value  quote  empty  last  --                                                          
+help                                             -- Print this message or the help of the given subcommand(s)         
+pacman  action  alias  value  quote  hint  last  --                                                                   
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
-
-    let input = "exhaustive empty \t";
-    let expected = snapbox::str!["% exhaustive empty "];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-
-    let input = "exhaustive --empty=\t";
-    let expected = snapbox::str!["% exhaustive --empty="];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
 }
 
 #[test]
@@ -203,11 +192,12 @@ fn complete_dynamic_env_toplevel() {
     let input = "exhaustive \t\t";
     let expected = snapbox::str![[r#"
 % exhaustive
---generate      -- generate
---help          -- Print help
-help            -- Print this message or the help of the given subcommand(s)
---empty-choice  alias           global          last            quote           
-action          empty           hint            pacman          value           
+--generate  -- generate
+--global    -- everywhere
+--help      -- Print help
+--version   -- Print version
+help        -- Print this message or the help of the given subcommand(s)
+action  alias   hint    last    pacman  quote   value
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -227,7 +217,9 @@ fn complete_dynamic_env_quoted_help() {
     let input = "exhaustive quote \t\t";
     let expected = snapbox::str![[r#"
 % exhaustive quote
+--global                            -- everywhere                                                                     
 --help                              -- Print help (see more with '--help')                                            
+--version                           -- Print version                                                                  
 cmd-backslash      --backslash      -- Avoid '/n'                                                                     
 cmd-backticks      --backticks      -- For more information see `echo test`                                           
 cmd-brackets       --brackets       -- List packages [filter]                                                         
@@ -294,37 +286,3 @@ zsh            -- zsh shell
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
 }
-
-#[test]
-#[cfg(all(unix, feature = "unstable-dynamic"))]
-#[cfg(feature = "unstable-shell-tests")]
-fn complete_dynamic_empty_subcommand() {
-    if !common::has_command(CMD) {
-        return;
-    }
-
-    let term = completest::Term::new();
-    let mut runtime = common::load_runtime::<RuntimeBuilder>("dynamic-env", "exhaustive");
-
-    let input = "exhaustive empty \t\t";
-    let expected = snapbox::str!["% exhaustive empty "];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-}
-
-#[test]
-#[cfg(all(unix, feature = "unstable-dynamic"))]
-#[cfg(feature = "unstable-shell-tests")]
-fn complete_dynamic_empty_option_value() {
-    if !common::has_command(CMD) {
-        return;
-    }
-
-    let term = completest::Term::new();
-    let mut runtime = common::load_runtime::<RuntimeBuilder>("dynamic-env", "exhaustive");
-
-    let input = "exhaustive --empty=\t";
-    let expected = snapbox::str!["% exhaustive --empty="];
-    let actual = runtime.complete(input, &term).unwrap();
-    assert_data_eq!(actual, expected);
-}
diff --git a/clap_mangen/tests/snapshots/help_headings.bash.roff b/clap_mangen/tests/snapshots/help_headings.bash.roff
new file mode 100644
index 00000000..e3400e25
--- /dev/null
+++ b/clap_mangen/tests/snapshots/help_headings.bash.roff
@@ -0,0 +1,25 @@
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.TH my-app 1  "my-app " 
+.SH NAME
+my\-app
+.SH SYNOPSIS
+\fBmy\-app\fR [\fB\-r\fR|\fB\-\-recursive\fR] [\fB\-f\fR|\fB\-\-force\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIcolor\fR] 
+.SH DESCRIPTION
+.SH OPTIONS
+.TP
+\fB\-r\fR, \fB\-\-recursive\fR
+
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help
+.SH "CONFLICT OPTIONS"
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+
+.SH "GLOBAL OPTIONS"
+.TP
+[\fIcolor\fR]
+
+.br
+[\fIpossible values: \fRalways, never, auto]
diff --git a/clap_mangen/tests/testsuite/common.rs b/clap_mangen/tests/testsuite/common.rs
index fcb20cd8..e4ed80c5 100644
--- a/clap_mangen/tests/testsuite/common.rs
+++ b/clap_mangen/tests/testsuite/common.rs
@@ -323,3 +323,34 @@ pub(crate) fn value_name_without_arg(name: &'static str) -> clap::Command {
             .action(clap::ArgAction::SetTrue),
     )
 }
+
+pub(crate) fn help_headings(name: &'static str) -> clap::Command {
+    clap::Command::new(name)
+        .arg(
+            clap::Arg::new("recursive")
+                .long("recursive")
+                .short('r')
+                .action(clap::ArgAction::SetTrue),
+        )
+        .next_help_heading("Conflict Options")
+        .arg(
+            clap::Arg::new("force")
+                .long("force")
+                .short('f')
+                .action(clap::ArgAction::SetTrue),
+        )
+        .next_help_heading("Hidden Options")
+        .arg(
+            clap::Arg::new("debug")
+                .long("debug")
+                .short('d')
+                .hide(true)
+                .action(clap::ArgAction::SetTrue),
+        )
+        .next_help_heading("Global Options")
+        .arg(
+            clap::Arg::new("color")
+                .global(true)
+                .value_parser(["always", "never", "auto"]),
+        )
+}
diff --git a/clap_mangen/tests/testsuite/roff.rs b/clap_mangen/tests/testsuite/roff.rs
index 9f3f4ee6..6adfcd23 100644
--- a/clap_mangen/tests/testsuite/roff.rs
+++ b/clap_mangen/tests/testsuite/roff.rs
@@ -96,6 +96,13 @@ fn sub_subcommands_help() {
     }
 }
 
+#[test]
+fn help_headings() {
+    let name = "my-app";
+    let cmd = common::help_headings(name);
+    common::assert_matches(snapbox::file!["../snapshots/help_headings.bash.roff"], cmd);
+}
+
 #[test]
 fn value_name_without_arg() {
     let name = "my-app";