Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm
Precedence: bulk
X-No-Archive: yes
List-Id: Zsh Workers List <zsh-workers.zsh.org>
List-Post: <mailto:zsh-workers@zsh.org>
List-Help: <mailto:zsh-workers-help@zsh.org>
X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au
X-Spam-Level: 
X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham
	autolearn_force=no version=3.4.1
Date: Fri, 03 Jun 2016 20:40:43 +0000
From: Daniel Shahaf <d.s@daniel.shahaf.name>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: Re: zle hook conventions (was Re: bracket-paste-magic ...)
Message-ID: <20160603204043.GA18181@tarsus.local2>
References: <20160510085833.GA20332@cventin.lip.ens-lyon.fr>
 <160510125848.ZM1686@torch.brasslantern.com>
 <20160513092348.GB18186@zira.vinc17.org>
 <CAH+w=7YYkto7u1WNcfmTs30o1wVGF4VRwnKmJtFz=5K4iLLp5A@mail.gmail.com>
 <20160513222039.GA2425@tarsus.local2>
 <CAHYJk3S9qPhCByg8T-mrRjgUNBs-ubFCGKDKT7qx9=yGepA8qg@mail.gmail.com>
 <20160514030031.GA2530@tarsus.local2>
 <CAH+w=7aAtxrpcXg8nyGUE1mB1ifczMU1L13g7nqcoMp2f68LYg@mail.gmail.com>
 <20160519211458.GD8007@tarsus.local2>
 <160602000600.ZM14708@torch.brasslantern.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
In-Reply-To: <160602000600.ZM14708@torch.brasslantern.com>
User-Agent: Mutt/1.5.23 (2014-03-12)
X-Seq: zsh-workers 38591

Bart Schaefer wrote on Thu, Jun 02, 2016 at 00:06:00 -0700:
> On May 19,  9:14pm, Daniel Shahaf wrote:
> }
> } Bart Schaefer wrote on Sun, May 15, 2016 at 04:59:27 -0700:
> } > Hence I also think that a plugin registry for the special zle hook
> } > widgets ought to be implemented externally, and the plugins agree to
> } > make use of it -- because if the plugins don't follow such a
> } > convention then the user has to update .zshrc in lockstep with the
> } > plugin installation anyway.
> } 
> } I don't follow your reasoning: whether .zshrc needs to be updated
> } manually is orthogonal to how the plugin hooks into zle.
> 
> If you have two or more plugins referenced from .zshrc, and not all of
> them follow the same convention for how to hook into zle, then any time
> one of them changes the user has to make sure it hasn't now interfered
> with the hooks of the others.
> 

I think it is possible for a plugin to hook into zle without interfering
with other plugins' hooks, without assuming anything about those other
plugins.  z-sy-h's hooking code attempts to achieve that (modulo a known
bug†):

https://github.com/zsh-users/zsh-syntax-highlighting/blob/47144ad9742a948337c6a0e315474b5fea94a6d3/zsh-syntax-highlighting.zsh#L243-L272

That said, I agree that having some an array of functions that are to be
called by a central dispatcher — as with add-zsh-hook and
add-zle-widget-hook — would sidestep this "devise a perfectly composable
wrapper" problem entirely.

> } It is about the mechanism used by zsh to find and run the code that
> } _installs_ the zle hook, not about whether said installation is done
> } by [...]
> 
> That's exactly my point: A convention no one uses is no better than no
> convention at all, even if there's specialty C code instead of shell
> code.
> 

I think you're saying: if one plugin uses add-zle-hook-widget(), then
other plugins can coexist with that plugin by also using
add-zle-hook-widget().

I'm a bit wary of imposing dependencies on other plugins.  Might there
be a valid reason for those fourth-party plugins to prefer not to use
add-zle-hook-widget? 

> Further, an externally-defined convention can be made backward-compatible
> to at least some older versions of zsh.
> 

Good point.

> } I'm happy to keep this external, although if widgets shipped with zsh
> } used this "external" plugin, it'd probably become de facto official.
> 
> Currently there aren't any functions shipped with zsh that would need
> this.  The only references to the zle-* hooks in the shipped code are
> tests for whether zle-line-init is currently in progress, not for using
> any hooks to set up specific behavior.
> 

Currently, no.  However, this subthread started when you mentioned (in
38485) that url-quote-magic considered hooking to zle-line-pre-redraw.

> Crudely sketched, I'm thinking of something like this:
> ⋮
> Usage would be e.g. (inventing a function for example purposes):
> 
>     add-zle-hook-widget zle-line-pre-redraw 30:z-sy-h-redraw
> 
> If you leave out the number: prefix, it's assumed you don't care in
> what order it executes, but it'll always be after the ones that do
> have number prefixes.  Left up to the plugins to work out what number
> they need/get.  Note you can call the same widget more than once by
> adding it with two different numbers.

This appears to be a straightforward registrar API.

I would suggest making this idempotent by uniquifying the list of hooks
(in order to support 'source ~/.zshrc').

With my plugin author perspective, if I were to add a dependency on this
function, I'd want it to be easily available for users to install.
Where would add-zle-hook-widget's implementation live?  In Functions/ in
the zsh tree, or as a third-party project?

> 	zstyle -g extant_hooks "$hook" widgets
> 	extant_hooks+=("$@")
> 	zstyle -- "$hook" widgets "${extant_hooks[@]}"

Why use zstyle's instead of declaring a global array and appending to it?

Many thanks,

Daniel

† The linked excerpt's infinite recursion guard doesn't currently catch
the case that $cur_widget is a user-defined widget and ${widgets[$cur_widget]#user:}
is a function that calls «_zsh_highlight_widget_${cur_widget}»; however,
this should be simple to fix by embedding a nonce (e.g., $EPOCHREALTIME)
in the name of the wrapper functions and widgets.

