fzf icon indicating copy to clipboard operation
fzf copied to clipboard

Selection lost when reload action is involved

Open gulash007 opened this issue 5 months ago • 3 comments

Checklist

  • [x] I have read through the manual page (man fzf)
  • [x] I have searched through the existing issues
  • [x] For bug reports, I have checked if the bug is reproducible in the latest version of fzf

Output of fzf --version

0.65.1 (e5cd7f0a)

OS

  • [ ] Linux
  • [x] macOS
  • [ ] Windows
  • [ ] Etc.

Shell

  • [ ] bash
  • [x] zsh
  • [ ] fish

Problem / Steps to reproduce

Hello, I have a problem with losing all selections on reload followed by any selecting action (select-all, toggle,…).

printf "%s\n" 1 2 3 | bin/fzf --multi --bind 'esc:reload(printf "%s\n" 1 2 3)+select-all' 
  • The selections happen - they just flicker and disappear.
  • Tried it also with reload-sync with the same result.
  • Same result with older version 0.56.3 (add1aec).
  • I noticed that when I add any action after reload(-sync) it's executed immediately (it doesn't wait for reload to finish). I'm pretty sure this is expected but how can I ensure that some actions are invoked only after the list is complete?
  • Tried using experimental state JSON to only output select-all from transform when "reading" is false but it got stuck on true despite "progress" being 100.

gulash007 avatar Aug 11 '25 04:08 gulash007

I've always wondered about the order of the execution of actions. It's not always clear which actions are blocking and which are not, and sometimes I'm not sure if they execute in order or concurrently.

For your immediate issue, I found this to work (but is not ideal):

printf "%s\n" 1 2 3 | fzf --multi --bind 'esc:reload(printf "%s\n" 1 2 3)+bg-transform(sleep 0.01; echo select-all)'

jaydee-coder avatar Aug 12 '25 09:08 jaydee-coder

Everything is synchronous (blocking), except for reload, because loading of the input list is inherently asynchronous. This is also true for reload-sync. The "sync" part means that it replaces the list at once after the reload process is complete, it doesn't block fzf during the process.

To deal with the asynchronous nature of loading, you can bind actions to the load event:

printf "%s\n" 1 2 3 | fzf --multi --bind 'esc:reload(printf "%s\n" 1 2 3),load:select-all'

But load also fires on the initial input, so you may need a way to suppress it until the next reload. This is one way to do it using unbind and rebind:

printf "%s\n" 1 2 3 | fzf --multi --bind 'start:unbind(load),esc:rebind(load)+reload(printf "%s\n" 1 2 3),load:select-all'

I know this is not the most straightforward or ergonomic way to implement things, but it is how it is. I'm open to suggestions. Some ideas.

  • Implement a truly synchronous version of gg that blocks everything until the command is complete and fzf finished consuming the output (this is probably my least favorite).
  • Add reload event to complement the load event.
  • ...

junegunn avatar Aug 12 '25 10:08 junegunn

See also:

  • https://github.com/junegunn/fzf/issues/2441
  • https://github.com/junegunn/fzf/issues/4409

Iron-E avatar Aug 14 '25 13:08 Iron-E