1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-25 17:20:25 +02:00

38715: add-zle-hook-widget: assorted ksharrays fixes; assign an index to any hook that is added without one, to preserve append ordering

This commit is contained in:
Barton E. Schaefer 2016-06-19 19:50:37 -07:00
parent 25ae250068
commit 0b8ab3a21a
3 changed files with 69 additions and 36 deletions

View file

@ -6,6 +6,7 @@
#
# WIDGET may be of the form INDEX:NAME in which case the INDEX determines
# the order in which the widget executes relative to other hook widgets.
# Othewise the widget is assigned an index that appends it to the array.
#
# With -d, remove the widget from the hook instead; delete the hook
# variable if it is empty.
@ -17,38 +18,45 @@
# same name is marked for autoload; -U is passed down to autoload if that
# is given, as are -z and -k. (This is harmless if the function is
# already defined.) The WIDGET is then created with zle -N.
#
# The -L option lists the hooks and their associated widgets.
emulate -L zsh
# Setup - create the base functions for hook widgets that call the others
zmodload zsh/parameter || {
print -u2 "Need parameter module for zle hooks"
# This is probably more safeguarding than necessary
zmodload -e zsh/zle || return 1
{ zmodload zsh/parameter && zmodload zsh/zleparameter } || {
print -u2 "Need parameter modules for zle hooks"
return 1
}
local -a hooktypes=( isearch-exit isearch-update
line-pre-redraw line-init line-finish
history-line-set keymap-select )
# Setup - create the base functions for hook widgets that call the others
local -a hooktypes=( zle-isearch-exit zle-isearch-update
zle-line-pre-redraw zle-line-init zle-line-finish
zle-history-line-set zle-keymap-select )
# Stash in zstyle to make it global
zstyle zle-hook types $hooktypes
zstyle zle-hook types ${hooktypes#zle-}
for hook in $hooktypes
do
function zle-$hook {
function azhw:$hook {
local -a hook_widgets
local hook
# Values of these styles look like number:name
# and we run them in number order
# $funcstack is more reliable than $0
# Also, ksh_arrays is annoying
emulate zsh -c 'zstyle -a $funcstack[2] widgets hook_widgets'
for hook in "${@${(@on)hook_widgets}#*:}"
do
zle "$hook" -Nw || return
zstyle -a $WIDGET widgets hook_widgets
for hook in "${(@)${(@on)hook_widgets[@]}#<->:}"; do
zle "$hook" -Nw "$@" || return
done
return 0
}
# Check for an existing widget, add it as the first hook
if [[ ${widgets[$hook]} = user:* ]]; then
zle -A "$hook" "${widgets[$hook]}"
zstyle -- "$hook" widgets 0:"${widgets[$hook]}"
zle -N "$hook" azhw:"$hook"
fi
done
# Redefine ourself with the setup left out
@ -93,25 +101,27 @@ function add-zle-hook-widget {
done
shift $(( OPTIND - 1 ))
1=${1#zle-} # Strip prefix not stored in zle-hook types style
if (( list )); then
zstyle -L "zle-(${1:-${(@j:|:)hooktypes}})" widgets
zstyle -L "zle-(${1:-${(@j:|:)hooktypes[@]}})" widgets
return $?
elif (( help || $# != 2 || ${hooktypes[(I)${1#zle-}]} == 0 )); then
elif (( help || $# != 2 || ${hooktypes[(I)$1]} == 0 )); then
print -u$(( 2 - help )) $usage
return $(( 1 - help ))
fi
local -aU extant_hooks
local hook="zle-${1#zle-}"
local hook="zle-$1"
local fn="$2"
if (( del )); then
# delete, if hook is set
if zstyle -g extant_hooks "$hook" widgets; then
if (( del == 2 )); then
set -A extant_hooks ${extant_hooks:#(<->:|)${~fn}}
set -A extant_hooks ${extant_hooks[@]:#(<->:|)${~fn}}
else
set -A extant_hooks ${extant_hooks:#(<->:|)$fn}
set -A extant_hooks ${extant_hooks[@]:#(<->:|)$fn}
fi
# unset if no remaining entries
if (( ${#extant_hooks} )); then
@ -121,15 +131,28 @@ function add-zle-hook-widget {
fi
fi
else
integer i=${#options[ksharrays]}-2
zstyle -g extant_hooks "$hook" widgets
extant_hooks+=("$fn")
if [[ "$fn" != <->:* ]]; then
if [[ -z ${(M)extant_hooks[@]:#(<->:|)$fn} ]]; then
# no index and not already hooked
# assign largest existing index plus 10
i=${${(On@)${(@M)extant_hooks[@]#<->:}%:}[i]}+10
else
return 0
fi
else
i=${${(M)fn#<->:}%:}
fn=${fn#<->:}
fi
extant_hooks+=("${i}:${fn}")
zstyle -- "$hook" widgets "${extant_hooks[@]}"
if [[ -z "${widgets[$fn]}" ]]; then
autoload "${autoopts[@]}" -- "$fn"
zle -N "$fn"
zle -N -- "$fn"
fi
if [[ -z "${widgets[$hook]}" ]]; then
zle -N "$hook"
zle -N "$hook" azhw:"$hook"
fi
fi
}