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

Re: A serious bug in execution – where to debug?

On Wed, Jul 31, 2019 at 1:41 PM Sebastian Gniazdowski
<sgniazdowski@xxxxxxxxx> wrote:
> I'm not sure if this will not be "honest specification" (that is) "is
> tightly tied to their implementation
> details", but somewhat user-observable effects of zplugin unload
> procedure "described in theory" are:
> [...]

When users are told they can unload plugins without restarting ZSH,
they hear the following story. Normally, to disable a plugin you must
remove it from your ~/.zshrc and restart ZSH. But if you are using
zplugin you can achieve the same result without restarting your ZSH
simply by typing a command.

This is an easy-to-understand feature. If it could be implemented, it
would be mildly useful. Unfortunately, it cannot be implemented even
for simple plugins.

Suppose I have three plugins specified in ~/.zshrc called foo, bar and
baz, and they are loaded in the specified order. I want to unload foo.
That is, I want to get the same shell state that I would get if I
removed foo from ~/.zshrc and restarted ZSH. While loading, foo
defined an alias for grep: alias grep='grep --color=auto'. When foo is
unloaded, this alias is unset, and this causes two unexpected
consequences. The first is that when I type `grep` in my prompt I get
output without colors. The second is that calling a function from bar
produces colorful output. Once I restart zsh with just bar and baz in
~/.zshrc, these cases swap: interactive grep is colorful while a
function in bar isn't.

How is this possible?

  foo.zsh:  alias grep='grep --color=auto'
  bar.zsh:  function bar() { grep hello <<<hello }
  baz.zsh  alias grep='grep --color=auto'

You can get the same problems when reverting changes to any resource
with a shared name: aliases, traps, options, widgets. All code that
ran after the plugin you are attempting could've been affected by the
value you are reverting.

Removing widgets is very likely to break your prompt due to the way
widgets are commonly hooked. When a decent plugin wants to hook a zle
widget, it will copy the previous widget and install its own. The
installed widget will do something and call the previous widget. Now,
if *this* widget gets wrapped too, and you remove it, the chain of
hooks is broken. All plugins that have wrapped that widget before
won't be called. Plugins that have wrapped the widget after will spew

> I think that it's actually possible to predict to a large extent by
> looking at the list of unload-actions.

You can predict which aliases will be unset and which widgets removed
but you cannot predict how it will affect shell. Things can break a
little or a lot. Things may look OK but do damage behind the scenes.


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