From 0b8ab3a21a15c12b22f39cd19ce5ef90fdc31ad1 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 19 Jun 2016 19:50:37 -0700 Subject: 38715: add-zle-hook-widget: assorted ksharrays fixes; assign an index to any hook that is added without one, to preserve append ordering --- Functions/Zle/add-zle-hook-widget | 69 ++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 23 deletions(-) (limited to 'Functions') diff --git a/Functions/Zle/add-zle-hook-widget b/Functions/Zle/add-zle-hook-widget index eeb0191f0..608a77607 100644 --- a/Functions/Zle/add-zle-hook-widget +++ b/Functions/Zle/add-zle-hook-widget @@ -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 } -- cgit 1.4.1