1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-01-01 05:16:05 +01: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

@ -1,3 +1,9 @@
2016-06-19 Barton E. Schaefer <schaefer@brasslantern.com>
* 38715: Doc/Zsh/contrib.yo, Functions/Zle/add-zle-hook-widget:
assorted ksharrays fixes; assign an index to any hook that is
added without one, to preserve append ordering
2016-06-18 Barton E. Schaefer <schaefer@zsh.org>
* unposted: Functions/Misc/zed: localoptions noksharrays

View file

@ -345,14 +345,16 @@ tt(zle-isearch-exit), etc.
var(widgetname) is the name of a ZLE widget. If no options are given this
is added to the array of widgets to be invoked in the given hook context.
Note that the hooks are called as widgets, that is, with
`tt(zle )var(widgetname)tt( -Nw)' rather than as a function call.
example(tt(zle )var(widgetname)tt( -Nw "$@"))
rather than as a function call.
The arrays of var(widgetname) are maintained in several tt(zstyle)
contexts, one for each var(hook) context, with a style of `tt(widgets)'.
If the tt(-L) option is given, this set of styles is listed with
`tt(zstyle -L)'. These styles may be updated directly with tt(zstyle)
commands, but the special widgets that refer to the styles are created
only if tt(add-zle-hook-widget) is called to add at least one widget.
In typical usage, var(widgetname) has the form var(index)tt(:)var(name).
In this case var(index) is an integer which determines the order in which
the widget var(name) will be called relative to other widgets in the
array. Widgets having the same var(index) are called in unspecified
order. However, var(widgetname) may omit the index, in which case an
index is computed for it to arrange for it to be called in the order
in which it was added to the array.
If the option tt(-d) is given, the var(widgename) is removed from
the array of widgets to be executed.
@ -368,12 +370,14 @@ passed as arguments to tt(autoload) as with tt(add-zsh-hook). The
widget is also created with `tt(zle -N )var(widgetname)' to cause the
corresponding function to be loaded the first time the hook is called.
In addition, var(widgetname) may be of the form var(index)tt(:)var(name).
In this case var(index) is an integer which determines the order in
which the widget var(name) will be called relative to other widgets in
the array. Widgets having the same var(index) are called in unspecified
order, and all widgets declared with an index are called before any
widgets that have no index.
The arrays of var(widgetname) are currently maintained in tt(zstyle)
contexts, one for each var(hook) context, with a style of `tt(widgets)'.
If the tt(-L) option is given, this set of styles is listed with
`tt(zstyle -L)'. This implementation may change, and the special widgets
that refer to the styles are created only if tt(add-zle-hook-widget) is
called to add at least one widget, so if this function is used for any
hooks, then all hooks should be managed only via this function.
)
enditem()

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
}