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

Issue:
Parentheses in doc comments for `ValueEnum` break generated fish completions
### Please complete the following tasks

- [X] I have searched the [discussions](https://github.com/clap-rs/clap/discussions)
- [X] I have searched the [open](https://github.com/clap-rs/clap/issues) and [rejected](https://github.com/clap-rs/clap/issues?q=is%3Aissue+label%3AS-wont-fix+is%3Aclosed) issues

### Rust Version

rustc 1.72.0 (5680fa18f 2023-08-23)

### Clap Version

4.4.1

### Minimal reproducible code

```rust
use clap::CommandFactory;

#[derive(clap::Parser)]
struct MyCommand {
    #[arg(long)]
    color: Color,
}

#[derive(Clone, clap::ValueEnum)]
enum Color {
    /// do something (default)
    Auto,
    /// do not use colorized output
    Never,
}

fn main() {
    clap_complete::generate(
        clap_complete::shells::Fish,
        &mut MyCommand::command(),
        "ls",
        &mut std::io::stdout(),
    );
}
```


### Steps to reproduce the bug with the above code

```fish
$ cargo run | source
$ ls --color=<TAB>
```

### Actual Behaviour

```fish
$ ls --color=<TAB>fish: Unknown command: default
fish: 
default
^~~~~~^
in command substitution
```

### Expected Behaviour

```fish
$ ls --color=<TAB>
--color=auto  (show colors if the output goes to an interactive console (default))
--color=never                                        (do not use colorized output)
```

### Additional Context

The solution might just be to escape parentheses in `clap_complete::shells::Fish::escape_string`. But A) I'm not sure if there are unintended consequences of doing that and B) the docs for that function mention that it's for escaping single quoted strings which the completions don't use. But it's also used in `value_completion` to escape a string inside double quotes so maybe that comment is just out-of-date? I didn't feel confident making the change so I'll defer to someone more knowledgeable.

### Debug Output

_No response_


Discussion / hints:
I would like to work on this @epage. Please assign this to me.
Below is my analysis so far:
The `complete` command that `clap_complete` generates for @cstyles's example, for fish shell is this:
```bash
complete -c ls -l color -r -f -a "{auto	do something (default)}"
```
If I go through fish shell's [documentation](https://fishshell.com/docs/current/completions.html#completion-own), I don't see any mention of adding description/hint in the `-a` flag itself. The flag `-d` suits the purpose. So, if I compose the following command:
```bash
complete -c ls -l color -r -f -a auto -d "do something (default)"
```
And then try the auto-completion:
```bash
$ ls --color=<TAB>
```
I get the expected output:
```bash
--color=always  (Use colors)  --color=auto  (do something (default))  --color=never  (Use colors)
```
without any errors. I will do some more analysis with multiple parameters and their description. From the face value, it seems like separate `complete` command will be required for parameters that have a description/hint with them. If that is the case, this might be a bigger change/fix than anticipated.
I don't think it's _required_ that we use separate `complete` commands, though that might be a good idea. The relevant bit from that documentation page is this:

> Each line of output is used as a separate candidate, and anything after a tab is taken as the description.

Which is what `clap_complete` is using:

https://github.com/clap-rs/clap/blob/dc63cba772ab1d1a2b977acedd08af2b3baa6692/clap_complete/src/shells/fish.rs#L171-L175

The problem is this, emphasis mine:

> The argument to the -a switch is always a single string. At completion time, it will be tokenized on spaces and tabs, and variable expansion, *command substitution* and other forms of parameter expansion will take place.

I tried a couple different approaches but I think the simplest solution is to wrap the description in single quotes and ditch the comma-escaping. For me, that prevents any expansion inside the description and doesn't require any complicated escaping.

```diff
diff --git a/clap_complete/src/shells/fish.rs b/clap_complete/src/shells/fish.rs
index 5a069d35..175ae6aa 100644
--- a/clap_complete/src/shells/fish.rs
+++ b/clap_complete/src/shells/fish.rs
@@ -169,9 +169,9 @@ fn value_completion(option: &Arg) -> String {
                     None
                 } else {
                     Some(format!(
-                        "{}\t{}",
+                        "{}\t'{}'",
                         escape_string(value.get_name(), true).as_str(),
-                        escape_string(&value.get_help().unwrap_or_default().to_string(), true)
+                        escape_string(&value.get_help().unwrap_or_default().to_string(), false)
                     ))
                 })
                 .collect::<Vec<_>>()
```
Valid point @cstyles. I tried few more variations with your solution. Here are my observations:
✓
```bash
$ complete -c ls -l color -r -f -a "{auto\t'do something (default)',never\t'no color',always\t'always color'}"
$ ls --color=<TAB>
--color=always  (always color)  --color=auto  (do something (default))  --color=never  (no color)
```
✕ - I believe this is expected, so this case is fine?
```bash
$ complete -c ls -l color -r -f -a "{auto\t'do something %$# (default)',never\t'no &* color',always\t'always!! color'}"
$ ls --color=<TAB>
fish: $# is not supported. In fish, please use 'count $argv'.
complete -c ls -l color -r -f -a "{auto\t'do something %$# (default)',never\t'no &* color',always\t'always!! color'}"
```
✕ - Same as the previous one.
```bash
$ complete -c ls -l color -r -f -a "{auto\t'do something %$ (default)',never\t'no &* color',always\t'always!! color'}"
$ ls --color=<TAB>
fish: $  is not a valid variable in fish.
complete -c ls -l color -r -f -a "{auto\t'do something %$ (default)',never\t'no &* color',always\t'always!! color'}"
```
✓
```bash
$ complete -c ls -l color -r -f -a "{auto\t'do something % (default)',never\t'no &* color',always\t'always!! color'}"
$ ls --color=<TAB>
--color=always  (always!! color)  --color=auto  (do something % (default))  --color=never  (no &* color)
```

So, in summary, the solution to enclose the help text in `''` , without `,` escaping, should work! I will fix.

Fix patch:
diff --git a/clap_complete/examples/exhaustive.rs b/clap_complete/examples/exhaustive.rs
index f9110490e05..de00da622a1 100644
--- a/clap_complete/examples/exhaustive.rs
+++ b/clap_complete/examples/exhaustive.rs
@@ -1,3 +1,4 @@
+use clap::builder::PossibleValue;
 #[cfg(feature = "unstable-dynamic")]
 use clap::{FromArgMatches, Subcommand};
 use clap_complete::{generate, Generator, Shell};
@@ -88,6 +89,14 @@ fn cli() -> clap::Command {
                         .long("expansions")
                         .action(clap::ArgAction::SetTrue)
                         .help("Execute the shell command with $SHELL"),
+                    clap::Arg::new("choice")
+                        .long("choice")
+                        .action(clap::ArgAction::Set)
+                        .value_parser(clap::builder::PossibleValuesParser::new([
+                            PossibleValue::new("bash").help("bash (shell)"),
+                            PossibleValue::new("fish").help("fish shell"),
+                            PossibleValue::new("zsh").help("zsh shell"),
+                        ])),
                 ])
                 .subcommands([
                     clap::Command::new("cmd-single-quotes")
diff --git a/clap_complete/src/shells/fish.rs b/clap_complete/src/shells/fish.rs
index 5a069d35b56..7dae5b6d6e8 100644
--- a/clap_complete/src/shells/fish.rs
+++ b/clap_complete/src/shells/fish.rs
@@ -168,10 +168,12 @@ fn value_completion(option: &Arg) -> String {
                 .filter_map(|value| if value.is_hide_set() {
                     None
                 } else {
+                    // The help text after \t is wrapped in '' to make sure that the it is taken literally
+                    // and there is no command substitution or variable expansion resulting in unexpected errors
                     Some(format!(
-                        "{}\t{}",
+                        "{}\t'{}'",
                         escape_string(value.get_name(), true).as_str(),
-                        escape_string(&value.get_help().unwrap_or_default().to_string(), true)
+                        escape_string(&value.get_help().unwrap_or_default().to_string(), false)
                     ))
                 })
                 .collect::<Vec<_>>()


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 a843c90ee31..f28713111d7 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/bash/.bashrc
@@ -732,12 +732,16 @@ _exhaustive() {
             return 0
             ;;
         exhaustive__quote)
-            opts="-h -V --single-quotes --double-quotes --backticks --backslash --brackets --expansions --global --help --version 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
             fi
             case "${prev}" in
+                --choice)
+                    COMPREPLY=($(compgen -W "bash fish zsh" -- "${cur}"))
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
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 3e596f7f242..e403bd8310f 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
@@ -48,6 +48,7 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
             cand --version 'Print version'
         }
         &'exhaustive;quote'= {
+            cand --choice 'choice'
             cand --single-quotes 'Can be ''always'', ''auto'', or ''never'''
             cand --double-quotes 'Can be "always", "auto", or "never"'
             cand --backticks 'For more information see `echo test`'
@@ -55,8 +56,8 @@ set edit:completion:arg-completer[exhaustive] = {|@words|
             cand --brackets 'List packages [filter]'
             cand --expansions 'Execute the shell command with $SHELL'
             cand --global 'everywhere'
-            cand -h 'Print help'
-            cand --help 'Print help'
+            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'''
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 47b42f4a4d4..e9558b91118 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,4 +1,4 @@
-complete -c exhaustive -n "__fish_use_subcommand" -l generate -d 'generate' -r -f -a "{bash	,elvish	,fish	,powershell	,zsh	}"
+complete -c exhaustive -n "__fish_use_subcommand" -l generate -d 'generate' -r -f -a "{bash	'',elvish	'',fish	'',powershell	'',zsh	''}"
 complete -c exhaustive -n "__fish_use_subcommand" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_use_subcommand" -s h -l help -d 'Print help'
 complete -c exhaustive -n "__fish_use_subcommand" -s V -l version -d 'Print version'
@@ -12,12 +12,13 @@ complete -c exhaustive -n "__fish_use_subcommand" -f -a "hint"
 complete -c exhaustive -n "__fish_use_subcommand" -f -a "complete" -d 'Register shell completions for this program'
 complete -c exhaustive -n "__fish_use_subcommand" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
 complete -c exhaustive -n "__fish_seen_subcommand_from action" -l set -d 'value' -r
-complete -c exhaustive -n "__fish_seen_subcommand_from action" -l choice -d 'enum' -r -f -a "{first	,second	}"
+complete -c exhaustive -n "__fish_seen_subcommand_from action" -l choice -d 'enum' -r -f -a "{first	'',second	''}"
 complete -c exhaustive -n "__fish_seen_subcommand_from action" -l set-true -d 'bool'
 complete -c exhaustive -n "__fish_seen_subcommand_from action" -l count -d 'number'
 complete -c exhaustive -n "__fish_seen_subcommand_from action" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_seen_subcommand_from action" -s h -l help -d 'Print help'
 complete -c exhaustive -n "__fish_seen_subcommand_from action" -s V -l version -d 'Print version'
+complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from escape-help; and not __fish_seen_subcommand_from help" -l choice -r -f -a "{bash	'bash (shell)',fish	'fish shell',zsh	'zsh shell'}"
 complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from escape-help; and not __fish_seen_subcommand_from help" -l single-quotes -d 'Can be \'always\', \'auto\', or \'never\''
 complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from escape-help; and not __fish_seen_subcommand_from help" -l double-quotes -d 'Can be "always", "auto", or "never"'
 complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from escape-help; and not __fish_seen_subcommand_from help" -l backticks -d 'For more information see `echo test`'
@@ -25,7 +26,7 @@ complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_see
 complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from escape-help; and not __fish_seen_subcommand_from help" -l brackets -d 'List packages [filter]'
 complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from escape-help; and not __fish_seen_subcommand_from help" -l expansions -d 'Execute the shell command with $SHELL'
 complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from escape-help; and not __fish_seen_subcommand_from help" -l global -d 'everywhere'
-complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from escape-help; and not __fish_seen_subcommand_from help" -s h -l help -d 'Print help'
+complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from escape-help; and not __fish_seen_subcommand_from help" -s h -l help -d 'Print help (see more with \'--help\')'
 complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from escape-help; and not __fish_seen_subcommand_from help" -s V -l version -d 'Print version'
 complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from escape-help; and not __fish_seen_subcommand_from help" -f -a "cmd-single-quotes" -d 'Can be \'always\', \'auto\', or \'never\''
 complete -c exhaustive -n "__fish_seen_subcommand_from quote; and not __fish_seen_subcommand_from cmd-single-quotes; and not __fish_seen_subcommand_from cmd-double-quotes; and not __fish_seen_subcommand_from cmd-backticks; and not __fish_seen_subcommand_from cmd-backslash; and not __fish_seen_subcommand_from cmd-brackets; and not __fish_seen_subcommand_from cmd-expansions; and not __fish_seen_subcommand_from escape-help; and not __fish_seen_subcommand_from help" -f -a "cmd-double-quotes" -d 'Can be "always", "auto", or "never"'
@@ -95,7 +96,7 @@ complete -c exhaustive -n "__fish_seen_subcommand_from alias" -s f -s F -l flag
 complete -c exhaustive -n "__fish_seen_subcommand_from alias" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_seen_subcommand_from alias" -s h -l help -d 'Print help'
 complete -c exhaustive -n "__fish_seen_subcommand_from alias" -s V -l version -d 'Print version'
-complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l choice -r -f -a "{bash	,fish	,zsh	}"
+complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l choice -r -f -a "{bash	'',fish	'',zsh	''}"
 complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l unknown -r
 complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l other -r -f
 complete -c exhaustive -n "__fish_seen_subcommand_from hint" -s p -l path -r -F
@@ -111,7 +112,7 @@ complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l email -r -f
 complete -c exhaustive -n "__fish_seen_subcommand_from hint" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_seen_subcommand_from hint" -s h -l help -d 'Print help'
 complete -c exhaustive -n "__fish_seen_subcommand_from hint" -s V -l version -d 'Print version'
-complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l shell -d 'Specify shell to complete for' -r -f -a "{bash	,fish	}"
+complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l shell -d 'Specify shell to complete for' -r -f -a "{bash	'',fish	''}"
 complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l register -d 'Path to write completion-registration to' -r -F
 complete -c exhaustive -n "__fish_seen_subcommand_from complete" -l global -d 'everywhere'
 complete -c exhaustive -n "__fish_seen_subcommand_from complete" -s h -l help -d 'Print help (see more with \'--help\')'
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 2c8b30e6c61..82e68ced2e9 100644
--- a/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive
+++ b/clap_complete/tests/snapshots/home/static/exhaustive/zsh/zsh/_exhaustive
@@ -45,6 +45,9 @@ _arguments "${_arguments_options[@]}" \
 ;;
 (quote)
 _arguments "${_arguments_options[@]}" \
+'--choice=[]: :((bash\:"bash (shell)"
+fish\:"fish shell"
+zsh\:"zsh shell"))' \
 '--single-quotes[Can be '\''always'\'', '\''auto'\'', or '\''never'\'']' \
 '--double-quotes[Can be "always", "auto", or "never"]' \
 '--backticks[For more information see \`echo test\`]' \
@@ -52,8 +55,8 @@ _arguments "${_arguments_options[@]}" \
 '--brackets[List packages \[filter\]]' \
 '--expansions[Execute the shell command with \$SHELL]' \
 '--global[everywhere]' \
-'-h[Print help]' \
-'--help[Print help]' \
+'-h[Print help (see more with '\''--help'\'')]' \
+'--help[Print help (see more with '\''--help'\'')]' \
 '-V[Print version]' \
 '--version[Print version]' \
 ":: :_exhaustive__quote_commands" \
diff --git a/clap_complete/tests/snapshots/sub_subcommands.fish b/clap_complete/tests/snapshots/sub_subcommands.fish
index f0eccd7c061..cec51a63a1f 100644
--- a/clap_complete/tests/snapshots/sub_subcommands.fish
+++ b/clap_complete/tests/snapshots/sub_subcommands.fish
@@ -11,7 +11,7 @@ complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and not __fish_seen
 complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -s V -l version -d 'Print version'
 complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "sub_cmd" -d 'sub-subcommand'
 complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
-complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -l config -d 'the other case to test' -r -f -a "{Lest quotes\, aren\'t escaped.	help\,with\,comma,Second to trigger display of options	}"
+complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -l config -d 'the other case to test' -r -f -a "{Lest quotes\, aren\'t escaped.	'help,with,comma',Second to trigger display of options	''}"
 complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -s h -l help -d 'Print help (see more with \'--help\')'
 complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -s V -l version -d 'Print version'
 complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from sub_cmd; and not __fish_seen_subcommand_from help" -f -a "sub_cmd" -d 'sub-subcommand'
diff --git a/clap_complete/tests/snapshots/value_hint.fish b/clap_complete/tests/snapshots/value_hint.fish
index 17fbb849925..27cd24bbaa1 100644
--- a/clap_complete/tests/snapshots/value_hint.fish
+++ b/clap_complete/tests/snapshots/value_hint.fish
@@ -1,4 +1,4 @@
-complete -c my-app -l choice -r -f -a "{bash	,fish	,zsh	}"
+complete -c my-app -l choice -r -f -a "{bash	'',fish	'',zsh	''}"
 complete -c my-app -l unknown -r
 complete -c my-app -l other -r -f
 complete -c my-app -s p -l path -r -F
diff --git a/clap_complete/tests/testsuite/fish.rs b/clap_complete/tests/testsuite/fish.rs
index 49656a5cb47..68388991e6c 100644
--- a/clap_complete/tests/testsuite/fish.rs
+++ b/clap_complete/tests/testsuite/fish.rs
@@ -142,6 +142,12 @@ action  complete            (Register shell completions for this program)  hint
 alias   help  (Print this message or the help of the given subcommand(s))  last  quote"#;
     let actual = runtime.complete(input, &term).unwrap();
     snapbox::assert_eq(expected, actual);
+
+    let input = "exhaustive quote --choice \t";
+    let actual = runtime.complete(input, &term).unwrap();
+    let expected = r#"% exhaustive quote --choice
+bash  (bash (shell))  fish  (fish shell)  zsh  (zsh shell)"#;
+    snapbox::assert_eq(expected, actual);
 }
 
 #[cfg(all(unix, feature = "unstable-dynamic"))]