From 40e025a0f801a81634c5789a6e0900cf479149a5 Mon Sep 17 00:00:00 2001 From: nikolay Date: Sat, 2 May 2026 11:50:14 -0700 Subject: [PATCH] fix(zsh): clear autosuggestions POSTDISPLAY on forge-accept-line zsh-autosuggestions wraps widgets listed in ZSH_AUTOSUGGEST_CLEAR_WIDGETS during its one-shot bind pass, so the wrapper can reset POSTDISPLAY (the gray inline suggestion) before the widget fires. The default list includes accept-line and friends but not forge-accept-line, because the latter doesn't exist yet when autosuggestions binds. Under a standard OMZ setup the load order is: 1. OMZ sources plugins -> zsh-autosuggestions runs its bind pass -> wraps accept-line, accept-and-hold, etc. 2. Later in .zshrc: eval "$(forge zsh plugin)" -> defines and binds forge-accept-line on ^M / ^J. After step 2 pressing Enter routes to an unwrapped widget, POSTDISPLAY is never cleared visually, and the ghost suggestion lingers on the screen overlapping the next prompt. Fix: append forge-accept-line to ZSH_AUTOSUGGEST_CLEAR_WIDGETS at the end of bindings.zsh (right after the widget is registered and bound) and re-invoke _zsh_autosuggest_bind_widgets so the wrapper is installed. The block is a safe no-op when autosuggestions isn't loaded, when the widget is already registered (idempotent), and works with older autosuggestions releases that lack the _zsh_autosuggest_bind_widgets helper. Verified with a stand-alone zsh harness that covers: - happy path: widget registered and bind_widgets re-invoked - idempotence: re-sourcing doesn't duplicate the entry - graceful no-op when ZSH_AUTOSUGGEST_CLEAR_WIDGETS is unset - works when _zsh_autosuggest_bind_widgets function is absent Closes #3243 Co-Authored-By: ForgeCode --- shell-plugin/lib/bindings.zsh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/shell-plugin/lib/bindings.zsh b/shell-plugin/lib/bindings.zsh index 432d0cb421..c34aa7fb64 100644 --- a/shell-plugin/lib/bindings.zsh +++ b/shell-plugin/lib/bindings.zsh @@ -43,3 +43,25 @@ bindkey '^M' forge-accept-line bindkey '^J' forge-accept-line # Update the Tab binding to use the new completion widget bindkey '^I' forge-completion # Tab for both @ and :command completion + +# Integrate with zsh-autosuggestions. +# +# zsh-autosuggestions wraps widgets listed in ZSH_AUTOSUGGEST_CLEAR_WIDGETS, +# ZSH_AUTOSUGGEST_ACCEPT_WIDGETS, etc. so it can clear POSTDISPLAY (the gray +# inline suggestion) before the widget runs. The wrapping happens once, when +# autosuggestions loads. If Forge's plugin is sourced *after* autosuggestions +# (the Oh-My-Zsh default when users follow `forge zsh setup`), our +# forge-accept-line widget is defined too late to be wrapped, and the inline +# suggestion lingers on the screen after the user presses Enter. +# +# Fix: append forge-accept-line to ZSH_AUTOSUGGEST_CLEAR_WIDGETS and re-run +# the bind pass so the wrapper is installed. Safe no-op when autosuggestions +# is not loaded or when the widget is already registered. +if typeset -p ZSH_AUTOSUGGEST_CLEAR_WIDGETS >/dev/null 2>&1; then + if [[ ${ZSH_AUTOSUGGEST_CLEAR_WIDGETS[(Ie)forge-accept-line]} -eq 0 ]]; then + ZSH_AUTOSUGGEST_CLEAR_WIDGETS+=(forge-accept-line) + if typeset -f _zsh_autosuggest_bind_widgets >/dev/null 2>&1; then + _zsh_autosuggest_bind_widgets + fi + fi +fi