1. Insert `-` in `echo -nE "$suggestion"`. This is necessary to prevent
`"$suggestion"` from being treated as an option for `echo`.
2. Close file descriptors only in `_zsh_autosuggest_async_response` to
ensure that each file descriptor is closed only once.
It's the second bug that prompted the fix. The original code in some
cases could close the same file descriptor twice. The code relied on
an invalid assumption that `_zsh_autosuggest_async_response` cannot
fire after the file descriptor is closed. Here's a demo that shows
this assumption being violated:
() {
emulate -L zsh
function callback1() {
zle -I
emulate -L zsh -o xtrace
: "$@"
zle -F $fd1
exec {fd1}>&-
zle -F $fd2
exec {fd2}>&-
}
function callback2() {
zle -I
emulate -L zsh -o xtrace
: "$@"
}
exec {fd1} </dev/null
exec {fd2} </dev/null
zle -F $fd1 callback1
zle -F $fd2 callback2
}
And here's the output I get if the code is pasted into an interactive zsh:
+callback1:3> : 12
+callback1:4> zle -F 12
+callback1:6> zle -F 13
+callback2:3> : 13
Note that `callback2` fires after its file descriptor has been closed
by `callback1`.
This bug was the culprit of several issues filed against powerlevel10k.
In a nutshell:
1. `_zsh_autosuggest_async_request` opens a file.
2. `_zsh_autosuggest_async_request` closes the file descriptor.
3. powerlevel10k opens a file and gets the same file descriptor as above.
4. `_zsh_autosuggest_async_response` fires and closes the same file descriptor.
5. powerlevel10k encounters errors when trying to read from the file descriptor.