Repository: junegunn/fzf (language: go)

Issue:
Broken zsh shell integration on 0.51+
### Checklist

- [X] I have read through the manual page (`man fzf`)
- [X] I have searched through the existing issues
- [X] For bug reports, I have checked if the bug is reproducible in the latest version of fzf

### Output of `fzf --version`

0.53.0 (c4a9ccd)

### OS

- [X] Linux
- [ ] macOS
- [ ] Windows
- [ ] Etc.

### Shell

- [ ] bash
- [X] zsh
- [ ] fish

### Problem / Steps to reproduce

Shell integration appears to be broken on early 5.x.x releases of zsh, starting from from fzf version 0.51.0.

I am using a locked system where zsh version cannot be changed:
```
% zsh --version
zsh 5.0.2 (x86_64-redhat-linux-gnu)
% ./fzf --version
0.53.0 (c4a9ccd)
% source <(./fzf --zsh)
% vi **<TAB>
vi **__fzf_generic_path_completion:export:23: not an identifier: 40%
```

The last fzf version which supports this version of zsh is `0.50.0 (f97d275)`.


Discussion / hints:
> The last fzf version which supports this version of zsh is `0.50.0 (f97d275)`

I believe the issue has been introduced through commit f864f8b5f7ab62e81fbf9eb2ac2333c7e52bb4e4.

I can confirm the problem occurs with any version up to **5.1**, and the change was implemented in a commit[^1], which introduced improved assignment handling in **zsh** for builtin commands such as `export`.

### zsh-5.0.2 ❌
```sh
❯ ~/.local/zsh-test/bin/zsh-5.0.2 -fxvc 'export TEST=$(echo "--height 40% --reverse --scheme=path")'
+zsh:1> echo '--height 40% --reverse --scheme=path'
+zsh:1> export 'TEST=--height' 40% --reverse '--scheme=path'
zsh:export:1: not an identifier: 40%
```

### zsh-5.1 ✅
```sh
❯ ~/.local/zsh-test/bin/zsh-5.1 -fxvc 'export TEST=$(echo "--height 40% --reverse --scheme=path")'
export TEST=$(echo "--height 40% --reverse --scheme=path")
+zsh:1> echo '--height 40% --reverse --scheme=path'
+zsh:1> export TEST='--height 40% --reverse --scheme=path'
```

---

Does splitting declaration and assignment solve the issue for you?

```diff
--- a/shell/completion.zsh
+++ b/shell/completion.zsh
@@ -158,5 +158,6 @@ __fzf_generic_path_completion() {
       [ "$dir" != "/" ] && dir="${dir/%\//}"
       matches=$(
-        export FZF_DEFAULT_OPTS=$(__fzf_defaults "--reverse --scheme=path" "${FZF_COMPLETION_OPTS-}")
+        export FZF_DEFAULT_OPTS
+        FZF_DEFAULT_OPTS=$(__fzf_defaults "--reverse --scheme=path" "${FZF_COMPLETION_OPTS-}")
         unset FZF_DEFAULT_COMMAND FZF_DEFAULT_OPTS_FILE
         if declare -f "$compgen" > /dev/null; then
```

[^1]: [sourceforge.net/p/zsh/code/ci/39b28980f](https://sourceforge.net/p/zsh/code/ci/39b28980f38e83e15cdeb19a489b5659af97fe93)



Fix patch:
diff --git a/shell/completion.zsh b/shell/completion.zsh
index 3634a0b19f2..aa03468e47a 100644
--- a/shell/completion.zsh
+++ b/shell/completion.zsh
@@ -157,7 +157,9 @@ __fzf_generic_path_completion() {
       [ -z "$dir" ] && dir='.'
       [ "$dir" != "/" ] && dir="${dir/%\//}"
       matches=$(
-        export FZF_DEFAULT_OPTS=$(__fzf_defaults "--reverse --scheme=path" "${FZF_COMPLETION_OPTS-}")
+        # Declare and assign separately for older zsh versions.
+        export FZF_DEFAULT_OPTS
+        FZF_DEFAULT_OPTS=$(__fzf_defaults "--reverse --scheme=path" "${FZF_COMPLETION_OPTS-}")
         unset FZF_DEFAULT_COMMAND FZF_DEFAULT_OPTS_FILE
         if declare -f "$compgen" > /dev/null; then
           eval "$compgen $(printf %q "$dir")" | __fzf_comprun "$cmd" ${(Q)${(Z+n+)fzf_opts}} -q "$leftover"
@@ -264,13 +266,14 @@ _fzf_complete_telnet() {
 # The first and the only argument is the LBUFFER without the current word that contains the trigger.
 # The current word without the trigger is in the $prefix variable passed from the caller.
 _fzf_complete_ssh() {
-  local tokens=(${(z)1})
+  local -a tokens
+  tokens=(${(z)1})
   case ${tokens[-1]} in
     -i|-F|-E)
       _fzf_path_completion "$prefix" "$1"
       ;;
     *)
-      local user=
+      local user
       [[ $prefix =~ @ ]] && user="${prefix%%@*}@"
       _fzf_complete +m -- "$@" < <(__fzf_list_hosts | awk -v user="$user" '{print user $0}')
       ;;


Test patch: