fix(z): prevent stack overflow from recursive Tab binding on re-source

The ZLE widget added in #13710 saves the current Tab binding and
delegates to it. If the plugin is sourced more than once, the saved
binding points to the widget itself, causing infinite recursion and
"maximum nested function level reached" errors on any Tab press.

Guard against self-reference by only capturing the binding on first
load and falling back to expand-or-complete if the saved value is
our own widget.

Fixes #13714

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mahesh Subramanian 2026-04-27 12:53:33 -07:00
commit a4f13aec98

View file

@ -960,8 +960,15 @@ add-zsh-hook chpwd _zshz_chpwd
(( ${fpath[(ie)${0:A:h}]} <= ${#fpath} )) || fpath=( "${0:A:h}" "${fpath[@]}" ) (( ${fpath[(ie)${0:A:h}]} <= ${#fpath} )) || fpath=( "${0:A:h}" "${fpath[@]}" )
# Save the existing Tab binding # Save the existing Tab binding (only on first load to avoid self-reference
# if the plugin is sourced more than once)
if [[ -z ${ZSHZ[TAB_BINDING]} ]] || \
[[ ${ZSHZ[TAB_BINDING]} == _zshz_zle_completion_widget ]]; then
ZSHZ[TAB_BINDING]="${$(bindkey -M main '^I')##* }" ZSHZ[TAB_BINDING]="${$(bindkey -M main '^I')##* }"
# If we somehow captured our own widget (race condition), fall back to default
[[ ${ZSHZ[TAB_BINDING]} == _zshz_zle_completion_widget ]] && \
ZSHZ[TAB_BINDING]=expand-or-complete
fi
############################################################ ############################################################
# ZLE widget to fix spaces-as-wildcards completion # ZLE widget to fix spaces-as-wildcards completion