zsh-autosuggestions/src/async.zsh
Eric Freese 88fe824ddf Add some error handling to async response handler
We only want to read data in case of POLLIN or POLLHUP. Not POLLNVAL or
select error.

We always want to remove the handler, so it doesn't get called in an
infinite loop when error is nval or err.

In zsh source, see main zle event loop in zle_main.c raw_getbyte
function.
2018-07-13 11:26:57 -06:00

54 lines
1.7 KiB
Bash

#--------------------------------------------------------------------#
# Async #
#--------------------------------------------------------------------#
zmodload zsh/system
_zsh_autosuggest_async_request() {
typeset -g _ZSH_AUTOSUGGEST_ASYNC_FD _ZSH_AUTOSUGGEST_CHILD_PID
# If we've got a pending request, cancel it
if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
# Close the file descriptor and remove the handler
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&-
zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD
# Assume the child process created a new process group and send
# TERM to the group to attempt to kill all descendent processes
kill -TERM -$_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
fi
# Fork a process to fetch a suggestion and open a pipe to read from it
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <(
# Tell parent process our pid
echo $sysparams[pid]
# Fetch and print the suggestion
local suggestion
_zsh_autosuggest_fetch_suggestion "$1"
echo -nE "$suggestion"
)
# Read the pid from the child process
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
# When the fd is readable, call the response handler
zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response
}
# Called when new data is ready to be read from the pipe
# First arg will be fd ready for reading
# Second arg will be passed in case of error
_zsh_autosuggest_async_response() {
if [[ -z "$2" || "$2" == "hup" ]]; then
# Read everything from the fd and give it as a suggestion
zle autosuggest-suggest -- "$(cat <&$1)"
# Close the fd
exec {1}<&-
fi
# Always remove the handler
zle -F "$1"
}