summaryrefslogtreecommitdiff
path: root/Functions/Zle
diff options
context:
space:
mode:
authorBarton E. Schaefer <schaefer@zsh.org>2016-06-12 18:50:10 -0700
committerBarton E. Schaefer <schaefer@zsh.org>2016-06-12 18:50:10 -0700
commit8e2ec4517fcce11475d579abb827d851f858d9aa (patch)
treec7ecc032aedf12600bcc144cc8f14907ab4a96e1 /Functions/Zle
parent20948d088994dc7b26a26b94926432985fa6863e (diff)
downloadzsh-8e2ec4517fcce11475d579abb827d851f858d9aa.tar.gz
zsh-8e2ec4517fcce11475d579abb827d851f858d9aa.zip
38670: New function for managing ZLE special widgets, modeled after Functions/Misc/add-zsh-hook.
Diffstat (limited to 'Functions/Zle')
-rw-r--r--Functions/Zle/add-zle-hook-widget140
1 files changed, 140 insertions, 0 deletions
diff --git a/Functions/Zle/add-zle-hook-widget b/Functions/Zle/add-zle-hook-widget
new file mode 100644
index 000000000..eeb0191f0
--- /dev/null
+++ b/Functions/Zle/add-zle-hook-widget
@@ -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