fix(zsh): use decorated widget for rendering tooltips

This commit is contained in:
L. Yeung 2024-07-15 10:59:13 +08:00 committed by Jan De Dobbeleer
parent 908c9eafac
commit ec2c6fb2d8

View file

@ -76,31 +76,29 @@ autoload -Uz add-zsh-hook
add-zsh-hook precmd prompt_ohmyposh_precmd add-zsh-hook precmd prompt_ohmyposh_precmd
add-zsh-hook preexec prompt_ohmyposh_preexec add-zsh-hook preexec prompt_ohmyposh_preexec
# perform cleanup so a new initialization in current session works # Prevent incorrect behaviors when the initialization is executed twice in current session.
if [[ "$(bindkey " ")" = *"_posh-tooltip"* ]]; then function _omp_cleanup() {
bindkey " " self-insert local omp_widgets=(
fi self-insert
if [[ "$(zle -lL zle-line-init)" = *"_posh-zle-line-init"* ]]; then zle-line-init
zle -N zle-line-init )
fi local widget
for widget in "${omp_widgets[@]}"; do
function _posh-tooltip() { if [[ "${widgets[_omp_original::$widget]}" ]]; then
# https://github.com/zsh-users/zsh-autosuggestions - clear suggestion to avoid keeping it after the newly inserted space # Restore the original widget.
if [[ "$(zle -lL autosuggest-clear)" ]]; then zle -A _omp_original::$widget $widget
# only if suggestions not disabled (variable not set) elif [[ "${widgets[$widget]}" = user:_omp_* ]]; then
if [[ ! -v _ZSH_AUTOSUGGEST_DISABLED ]]; then # Delete the OMP-defined widget.
zle autosuggest-clear zle -D $widget
fi
fi fi
done
}
_omp_cleanup
unset -f _omp_cleanup
zle .self-insert function _omp_render_tooltip() {
if [[ "$KEYS" != ' ' ]]; then
# https://github.com/zsh-users/zsh-autosuggestions - fetch new suggestion after the space return
if [[ "$(zle -lL autosuggest-fetch)" ]]; then
# only if suggestions not disabled (variable not set)
if [[ ! -v _ZSH_AUTOSUGGEST_DISABLED ]]; then
zle autosuggest-fetch
fi
fi fi
# Get the first word of command line as tip. # Get the first word of command line as tip.
@ -121,7 +119,7 @@ function _posh-tooltip() {
zle .reset-prompt zle .reset-prompt
} }
function _posh-zle-line-init() { function _omp_zle-line-init() {
[[ $CONTEXT == start ]] || return 0 [[ $CONTEXT == start ]] || return 0
# Start regular line editor. # Start regular line editor.
@ -149,69 +147,53 @@ function _posh-zle-line-init() {
return ret return ret
} }
function enable_poshtooltips() { # Helper function for calling a widget before the specified OMP function.
zle -N _posh-tooltip function _omp_call_widget() {
bindkey " " _posh-tooltip # The name of the OMP function.
local omp_func=$1
# The remainder are the widget to call and potential arguments.
shift
zle "$@" && shift 2 && $omp_func "$@"
} }
# Helper function for posh::decorate_widget # Create a widget with the specified OMP function.
# It calls the posh function right after the original definition of the widget # An existing widget will be preserved and decorated with the function.
# $1 is the posh widget name function _omp_create_widget() {
# $2.. are the name of the widget to call + potential args # The name of the widget to create/decorate.
posh::call_widget() local widget=$1
{ # The name of the OMP function.
local posh_widget=$1;shift local omp_func=$2
builtin zle "${@}" &&
${posh_widget}
}
# decorate_widget case ${widgets[$widget]:-''} in
# Allows to preserve any user defined value that may have been defined before posh tries to redefine it.
# Instead, we keep the previous function and decorate it with the posh additions
# $1: The name of the widget to decorate
# $2: The name of the posh function to decorate it with
function posh::decorate_widget() {
orig_widget=${1};shift
posh_widget=${1};shift
# from this point $@ does not have $1 $2 anymore
case ${widgets[$orig_widget]:-""} in
# Already decorated: do nothing. # Already decorated: do nothing.
user:_posh-decorated-*);; user:_omp_decorated_*) ;;
# User defined # Non-existent: just create it.
user:*) '')
zle -N $POSH_PID-$orig_widget ${widgets[$orig_widget]#*:} zle -N $widget $omp_func
eval "_posh-decorated-${(q)POSH_PID}-${(q)orig_widget}() { posh::call_widget ${(q)posh_widget} ${(q)POSH_PID}-${(q)orig_widget} -- \"\$@\" }" ;;
zle -N $orig_widget _posh-decorated-$POSH_PID-$orig_widget;;
# Built-in # User-defined or builtin: backup and decorate it.
builtin:*)
eval "_posh-decorated-${(q)POSH_PID}-${(q)orig_widget}() { posh::call_widget ${(q)posh_widget} .${(q)orig_widget} -- \"\$@\" }"
zle -N $orig_widget _posh-decorated-$POSH_PID-$orig_widget;;
# non-existent
*) *)
if [[ $orig_widget == zle-* ]] && (( ! ${+widgets[$orig_widget]} )); then # Back up the original widget.
# The widget is a zle one and does not exist, we can safely create it zle -A $widget _omp_original::$widget
# Otherwise, do nothing eval "_omp_decorated_${(q)widget}() { _omp_call_widget ${(q)omp_func} _omp_original::${(q)widget} -- \"\$@\" }"
eval "_posh-decorated-${(q)POSH_PID}-${(q)orig_widget}() { ${(q)posh_widget} }" zle -N $widget _omp_decorated_$widget
zle -N $orig_widget _posh-decorated-$POSH_PID-$orig_widget
fi
;; ;;
esac esac
} }
function enable_poshtransientprompt() { # legacy functions
posh::decorate_widget zle-line-init _posh-zle-line-init function enable_poshtooltips() {}
} function enable_poshtransientprompt() {}
if [[ "::TOOLTIPS::" = "true" ]]; then if [[ "::TOOLTIPS::" = "true" ]]; then
enable_poshtooltips _omp_create_widget self-insert _omp_render_tooltip
fi fi
if [[ "::TRANSIENT::" = "true" ]]; then if [[ "::TRANSIENT::" = "true" ]]; then
enable_poshtransientprompt _omp_create_widget zle-line-init _omp_zle-line-init
fi fi
if [[ "::UPGRADE::" = "true" ]]; then if [[ "::UPGRADE::" = "true" ]]; then