Repository: clap-rs/clap
Pull request #5857 (2024-12-24 01:55:40)

test(complete() Show empty candidate behavior
This was meant to help with #5856 but I couldn't reproduce the behavior


Patch:
diff --git a/clap_complete/examples/exhaustive.rs b/clap_complete/examples/exhaustive.rs
index 2c00a2c7..1cc3be28 100644
--- a/clap_complete/examples/exhaustive.rs
+++ b/clap_complete/examples/exhaustive.rs
@@ -23,24 +23,37 @@ 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")


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 be558dec..6fba6ddc 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
@@ -20,6 +20,12 @@ _exhaustive() {
             exhaustive,alias)
                 cmd="exhaustive__alias"
                 ;;
+            exhaustive,empty)
+                cmd="exhaustive__empty"
+                ;;
+            exhaustive,global)
+                cmd="exhaustive__global"
+                ;;
             exhaustive,help)
                 cmd="exhaustive__help"
                 ;;
@@ -38,12 +44,51 @@ _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"
                 ;;
@@ -62,6 +107,15 @@ _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"
                 ;;
@@ -162,7 +216,7 @@ _exhaustive() {
 
     case "${cmd}" in
         exhaustive)
-            opts="-h -V --global --generate --help --version action quote value pacman last alias hint help"
+            opts="-h --generate --empty-choice --help empty global action quote value pacman last alias hint help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -172,6 +226,10 @@ _exhaustive() {
                     COMPREPLY=($(compgen -W "bash elvish fish powershell zsh" -- "${cur}"))
                     return 0
                     ;;
+                --empty-choice)
+                    COMPREPLY=($(compgen -W "" -- "${cur}"))
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -180,7 +238,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__action)
-            opts="-h -V --set-true --set --count --choice --global --help --version"
+            opts="-h --set-true --set --count --choice --help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -202,7 +260,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__alias)
-            opts="-F -f -O -o -h -V --flg --flag --opt --option --global --help --version [positional]"
+            opts="-F -f -O -o -h --flg --flag --opt --option --help [positional]"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -231,8 +289,190 @@ _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="action quote value pacman last alias hint help"
+            opts="empty global action quote value pacman last alias hint help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -273,6 +513,76 @@ _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
@@ -484,7 +794,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__hint)
-            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]..."
+            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]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -609,7 +919,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__last)
-            opts="-h -V --global --help --version [first] [free]"
+            opts="-h --help [first] [free]"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -623,7 +933,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__pacman)
-            opts="-h -V --global --help --version one two help"
+            opts="-h --help one two help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -693,7 +1003,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__pacman__one)
-            opts="-h -V --global --help --version"
+            opts="-h --help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -707,7 +1017,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__pacman__two)
-            opts="-h -V --global --help --version"
+            opts="-h --help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -721,7 +1031,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote)
-            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"
+            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"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -739,7 +1049,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__cmd__backslash)
-            opts="-h -V --global --help --version"
+            opts="-h --help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -753,7 +1063,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__cmd__backticks)
-            opts="-h -V --global --help --version"
+            opts="-h --help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -767,7 +1077,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__cmd__brackets)
-            opts="-h -V --global --help --version"
+            opts="-h --help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -781,7 +1091,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__cmd__double__quotes)
-            opts="-h -V --global --help --version"
+            opts="-h --help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -795,7 +1105,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__cmd__expansions)
-            opts="-h -V --global --help --version"
+            opts="-h --help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -809,7 +1119,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__cmd__single__quotes)
-            opts="-h -V --global --help --version"
+            opts="-h --help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -823,7 +1133,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote__escape__help)
-            opts="-h -V --global --help --version"
+            opts="-h --help"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -963,7 +1273,7 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__value)
-            opts="-h -V --delim --tuple --require-eq --global --help --version [term]..."
+            opts="-h --delim --tuple --require-eq --help [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 afde72f4..c164d230 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 --global 'everywhere'
+            cand --empty-choice 'empty-choice'
             cand -h 'Print help'
             cand --help 'Print help'
-            cand -V 'Print version'
-            cand --version 'Print version'
+            cand empty 'empty'
+            cand global 'global'
             cand action 'action'
             cand quote 'quote'
             cand value 'value'
@@ -35,16 +35,70 @@ 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'
@@ -54,11 +108,8 @@ 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`'
@@ -69,53 +120,32 @@ 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'''
@@ -147,35 +177,23 @@ 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'
@@ -189,11 +207,8 @@ 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'
@@ -204,11 +219,8 @@ 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'
@@ -231,13 +243,12 @@ 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'
@@ -247,6 +258,19 @@ 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 82c56229..926edab8 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 global generate= h/help V/version
+	string join \n generate= empty-choice= h/help
 end
 
 function __fish_exhaustive_needs_command
@@ -25,9 +25,10 @@ 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 global -d 'everywhere'
+complete -c exhaustive -n "__fish_exhaustive_needs_command" -l empty-choice -r -f -a "{}"
 complete -c exhaustive -n "__fish_exhaustive_needs_command" -s h -l help -d 'Print help'
-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 "empty"
+complete -c exhaustive -n "__fish_exhaustive_needs_command" -f -a "global"
 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"
@@ -36,13 +37,28 @@ 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"'
@@ -50,9 +66,7 @@ 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`'
@@ -61,27 +75,13 @@ 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,32 +93,20 @@ 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
@@ -132,17 +120,19 @@ 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 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 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 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 ad827ab1..24733787 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive
@@ -16,11 +16,9 @@ _exhaustive() {
     local context curcontext="$curcontext" state line
     _arguments "${_arguments_options[@]}" : \
 '--generate=[generate]:SHELL:(bash elvish fish powershell zsh)' \
-'--global[everywhere]' \
+'--empty-choice=[]: :()' \
 '-h[Print help]' \
 '--help[Print help]' \
-'-V[Print version]' \
-'--version[Print version]' \
 ":: :_exhaustive_commands" \
 "*::: :->exhaustive" \
 && ret=0
@@ -30,17 +28,146 @@ _exhaustive() {
         (( CURRENT += 1 ))
         curcontext="${curcontext%:*:*}:exhaustive-command-$line[1]:"
         case $line[1] in
-            (action)
+            (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)
 _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)
@@ -55,11 +182,8 @@ 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
@@ -72,65 +196,44 @@ 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)
@@ -190,21 +293,15 @@ _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
@@ -217,20 +314,14 @@ _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)
@@ -267,11 +358,8 @@ 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
@@ -286,11 +374,8 @@ _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
 ;;
