Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Unset “zle_bracketed_paste” .zshrc

[tl;dr: See the antepenultimate paragraph.]

Daniel Shahaf wrote on Sat, 18 Jan 2020 19:40:42 +0000:
> Andrew Reyes wrote on Fri, 17 Jan 2020 23:20 +00:00:
> > The problem is: 
> > 1) zsh/zle's setup_() assigns the parameter, overwriting existing values
> > 
> > 2) not possible to 'unset' the parameter before zsh/zle is loaded.
> @Andrew thanks for the report.  Let me spell out the symptoms for the list:
> In zshrc, «typeset -a zle_bracketed_paste=('' '')» and «unset
> zle_bracketed_paste» have no effect if done before zsh/zle has been
> loaded, because of zsh/zle's setup_() unconditionally assigns to the
> parameter, even if it already exists and has a non-null value.
> I looked into this yesterday, and guarding the assignaparam() call with
> a paramtab->getnode() != NULL fixes the case that the variable is
> already set by the time zsh/zle is loaded (e.g., if it's set in zshrc).
> However, I haven't been able to make «unset zle_bracketed_paste»  have
> any lasting effect if done before zsh/zle is loaded.  Is that achievable?

I think it is achievable.

We already have a facility for knowing which parameters will be provided
by not-yet-loaded modules:

    $ zsh -fc 'zmodload -ap; zmodload' | tail
    patchars (zsh/parameter)
    reswords (zsh/parameter)
    saliases (zsh/parameter)
    termcap (zsh/termcap)
    terminfo (zsh/terminfo)
    userdirs (zsh/parameter)
    usergroups (zsh/parameter)
    widgets (zsh/zleparameter)
    zsh_scheduled_events (zsh/sched)

(For those following along at home: the 'autofeatures' array in the
*.mdd file is compiled into a call to the autofeatures() function, which
is done from init_bltinmods() during shell initialization.)

Currently, unsetting a marked-for-autoloading parameter removes all
traces of it:

    $ zsh -fc 'unset aliases; zmodload -ap | grep -w aliases; zmodload'

… but it's silently recreated when the module is actually loaded:

    $ zsh -fc 'unset aliases; zmodload zsh/parameter; echo ${(t)aliases}' 

Because we know which parameters will be provided by modules _before_
those modules are loaded, we can change the behaviour so loading
a module would not create parameters that had been marked autoloadable
and subsequently unset; that is, we can make it so after «unset aliases;
zmodload zsh/parameter» the parameter $aliases would remain unset.
Would this be the Right way to proceed?

Or would it be better to keep the current behaviour and document that modules
must be loaded before parameters provided by them are «unset»?  (In this
case, we could still check whether $zle_bracketed_paste exists before
silently overwriting its zshrc-set value.)

I haven't tried to implement this yet, but what I have in mind is
(1) Make unsetparam_pm() add the PM_UNSET bit if the PM_AUTOLOAD bit is
present; (2) Make module loading, before creating a parameter, check if
there's a Param with PM_UNSET and PM_AUTOLOAD both set; if there is,
rather than create the "real" parameter, delete the tombstone parameter.
(But if there isn't a Param at all, the module _should_ create its special
Param anyway, to allow modules to be unloaded and reloaded in the same
shell session.)



Messages sorted by: Reverse Date, Date, Thread, Author