# 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