@@ -316,11 +401,8 @@ _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
 ;;
@@ -336,7 +418,51 @@ _arguments "${_arguments_options[@]}" : \
         (( CURRENT += 1 ))
         curcontext="${curcontext%:*:*}:exhaustive-help-command-$line[1]:"
         case $line[1] in
-            (action)
+            (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)
 _arguments "${_arguments_options[@]}" : \
 && ret=0
 ;;
@@ -440,6 +566,8 @@ esac
 (( $+functions[_exhaustive_commands] )) ||
 _exhaustive_commands() {
     local commands; commands=(
+'empty:' \
+'global:' \
 'action:' \
 'quote:' \
 'value:' \
@@ -461,9 +589,92 @@ _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:' \
@@ -485,6 +696,36 @@ _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 0f3f1bce..9f7ef238 100644
--- a/clap_complete/tests/testsuite/bash.rs
+++ b/clap_complete/tests/testsuite/bash.rs
@@ -164,12 +164,22 @@ fn complete() {
     let input = "exhaustive \t\t";
     let expected = snapbox::str![[r#"
 % 
--h          --global    --help      action      value       last        hint        
--V          --generate  --version   quote       pacman      alias       help        
+-h              --empty-choice  empty           action          value           last            hint
+--generate      --help          global          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/"];
@@ -260,8 +270,8 @@ fn complete_dynamic_env_toplevel() {
     let input = "exhaustive \t\t";
     let expected = snapbox::str![[r#"
 % 
-action      value       last        hint        --global    --help      
-quote       pacman      alias       help        --generate  --version   
+empty           action          value           last            hint            --generate      --help
+global          quote           pacman          alias           help            --empty-choice  
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -281,9 +291,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        --global           --backslash        --choice
-cmd-double-quotes  cmd-brackets       help               --double-quotes    --brackets         --help
-cmd-backticks      cmd-expansions     --single-quotes    --backticks        --expansions       --version
+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           
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -336,3 +346,37 @@ 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 98f27e59..c9dc59b6 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_static_toplevel() {
+fn complete() {
     if !common::has_command(CMD) {
         return;
     }
@@ -162,22 +162,38 @@ fn complete_static_toplevel() {
 
     let input = "exhaustive \t";
     let expected = snapbox::str![[r#"
-% exhaustive --generate
+% exhaustive --empty-choice
  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);
@@ -203,10 +219,10 @@ fn complete_dynamic_env_toplevel() {
 
     let input = "exhaustive \t";
     let expected = snapbox::str![[r#"
-% exhaustive --generate
+% exhaustive --empty-choice
  COMPLETING argument  
---generate  --help     action  help  last    quote
---global    --version  alias   hint  pacman  value
+--empty-choice  --help  alias  global  hint  pacman  value
+--generate      action  empty  help    last  quote 
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -227,9 +243,9 @@ fn complete_dynamic_env_quoted_help() {
     let expected = snapbox::str![[r#"
 % exhaustive quote --backslash
  COMPLETING argument  
---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             
+--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      
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -294,3 +310,44 @@ 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 590faedc..a788debb 100644
--- a/clap_complete/tests/testsuite/fish.rs
+++ b/clap_complete/tests/testsuite/fish.rs
@@ -163,12 +163,26 @@ fn complete() {
     let input = "exhaustive \t";
     let expected = snapbox::str![[r#"
 % exhaustive 
-action  help  (Print this message or the help of the given subcommand(s))  last    quote
-alias   hint                                                               pacman  value
+action  empty   help  (Print this message or the help of the given subcommand(s))  last    quote
+alias   global  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#"
@@ -198,10 +212,10 @@ fn complete_dynamic_env_toplevel() {
 
     let input = "exhaustive \t\t";
     let expected = snapbox::str![[r#"
-% 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)
+% 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                                                     
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -230,7 +244,6 @@ 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')
@@ -238,7 +251,6 @@ 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);
@@ -293,3 +305,37 @@ 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 757c33f1..13d6a53e 100644
--- a/clap_complete/tests/testsuite/zsh.rs
+++ b/clap_complete/tests/testsuite/zsh.rs
@@ -164,11 +164,22 @@ fn complete() {
     let input = "exhaustive \t";
     let expected = snapbox::str![[r#"
 % exhaustive
-help                                             -- Print this message or the help of the given subcommand(s)         
-pacman  action  alias  value  quote  hint  last  --                                                                   
+help                                                      -- Print this message or the help of the given subcommand(s)
+hint                                                      
+pacman  action  global  alias  value  quote  empty  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]
@@ -192,12 +203,11 @@ fn complete_dynamic_env_toplevel() {
     let input = "exhaustive \t\t";
     let expected = snapbox::str![[r#"
 % exhaustive
---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
+--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           
 "#]];
     let actual = runtime.complete(input, &term).unwrap();
     assert_data_eq!(actual, expected);
@@ -217,9 +227,7 @@ 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]                                                         
@@ -286,3 +294,37 @@ 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);
+}