mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-10-29 05:21:00 +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:
		
							parent
							
								
									25ae250068
								
							
						
					
					
						commit
						0b8ab3a21a
					
				
					 3 changed files with 69 additions and 36 deletions
				
			
		|  | @ -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 | ||||
|  |  | |||
|  | @ -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() | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue