1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-01-01 05:16:05 +01:00

38670: New function for managing ZLE special widgets, modeled after Functions/Misc/add-zsh-hook.

This commit is contained in:
Barton E. Schaefer 2016-06-12 18:50:10 -07:00
parent 20948d0889
commit 8e2ec4517f
3 changed files with 200 additions and 2 deletions

View file

@ -1,3 +1,9 @@
2016-06-12 Barton E. Schaefer <schaefer@zsh.org>
* 38670: Doc/Zsh/contrib.yo, Functions/Zle/add-zle-hook-widget:
New function for managing ZLE special widgets, modeled after
Functions/Misc/add-zsh-hook.
2016-06-09 Oliver Kiddle <opk@zsh.org>
* 38579: Functions/Zle/bracketed-paste-magic: simplify saving

View file

@ -292,11 +292,11 @@ cindex(hook function utility)
startitem()
findex(add-zsh-hook)
item(tt(add-zsh-hook) [ tt(-dD) ] [ tt(-Uzk) ] var(hook) var(function))(
item(tt(add-zsh-hook) [ tt(-L) | tt(-dD) ] [ tt(-Uzk) ] var(hook) var(function))(
Several functions are special to the shell, as described in the section
ifnzman(Special Functions, noderef(Functions))\
ifzman(SPECIAL FUNCTIONS, see zmanref(zshmisc)),
in that they are automatic called at a specific point during shell execution.
in that they are automatically called at specific points during shell execution.
Each has an associated array consisting of names of functions to be
called at the same point; these are so-called `hook functions'.
The shell function tt(add-zsh-hook) provides a simple way of adding or
@ -312,6 +312,9 @@ var(function) is name of an ordinary shell function. If no options
are given this will be added to the array of functions to be executed
in the given context.
If the option tt(-L) is given, the current values for the hook arrays
are listed with tt(typeset).
If the option tt(-d) is given, the var(function) is removed from
the array of functions to be executed.
@ -323,6 +326,55 @@ The options tt(-U), tt(-z) and tt(-k) are passed as arguments to
tt(autoload) for var(function). For functions contributed with zsh, the
options tt(-Uz) are appropriate.
)
findex(add-zle-hook-widget)
item(tt(add-zle-hook-widget) [ tt(-L) | tt(-dD) ] [ tt(-Uzk) ] var(hook) var(widgetname))(
Several widget names are special to the line editor, as described in the section
ifnzman(Special Widgets, noderef(Zle Widgets))\
ifzman(Special Widgets, see zmanref(zshzle)),
in that they are automatically called at specific points during editing.
Unlike function hooks, these do not use a predefined array of other names
to call at the same point; the shell function tt(add-zle-hook-widget)
maintains a similar array and arranges for the special widget to invoke
those additional widgets.
var(hook) is one of tt(isearch-exit), tt(isearch-update),
tt(line-pre-redraw), tt(line-init), tt(line-finish), tt(history-line-set),
or tt(keymap-select), corresponding to each of the special widgets
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) -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.
If the option tt(-d) is given, the var(widgename) is removed from
the array of widgets to be executed.
If the option tt(-D) is given, the var(widgetname) is treated as a pattern
and any matching names of widgets are removed from the array.
If var(widgetname) does not name an existing widget when added to the
array, it is assumed that a shell function also named var(widgetname) is
meant to provide the implementation of the widget. This name is therefore
marked for autoloading, and the options tt(-U), tt(-z) and tt(-k) are
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.
)
enditem()
texinode(Recent Directories)(Other Directory Functions)(Utilities)(User Contributions)

View file

@ -0,0 +1,140 @@
# Add to HOOK the given WIDGET
#
# HOOK is one of isearch-exit, isearch-update, line-pre-redraw, line-init,
# line-finish, history-line-set, keymap-select (the zle- prefix is not
# required).
#
# 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.
#
# With -d, remove the widget from the hook instead; delete the hook
# variable if it is empty.
#
# -D behaves like -d, but pattern characters are active in the
# widget name, so any matching widget will be deleted from the hook.
#
# Without -d, if the WIDGET is not already defined, a function having the
# 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.
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"
return 1
}
local -a hooktypes=( isearch-exit isearch-update
line-pre-redraw line-init line-finish
history-line-set keymap-select )
# Stash in zstyle to make it global
zstyle zle-hook types $hooktypes
for hook in $hooktypes
do
function zle-$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
done
return 0
}
done
# Redefine ourself with the setup left out
function add-zle-hook-widget {
local -a hooktypes
zstyle -a zle-hook types hooktypes
# This part copied from add-zsh-hook
local usage="Usage: $0 hook widgetname\nValid hooks are:\n $hooktypes"
local opt
local -a autoopts
integer del list help
while getopts "dDhLUzk" opt; do
case $opt in
(d)
del=1
;;
(D)
del=2
;;
(h)
help=1
;;
(L)
list=1
;;
([Uzk])
autoopts+=(-$opt)
;;
(*)
return 1
;;
esac
done
shift $(( OPTIND - 1 ))
if (( list )); then
zstyle -L "zle-(${1:-${(@j:|:)hooktypes}})" widgets
return $?
elif (( help || $# != 2 || ${hooktypes[(I)${1#zle-}]} == 0 )); then
print -u$(( 2 - help )) $usage
return $(( 1 - help ))
fi
local -aU extant_hooks
local hook="zle-${1#zle-}"
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}}
else
set -A extant_hooks ${extant_hooks:#(<->:|)$fn}
fi
# unset if no remaining entries
if (( ${#extant_hooks} )); then
zstyle "$hook" widgets "${extant_hooks[@]}"
else
zstyle -d "$hook" widgets
fi
fi
else
zstyle -g extant_hooks "$hook" widgets
extant_hooks+=("$fn")
zstyle -- "$hook" widgets "${extant_hooks[@]}"
if [[ -z "${widgets[$fn]}" ]]; then
autoload "${autoopts[@]}" -- "$fn"
zle -N "$fn"
fi
if [[ -z "${widgets[$hook]}" ]]; then
zle -N "$hook"
fi
fi
}
# Handle zsh autoloading conventions
if [[ "$zsh_eval_context" = *loadautofunc && ! -o kshautoload ]]; then
add-zle-hook-widget "$@"
fi