fzf icon indicating copy to clipboard operation
fzf copied to clipboard

cursor position reset in raw mode

Open DarioDarko opened this issue 3 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.66.0 (8cdfb23d)

OS

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

Shell

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

Problem / Steps to reproduce

ive been testing the new raw mode, really great addition to fzf 👍️

however i came across this issue: if you use raw mode with --bind result:best (re)loading fzfs input resets the cursor position to the very first entry

# cursor on 2nd entry
fzf --bind 'load:pos(2)'

# cursor on 1st entry
fzf --bind 'load:pos(2)' --raw --bind result:best

this also happens every time you use reload or reload-sync, the cursor jumps to pos(1). after trying some options i found this workaround:

# doesnt work for setting initial cursor position
# but prevents cursor position from resetting on reload
fzf --bind 'load:pos(2)' --raw --bind result:best \
--bind 'load:unbind(result)' --bind 'change:rebind(result)' --bind 'ctrl-r:reload(ls)'

this is probably related to another issue im having:

when changing the query (quickly) there seems to be some kind of visual flicker, the first entry is highlighted for a split second. this also is solved by the workaround of un- and rebinding result

string="one
two
three"

# flicker
printf "%s" "$string" \
| fzf --raw --bind result:best --color current-bg:white

# no flicker
printf "%s" "$string" \
| fzf --raw --bind result:best --color current-bg:white \
--bind 'load:unbind(result)' --bind 'change:rebind(result)' 

to reproduce use the # flicker code above, type 't' and then quickly type and remove 'h' (to make the selection switch between 'two' and 'three'). the highlight sometimes hits 'one' for a few miliseconds, which causes the flicker

DarioDarko avatar Oct 18 '25 13:10 DarioDarko

I can see it's working as expected.

  • The load event is triggered when fzf gets the first result list after the input stream completes.
  • The result event is triggered whenever the result list is updated.

In this example:

fzf --bind 'start,space:reload:echo foo; sleep 1; echo bar' \
    --bind load:transform-footer:date \
    --bind result:transform-header:date
  • fzf starts and triggers the start event
  • fzf gets the initial partial list with foo
    • result event is triggered
      • Header is updated
  • After a 1-second delay
  • The input stream is complete and fzf gets the complete list (foo and bar)
    • load event is triggered because the stream is complete
      • Footer is updated
    • result event is triggered because we have a new list
      • Header is updated
  • This will repeat whenever you press space

And in this example, where fzf processes an infinite stream, the load event is never triggered. However, the result event fires each time the list is updated:

cat /dev/random | xxd | fzf --tail 1000 --bind result:transform-header:date --bind load:transform-footer:date

So in your case, the load and result events are triggered at the same tick, and the action bound to result ends up overriding the one from load.

What exactly are you trying to implement?

junegunn avatar Oct 19 '25 14:10 junegunn

in your examples the load event is triggered just once. my issue is that the cursor resets position on each load

for a more practical example, lets say you wanna monitor running processes:

ps -ef | fzf --raw --bind result:best --bind 'load:reload(ps -ef; sleep 1)'

youre unable to make a selection with up/down, because on each load the cursor will reset

DarioDarko avatar Oct 20 '25 09:10 DarioDarko

I find the flickering problem more reliably visible with a longer list, like:

printf '%s\n' {1..100000} | fzf --raw --bind result:best --color current-bg:white

and then when repeatedly typing e.g. 7/space/backspace — the cursor briefly jumps to the first item before coming back to the best match. (This happens with a fixed list, no reload, no infinite stream.)

Thanks @DarioDarko for the unbind/rebind trick that eliminates the flickering!

vejkse avatar Nov 09 '25 11:11 vejkse