Support reloading directly without shell
Checklist
- [x] I have read through the manual page (
man fzf) - [x] I have searched through the existing issues
- [ ] For bug reports, I have checked if the bug is reproducible in the latest version of fzf
Output of fzf --version
0.61 (devel)
OS
- [x] Linux
- [ ] macOS
- [ ] Windows
- [ ] Etc.
Shell
- [ ] bash
- [x] zsh
- [ ] fish
Problem / Steps to reproduce
As far as I know, the only way to reload fzf currently is by giving it a command to run in a shell and then it will read data from the shell's stdout. For most cases this is very convenient. Sometimes though you may want to programmatically control fzf at runtime from another process using the HTTP server. In this case it would be very useful to be able to tell fzf to reload directly from data you provide rather than from a shell command.
Real usecase: I am using fzf to make a window switcher script, similar to alt+tab on windows, and am using a single instance of kitty+fzf for latency reasons. When I press alt+tab, my script tells kitty to become visible and tells fzf to reload itself with the updated window list sorted by when each window was last focused.
Right now my script is controlling fzf like so:
# windows_string is null separated string representing all of the open windows
windows_bytes = windows_string.encode("utf-8")
windows_base64 = base64.b64encode(windows_bytes).decode("ascii")
await send_message_to_fzf(
f'unbind(focus)+clear-query+first+reload-sync:base64 --decode <<< "{windows_base64}"'
)
This works, but:
- The shell isn't really necessary since my script knows exactly what data fzf should be reloaded with.
- The script is unnecessarily tied to a POSIX-like environment.
- There is slight latency before fzf reloads itself because it needs to spawn and read from a shell which it turn needs to spawn
base64, etc.
Something like a reload-base64 action would enable more responsive/portable ways to programmatically control fzf.
My code would become:
await send_message_to_fzf(
f'unbind(focus)+clear-query+first+reload-base64:{windows_base64}'
)
This is probably one of those use-cases that is niche enough that it isn't worth the added complexity but I thought I would suggest it anyway.
So I'm probably not going to do this. As you mentioned, this is a very niche use case, and fzf is a short-lived process in most common scenarios.
The script is unnecessarily tied to a POSIX-like environment.
I wouldn't worry too much about it. fzf was essentially built as a Unix tool and is primarily used that way.
There is slight latency
Using a shell to run a command in non-interactive mode is extremely fast, and I doubt the delay is really noticeable in practice. That said, you can shave off a few milliseconds by using something like dash.
$ time bash -c ''
real 0m0.008s
user 0m0.004s
sys 0m0.003s
$ time zsh -c ''
real 0m0.015s
user 0m0.004s
sys 0m0.008s
$ time fish -c ''
real 0m0.044s
user 0m0.025s
sys 0m0.034s
$ time dash -c ''
real 0m0.005s
user 0m0.002s
sys 0m0.003s
So try setting fzf to use it like this: --with-shell 'dash -c'.
As for the base64, I'm not sure if it's necessary. Wouldn't it be simpler and potentially faster to write the list to a temp file and just cat it? Or you could use a named pipe for asynchronous feeding.
So I'm probably not going to do this. As you mentioned, this is a very niche use case, and fzf is a short-lived process in most common scenarios.
Totally understandable, and I expected as much.
The script is unnecessarily tied to a POSIX-like environment.
I wouldn't worry too much about it. fzf was essentially built as a Unix tool and is primarily used that way.
I didn't word this right. The rest of my script is heavily tied to my environment anyway, I just wanted to point out a potential benefit of something like reload-base64.
There is slight latency
Using a shell to run a command in non-interactive mode is extremely fast, and I doubt the delay is really noticeable in practice. That said, you can shave off a few milliseconds by using something like
dash.
You are right. After actually measuring the number of frames between when I press alt+tab and fzf is reloaded, I have determined that I am definitely hallucinating the latency. Or maybe I am super human.
As for the
base64, I'm not sure if it's necessary. Wouldn't it be simpler and potentially faster to write the list to a temp file and justcatit? Or you could use a named pipe for asynchronous feeding.
Yeah I thought about using a named pipe but just base64 encoding it felt easier at the time for various reasons. All of these solutions just felt a little indirect.
Thanks for making such a flexible tool.