zellij-autolock icon indicating copy to clipboard operation
zellij-autolock copied to clipboard

Not working with fzf-history-widget when pressing ctrl+r

Open oca159 opened this issue 1 year ago • 3 comments

zellij --version: 0.41.1

Terminal version: wezterm 20240203-110809-5046fc22

Operating system: OS X

Issue description

It works well with fzf except with the keybinding CTRL+R to see the history

Minimal reproduction

brew install fzf Add source <(fzf --zsh) to .zshrc source ~/.zshrc

Then press Ctrl+R and zellij autolock doesn't work

Other relevant information

oca159 avatar Dec 12 '24 19:12 oca159

After spending several hours troubleshooting and with the help of ChatGPT, I discovered that the issue was caused by the fzf-history-widget using a subshell.

To address this, I modified the widget to avoid using a subshell for storing the selected value. Instead, I ensured that fzf runs as a foreground process rather than in the background. Here's the updated code in case it helps someone else:

I edited the widget code in /opt/homebrew/opt/fzf/shell/key-bindings.zsh to use read -r selected instead of a subshell:

Please let me know if there is a better way to fix it, I don't have experience with bash scripting.

fzf-history-widget() {
  local selected
  setopt localoptions noglobsubst noposixbuiltins pipefail no_aliases noglob nobash_rematch 2> /dev/null
  
  # Ensure the associative history array is loaded, and Perl is installed for multi-line support.
  if zmodload -F zsh/parameter p:history 2>/dev/null && (( ${#commands[perl]} )); then
    printf '%s\t%s\000' "${(kv)history[@]}" |
      perl -0 -ne 'if (!$seen{(/^\s*[0-9]+\**\t(.*)/s, $1)}++) { s/\n/\n\t/g; print; }' |
      FZF_DEFAULT_OPTS=$(__fzf_defaults "" "-n2..,.. --scheme=history --bind=ctrl-r:toggle-sort --wrap-sign '\t↳ ' --highlight-line ${FZF_CTRL_R_OPTS-} --query=${(qqq)LBUFFER} +m --read0") \
      FZF_DEFAULT_OPTS_FILE='' $(__fzfcmd) | read -r selected

  else
    # Use a temporary file to capture fzf output
    fc -rl 1 | awk '{ cmd=$0; sub(/^[ \t]*[0-9]+\**[ \t]+/, "", cmd); if (!seen[cmd]++) print $0 }' |
      FZF_DEFAULT_OPTS=$(__fzf_defaults "" "-n2..,.. --scheme=history --bind=ctrl-r:toggle-sort --wrap-sign '\t↳ ' --highlight-line ${FZF_CTRL_R_OPTS-} --query=${(qqq)LBUFFER} +m") \
      FZF_DEFAULT_OPTS_FILE='' fzf | read -r selected
  fi

  # Handle the result
  local ret=$?
  if [ -n "$selected" ]; then
    if [[ $(awk '{print $1; exit}' <<< "$selected") =~ ^[1-9][0-9]*$ ]]; then
      zle vi-fetch-history -n $MATCH
    else
      LBUFFER="$selected"
    fi
  fi

  zle reset-prompt
  return $ret
}



oca159 avatar Dec 13 '24 02:12 oca159

Another way to resolve this issue is by adding support for handling subshell processes to the plugin.

oca159 avatar Dec 13 '24 02:12 oca159

Thanks for sharing your solution. I use atuin, so I've never encountered this.

This plugin can only evaluate what is returned by Zellij, which is N/A in this case.

Using the Ctrl r mapping below, you can disable the autolock mechanism and immediately enter locked mode. But this requires explicitly re-enabling the autolock after you've made your selection (not cool).

normal {
     bind "Ctrl r" {
         WriteChars "\u{0012}";  // Passthru `Ctrl+r`
         MessagePlugin "autolock" {payload "disable";};// Disable the autolock plugin.
         SwitchToMode "Locked";
     }
}

Note that it's also possible to toggle the plugin from the shell:

zellij pipe --name autolock -- [enable|disable|toggle]

and toggle the lock status using:

zellij action switch-mode [locked|normal]

I tried to figure out another approach, but gave up. Thanks for sharing.

fresh2dev avatar Dec 13 '24 09:12 fresh2dev