zsh-workers
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: "Zsh Hackers' List" <zsh-workers@zsh.org>
Subject: Re: add-zle-hook-widget Re: Next release (5.3)
Date: Wed, 13 Jul 2016 17:11:52 -0700	[thread overview]
Message-ID: <160713171152.ZM22376@torch.brasslantern.com> (raw)
In-Reply-To: <20160713050011.GA18173@tarsus.local2>

On Jul 13,  5:00am, Daniel Shahaf wrote:
} Subject: add-zle-hook-widget Re: Next release (5.3)
}
} Daniel Shahaf wrote on Thu, Jul 07, 2016 at 02:00:21 +0000:
} > How about including add-zle-hook-widget in 5.3, but without any indices
} > or before:/after: support
} 
} I've heard neither ayes nor nays, so here's a patch we can use if we
} choose this approach.
} 
} Shall we go for this patch then, or something else (what?)?

Other things have required my attention.

Here's a patch to the add-zle-hook-widget function which deletes the
reference to INDEX:NAME syntax and its implementation in the argument
list.  It's still visible in the stored record if you pass the -L
option just so I didn't have to rewrite too much of the rest of the
code and because a future patch might revive it.

This also handles some edge cases, like, what happens if you do

    autoload add-zle-hook-widget
    add-zle-hook-widget zle-line-init some-new-widget
    zle -N zle-line-finish my-line-finish
    add-zle-hook-widget zle-line-finish some-other-widget

Previously the second a-z-h-w would have been ignored because the check
for existing user widgets was only done at the first call.  Now it
checks on each call to see if the user has stepped on it and tries to
do the right thing.

I've also tried to fix the kshautoload handling.  Note that if you're
in the habit of doing goofy stuff like

	unsetopt kshautoload
	autoload -k +X somefunc
	somefunc

then you get what you deserve, i.e., somefunc will run twice the first
time you use it.  In the case of add-zsh-hook-widget, that's harmless.

The contrib.yo file needs to be updated, I wanted first to see whether
anyone spots any obvious problems with this rendition of the function.


diff --git a/Functions/Zle/add-zle-hook-widget b/Functions/Zle/add-zle-hook-widget
index 608a776..760e26d 100644
--- a/Functions/Zle/add-zle-hook-widget
+++ b/Functions/Zle/add-zle-hook-widget
@@ -1,18 +1,15 @@
 # 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).
+# 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.
 #
-# 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.
+# 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 the
-# widget name, so any matching widget will be deleted from the hook.
+# -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
@@ -47,16 +44,15 @@ do
       # and we run them in number order
       zstyle -a $WIDGET widgets hook_widgets
       for hook in "${(@)${(@on)hook_widgets[@]}#<->:}"; do
-	  zle "$hook" -Nw "$@" || return
+	  if [[ "$hook" = user:* ]]; then
+	      # Preserve $WIDGET within the renamed widget
+	      zle "$hook" -N "$@"
+	  else
+	      zle "$hook" -Nw "$@"
+	  fi || 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
@@ -133,17 +129,19 @@ function add-zle-hook-widget {
     else
 	integer i=${#options[ksharrays]}-2
 	zstyle -g extant_hooks "$hook" widgets
-	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
+        # Check for an existing widget, add it as the first hook
+	if [[ ${widgets[$hook]} != "user:azhw:$hook" ]]; then
+	    zle -A "$hook" "${widgets[$hook]}"
+	    extant_hooks=(0:"${widgets[$hook]}" "${extant_hooks[@]}")
+	    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
-	    i=${${(M)fn#<->:}%:}
-	    fn=${fn#<->:}
+	    return 0
 	fi
 	extant_hooks+=("${i}:${fn}")
 	zstyle -- "$hook" widgets "${extant_hooks[@]}"
@@ -157,7 +155,17 @@ function add-zle-hook-widget {
     fi
 }
 
-# Handle zsh autoloading conventions
-if [[ "$zsh_eval_context" = *loadautofunc && ! -o kshautoload ]]; then
-    add-zle-hook-widget "$@"
-fi
+# 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.


  reply	other threads:[~2016-07-14  0:11 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-04 10:40 Peter Stephenson
2016-07-04 15:04 ` Bart Schaefer
2016-07-05  6:00   ` Sebastian Gniazdowski
2016-07-05  6:33     ` Bart Schaefer
2016-07-05  8:33   ` Peter Stephenson
2016-07-05 11:48     ` Peter Stephenson
2016-07-05 16:29       ` Bart Schaefer
2016-07-07  2:00   ` Daniel Shahaf
2016-07-13  5:00     ` add-zle-hook-widget " Daniel Shahaf
2016-07-14  0:11       ` Bart Schaefer [this message]
2016-07-17  1:51         ` Bart Schaefer
2016-07-17 15:00           ` [PATCH] _add-zle-hook-widget: New completion Daniel Shahaf
2016-07-17 19:21             ` Bart Schaefer
2016-07-17 20:40               ` Bart Schaefer
2016-07-17 21:57             ` Bart Schaefer
2016-07-18  9:47             ` Oliver Kiddle
2016-07-18 15:30               ` Bart Schaefer
2016-07-19 10:30                 ` Oliver Kiddle
2016-07-19 17:58                   ` Bart Schaefer
2016-07-20  6:54               ` [PATCH v2] " Daniel Shahaf
2016-07-21 15:28                 ` Oliver Kiddle
2016-07-22  6:22                   ` Daniel Shahaf
2016-07-22 18:21                     ` Bart Schaefer
2016-07-22 18:45                     ` Oliver Kiddle
2016-07-23 18:03                       ` Daniel Shahaf
2016-07-17 14:59         ` add-zle-hook-widget Re: Next release (5.3) Daniel Shahaf
2016-07-17 18:48           ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=160713171152.ZM22376@torch.brasslantern.com \
    --to=schaefer@brasslantern.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).