summary refs log tree commit diff
path: root/Functions
diff options
context:
space:
mode:
authorBarton E. Schaefer <schaefer@zsh.org>2016-06-19 19:50:37 -0700
committerBarton E. Schaefer <schaefer@zsh.org>2016-06-19 19:50:37 -0700
commit0b8ab3a21a15c12b22f39cd19ce5ef90fdc31ad1 (patch)
treebc3bf73dc2f702e9b6ce1c0cef2d5a6810016c05 /Functions
parent25ae250068134eb87d8be1bd9aeee1590918d120 (diff)
downloadzsh-0b8ab3a21a15c12b22f39cd19ce5ef90fdc31ad1.tar.gz
zsh-0b8ab3a21a15c12b22f39cd19ce5ef90fdc31ad1.tar.xz
zsh-0b8ab3a21a15c12b22f39cd19ce5ef90fdc31ad1.zip
38715: add-zle-hook-widget: assorted ksharrays fixes; assign an index to any hook that is added without one, to preserve append ordering
Diffstat (limited to 'Functions')
-rw-r--r--Functions/Zle/add-zle-hook-widget69
1 files changed, 46 insertions, 23 deletions
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
 }