Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zsh-syntax-highlighting sends add-zle-hook-widget into an infinite loop #816

Open
marlonrichert opened this issue Jun 6, 2021 · 2 comments

Comments

@marlonrichert
Copy link

marlonrichert commented Jun 6, 2021

Given

  • add-zle-hook-widget <hook> <function> has been called before sourcing zsh-syntax-highlighting.

When

  • we call add-zle-hook-widget <hook> <function> for the same value of <hook> at runtime.

Then

  • azhw:zle-<hook> will go into an infinite loop.

This happens because

  1. zsh-syntax-highlighting makes $widgets[<hook>] equal to user:_zsh_highlight_widget_orig-s<float>-r<integer>-zle-<hook>,
  2. which causes [[ ${widgets[$hook]:-} != "user:azhw:$hook" ]] in add-zle-hook-widget to evaluate to true,
  3. which in turn causes add-zle-hook-widget to add the same widget again to the list,
  4. so that the wrapped zle-<hook> widget now ends up calling itself.

Steps to reproduce :

% cd $(mktemp -d)
% print '
bindkey >/dev/null # Strangely enough, if we dont call bindkey, then the bug never occurs.
foo bar () {}
autoload -Uz add-zle-hook-widget
add-zle-hook-widget line-init foo
source /<path to>/zsh-syntax-highlighting/zsh-syntax-highlighting.plugin.zsh
' > .zshrc
% exec env -i HOME=$PWD TERM=$TERM SHELL=$SHELL $SHELL -d 
% functions -T add-zle-hook-widget
% add-zle-hook-widget line-init bar; functions -T azhw:zle-line-init
+add-zle-hook-widget:1> local -a hooktypes
+add-zle-hook-widget:2> zstyle -a zle-hook types hooktypes
+add-zle-hook-widget:5> local usage='Usage: add-zle-hook-widget hook widgetname\nValid hooks are:\n  isearch-exit isearch-update line-pre-redraw line-init line-finish history-line-set keymap-select'
+add-zle-hook-widget:7> local opt
+add-zle-hook-widget:8> local -a autoopts
+add-zle-hook-widget:9> integer del list help
+add-zle-hook-widget:11> getopts dDhLUzk opt
+add-zle-hook-widget:38> shift 0
+add-zle-hook-widget:40> 1=line-init 
+add-zle-hook-widget:42> ((  list  ))
+add-zle-hook-widget:45> ((  help || 2 != 2 || 4 == 0  ))
+add-zle-hook-widget:50> local -aU extant_hooks
+add-zle-hook-widget:51> local hook=zle-line-init
+add-zle-hook-widget:52> local fn=bar
+add-zle-hook-widget:54> ((  del  ))
+add-zle-hook-widget:71> [[ bar = zle-line-init ]]
+add-zle-hook-widget:81> integer i=3-2
+add-zle-hook-widget:82> zstyle -g extant_hooks zle-line-init widgets
+add-zle-hook-widget:84> [[ user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init != user:azhw:zle-line-init ]]
+add-zle-hook-widget:85> [[ -n user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init ]]
+add-zle-hook-widget:86> zle -A zle-line-init user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init
+add-zle-hook-widget:87> extant_hooks=( 0:user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init 1:foo ) 
+add-zle-hook-widget:89> zle -N zle-line-init azhw:zle-line-init
+add-zle-hook-widget:92> [[ -z '' ]]
+add-zle-hook-widget:95> i=1+1 
+add-zle-hook-widget:99> extant_hooks+=( 2:bar ) 
+add-zle-hook-widget:100> zstyle -- zle-line-init widgets 0:user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init 1:foo 2:bar
+add-zle-hook-widget:101> ((  ! 0  ))
+add-zle-hook-widget:102> autoload -- bar
+add-zle-hook-widget:103> zle -N -- bar
+add-zle-hook-widget:105> ((  ! 1  ))
% +azhw:zle-line-init:1> local -a hook_widgets
+azhw:zle-line-init:2> local hook
+azhw:zle-line-init:5> zstyle -a zle-line-init widgets hook_widgets
+azhw:zle-line-init:6> hook=user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init
+azhw:zle-line-init:7> [[ user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init = user:* ]]
+azhw:zle-line-init:9> zle user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init -N --
+azhw:zle-line-init:1> local -a hook_widgets
+azhw:zle-line-init:2> local hook
+azhw:zle-line-init:5> zstyle -a zle-line-init widgets hook_widgets
+azhw:zle-line-init:6> hook=user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init
+azhw:zle-line-init:7> [[ user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init = user:* ]]
+azhw:zle-line-init:9> zle user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init -N --
+azhw:zle-line-init:1> local -a hook_widgets
+azhw:zle-line-init:2> local hook
+azhw:zle-line-init:5> zstyle -a zle-line-init widgets hook_widgets
+azhw:zle-line-init:6> hook=user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init
+azhw:zle-line-init:7> [[ user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init = user:* ]]
+azhw:zle-line-init:9> zle user:_zsh_highlight_widget_orig-s0.0000030000-r28564-zle-line-init -N --
<...>

[Process completed]
marlonrichert added a commit to marlonrichert/zsh-autocomplete that referenced this issue Jun 6, 2021
@danielshahaf
Copy link
Member

Only affects the non-redrawhook codepath.

Sounds like add-zle-hook-widget should detect this situation?

@marlonrichert
Copy link
Author

All right, I reported it on zsh-workers.

YingchangLiu pushed a commit to YingchangLiu/dotfiles that referenced this issue Aug 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants