From b3dba0f7c1e2accb18dcdb8d6329b4d6a8a568e8 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 17 Jul 2016 12:07:43 -0700 Subject: Relocate add-zle-hook-widget, everything else in Functions/Zle is a widget. --- Functions/Misc/add-zle-hook-widget | 186 +++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 Functions/Misc/add-zle-hook-widget (limited to 'Functions/Misc/add-zle-hook-widget') diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget new file mode 100644 index 000000000..04be50478 --- /dev/null +++ b/Functions/Misc/add-zle-hook-widget @@ -0,0 +1,186 @@ +# 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 allowed +# but not required). If a widget corresponding to HOOK already exists, it +# is preserved and called first in the new set of HOOK widgets. +# +# With -d, remove the WIDGET from the hook instead; deletes the hook +# linkage if it is empty. +# +# -D behaves like -d, but pattern characters are active in WIDGET, 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. +# +# The -L option lists the hooks and their associated widgets. + +() { # Preserve caller global option settings + +emulate -L zsh + +# 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 +} + +# 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#zle-} + +# Relying on multifuncdef option here +function azhw:${^hooktypes} { + local -a hook_widgets + local hook + # Values of these styles look like number:name + # and we run them in number order + zstyle -a $WIDGET widgets hook_widgets + for hook in "${(@)${(@on)hook_widgets[@]}#<->:}"; do + if [[ "$hook" = user:* ]]; then + # Preserve $WIDGET within the renamed widget + zle "$hook" -N "$@" + else + zle "$hook" -Nw "$@" + fi || return + done + return 0 +} + +# 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 )) + + 1=${1#zle-} # Strip prefix not stored in zle-hook types style + + if (( list )); then + zstyle -L "zle-(${1:-${(@j:|:)hooktypes[@]}})" widgets + return $? + 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" + 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 + # Check whether attempting to add a widget named for the hook + if [[ "$fn" = "$hook" ]]; then + if [[ -n "${widgets[$fn]}" ]]; then + print -u2 "Cannot hook $fn to itself" + return 1 + fi + # No point in building the array until another is added + autoload "${autoopts[@]}" -- "$fn" + zle -N "$fn" + return 0 + fi + integer i=${#options[ksharrays]}-2 + zstyle -g extant_hooks "$hook" widgets + # Check for an existing widget, add it as the first hook + if [[ ${widgets[$hook]} != "user:azhw:$hook" ]]; then + if [[ -n ${widgets[$hook]} ]]; then + zle -A "$hook" "${widgets[$hook]}" + extant_hooks=(0:"${widgets[$hook]}" "${extant_hooks[@]}") + fi + zle -N "$hook" azhw:"$hook" + fi + # Add new widget only if not already in the hook list + if [[ -z ${(M)extant_hooks[@]:#(<->:|)$fn} ]]; then + # no index and not already hooked + # assign largest existing index plus 1 + i=${${(On@)${(@M)extant_hooks[@]#<->:}%:}[i]}+1 + else + return 0 + fi + extant_hooks+=("${i}:${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" azhw:"$hook" + fi + fi +} + +} "$@" # Resume caller global options + +# Handle zsh autoloading conventions: +# - "file" appears last in zsh_eval_context when "source"-ing +# - "evalautofunc" appears with kshautoload set or autoload -k +# - "loadautofunc" appears with kshautoload unset or autoload -z +# - use of autoload +X cannot reliably be detected, use best guess +case "$zsh_eval_context" in +*file) ;; +*evalautofunc) ;; +*loadautofunc) add-zle-hook-widget "$@";; +*) [[ -o kshautoload ]] || add-zle-hook-widget "$@";; +esac +# Note fallback here is equivalent to the usual best-guess used by +# functions written for zsh before $zsh_eval_context was available +# so this case-statement is backward-compatible. -- cgit v1.2.3 From 74722c7392ae95069df6966b1194d3e10320f3de Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 27 Jul 2016 14:04:44 +0000 Subject: unposted: Prefix function's name to its error messages. --- ChangeLog | 3 +++ Functions/Misc/add-zle-hook-widget | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'Functions/Misc/add-zle-hook-widget') diff --git a/ChangeLog b/ChangeLog index 15fe53b70..bf74cbe3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-07-27 Daniel Shahaf + * unposted: Functions/Misc/add-zle-hook-widget: Prefix function's + name to its error messages. + * unposted (after 38939): Completion/Unix/Command/_git: _git-rebase: Unbreak. diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget index 04be50478..82a404d7a 100644 --- a/Functions/Misc/add-zle-hook-widget +++ b/Functions/Misc/add-zle-hook-widget @@ -25,7 +25,7 @@ emulate -L zsh # 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" + print -u2 "add-zle-hook-widget: Need parameter modules for zle hooks" return 1 } @@ -130,7 +130,7 @@ function add-zle-hook-widget { # Check whether attempting to add a widget named for the hook if [[ "$fn" = "$hook" ]]; then if [[ -n "${widgets[$fn]}" ]]; then - print -u2 "Cannot hook $fn to itself" + print -u2 "${0}: Cannot hook $fn to itself" return 1 fi # No point in building the array until another is added -- cgit v1.2.3 From 8e029323a76b48cdbeeb03045e2fc6348e2b060b Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 28 Jul 2016 18:01:36 +0000 Subject: unposted: Avoid $0 for POSIX_ARGZERO compatibility. --- ChangeLog | 6 ++++++ Functions/Misc/add-zle-hook-widget | 4 ++-- Functions/Misc/add-zsh-hook | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'Functions/Misc/add-zle-hook-widget') diff --git a/ChangeLog b/ChangeLog index 1d68cf75d..9153ff197 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2016-07-28 Daniel Shahaf + + * unposted: Functions/Misc/add-zle-hook-widget, + Functions/Misc/add-zsh-hook: Avoid $0 for POSIX_ARGZERO + compatibility. + 2016-07-28 Oliver Kiddle * 38957: Functions/Zle/select-word-match, diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget index 82a404d7a..c47d9a3cb 100644 --- a/Functions/Misc/add-zle-hook-widget +++ b/Functions/Misc/add-zle-hook-widget @@ -62,7 +62,7 @@ function add-zle-hook-widget { 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 usage="Usage: $funcstack[1] hook widgetname\nValid hooks are:\n $hooktypes" local opt local -a autoopts @@ -130,7 +130,7 @@ function add-zle-hook-widget { # Check whether attempting to add a widget named for the hook if [[ "$fn" = "$hook" ]]; then if [[ -n "${widgets[$fn]}" ]]; then - print -u2 "${0}: Cannot hook $fn to itself" + print -u2 "$funcstack[1]: Cannot hook $fn to itself" return 1 fi # No point in building the array until another is added diff --git a/Functions/Misc/add-zsh-hook b/Functions/Misc/add-zsh-hook index fc39659ae..3bc952e2f 100644 --- a/Functions/Misc/add-zsh-hook +++ b/Functions/Misc/add-zsh-hook @@ -19,7 +19,7 @@ hooktypes=( chpwd precmd preexec periodic zshaddhistory zshexit zsh_directory_name ) -local usage="Usage: $0 hook function\nValid hooks are:\n $hooktypes" +local usage="Usage: add-zsh-hook hook function\nValid hooks are:\n $hooktypes" local opt local -a autoopts -- cgit v1.2.3 From 70166178bdc7ea149eb1cd29bcdb549a392c46dd Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Tue, 30 Aug 2016 20:31:21 -0700 Subject: 39131: return on error needs to be at the outer scope. --- ChangeLog | 5 +++++ Functions/Misc/add-zle-hook-widget | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'Functions/Misc/add-zle-hook-widget') diff --git a/ChangeLog b/ChangeLog index 866e2add1..2f8f5b7a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,11 @@ * 39122: Completion/Unix/Command/_git: __git_recent_branches: Silence warning on an edge case. +2016-08-30 Barton E. Schaefer + + * 39131: Functions/Misc/add-zle-hook-widget: return on error + needs to be at the outer scope. + 2016-08-30 Daniel Shahaf * 39108: Completion/Unix/Command/_postfix: Support diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget index c47d9a3cb..572de2561 100644 --- a/Functions/Misc/add-zle-hook-widget +++ b/Functions/Misc/add-zle-hook-widget @@ -18,10 +18,6 @@ # # The -L option lists the hooks and their associated widgets. -() { # Preserve caller global option settings - -emulate -L zsh - # This is probably more safeguarding than necessary zmodload -e zsh/zle || return 1 { zmodload zsh/parameter && zmodload zsh/zleparameter } || { @@ -29,6 +25,10 @@ zmodload -e zsh/zle || return 1 return 1 } +() { # Preserve caller global option settings + +emulate -L zsh + # Setup - create the base functions for hook widgets that call the others local -a hooktypes=( zle-isearch-exit zle-isearch-update -- cgit v1.2.3 From 4f2a1810f2fa1d74008e03a09d66eaff3e5edc9e Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 29 Sep 2016 09:50:09 +0000 Subject: 39495: add-zle-hook-widget: Add end-of-options guard to hook invocation. Currently, the only special widget that takes arguments is zle-keymap-select. --- ChangeLog | 3 +++ Doc/Zsh/contrib.yo | 2 +- Functions/Misc/add-zle-hook-widget | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'Functions/Misc/add-zle-hook-widget') diff --git a/ChangeLog b/ChangeLog index 9df255631..b1b000025 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-09-30 Daniel Shahaf + * 39495: Doc/Zsh/contrib.yo, Functions/Misc/add-zle-hook-widget: + add-zle-hook-widget: Add end-of-options guard to hook invocation. + * 39480: Completion/Debian/Command/_bug: _reportbug: Complete absolute filenames, too. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 63df292ac..189a084ba 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -346,7 +346,7 @@ as the var(hook) argument. 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 -example(tt(zle )var(widgetname)tt( -Nw "$@")) +example(tt(zle )var(widgetname)tt( -Nw -- "$@")) vindex(WIDGET, in hooks) Note that this means that the `tt(WIDGET)' special parameter tracks the diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget index 572de2561..d8a3950fb 100644 --- a/Functions/Misc/add-zle-hook-widget +++ b/Functions/Misc/add-zle-hook-widget @@ -47,9 +47,9 @@ function azhw:${^hooktypes} { for hook in "${(@)${(@on)hook_widgets[@]}#<->:}"; do if [[ "$hook" = user:* ]]; then # Preserve $WIDGET within the renamed widget - zle "$hook" -N "$@" + zle "$hook" -N -- "$@" else - zle "$hook" -Nw "$@" + zle "$hook" -Nw -- "$@" fi || return done return 0 -- cgit v1.2.3