cursor position reset in raw mode
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
I can see it's working as expected.
- The
loadevent is triggered when fzf gets the first result list after the input stream completes. - The
resultevent 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
startevent - fzf gets the initial partial list with
foo-
resultevent is triggered- Header is updated
-
- After a 1-second delay
- The input stream is complete and fzf gets the complete list (
fooandbar)-
loadevent is triggered because the stream is complete- Footer is updated
-
resultevent 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?
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
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!