mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-10-31 18:10:56 +01:00 
			
		
		
		
	38670: New function for managing ZLE special widgets, modeled after Functions/Misc/add-zsh-hook.
This commit is contained in:
		
							parent
							
								
									20948d0889
								
							
						
					
					
						commit
						8e2ec4517f
					
				
					 3 changed files with 200 additions and 2 deletions
				
			
		|  | @ -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 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
							
								
								
									
										140
									
								
								Functions/Zle/add-zle-hook-widget
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								Functions/Zle/add-zle-hook-widget
									
										
									
									
									
										Normal 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 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue