From 616596726d387415624ad18fd4a2c1011f8ecfc3 Mon Sep 17 00:00:00 2001 From: Rootiest Date: Fri, 21 Aug 2026 00:46:29 -0400 Subject: [PATCH] feat(fzf): add preview, dirs, and image support to @@ inline picker The @@ picker only listed files with no preview. It now lists both files and directories via fd (matching _fzf_search_directory), and shows a bat-highlighted or image-rendered preview through _fzf_preview_file. Image previews use a kitty-graphics-protocol, chafa, viu, timg fallback chain via the new _fzf_preview_image helper, benefiting the Ctrl+F directory search and git-status pickers as well since they share the same preview helper. --- functions/__fzf_inline_picker.fish | 26 +++++++++++++++++--- functions/_fzf_preview_file.fish | 2 ++ functions/_fzf_preview_image.fish | 39 ++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 functions/_fzf_preview_image.fish diff --git a/functions/__fzf_inline_picker.fish b/functions/__fzf_inline_picker.fish index f9e05fb..71b3d2b 100644 --- a/functions/__fzf_inline_picker.fish +++ b/functions/__fzf_inline_picker.fish @@ -7,9 +7,12 @@ # DESCRIPTION # Bound to the @ key. Self-inserts @ normally; on a second consecutive @ # (detected by looking behind at the current token rather than making fish -# buffer ahead for a chord), opens an interactive fzf session and replaces -# the bare @ with the selected item. Cancelling leaves a literal @@ behind. -# Repaints the prompt after selection or cancellation. +# buffer ahead for a chord), opens an interactive fzf session listing both +# files and directories under the current directory, with a preview pane +# (bat-highlighted for text, image-rendered for pictures via +# _fzf_preview_file), and replaces the bare @ with the selected item. +# Cancelling leaves a literal @@ behind. Repaints the prompt after +# selection or cancellation. # # EXIT STATUS # 0 Always @@ -20,7 +23,22 @@ # # (e.g. a trailing /subdir). function __fzf_inline_picker if test (commandline -t) = @ - set -l selection (fzf) + # Directly use fd binary to avoid output buffering delay caused by a fd + # alias, if any. Debian-based distros install fd as fdfind. + set -f fd_cmd (command -v fdfind || command -v fd || echo "fd") + set -f --append fd_cmd --color=always $fzf_fd_opts + + set -l selection ($fd_cmd 2>/dev/null | _fzf_wrapper --ansi \ + --height=90% \ + --layout=reverse \ + --border=rounded \ + --border-label=' Insert Path ' \ + --prompt='@@ -> ' \ + --header='Enter: Insert Ctrl-/: Toggle Preview Esc: Cancel' \ + --bind='ctrl-/:toggle-preview' \ + --preview='_fzf_preview_file {}' \ + --preview-window='right:50%:wrap:border-left') + if test -n "$selection" commandline -t -- (string escape -- $selection) else diff --git a/functions/_fzf_preview_file.fish b/functions/_fzf_preview_file.fish index c926475..793520f 100644 --- a/functions/_fzf_preview_file.fish +++ b/functions/_fzf_preview_file.fish @@ -17,6 +17,8 @@ function _fzf_preview_file --description "Print a preview for the given file bas if set --query fzf_preview_file_cmd # need to escape quotes to make sure eval receives file_path as a single arg eval "$fzf_preview_file_cmd '$file_path'" + else if command -q file; and string match -q 'image/*' -- (command file --brief --mime-type -- "$file_path" 2>/dev/null) + _fzf_preview_image "$file_path" else bat --style=numbers --color=always "$file_path" end diff --git a/functions/_fzf_preview_image.fish b/functions/_fzf_preview_image.fish new file mode 100644 index 0000000..0fb65fd --- /dev/null +++ b/functions/_fzf_preview_image.fish @@ -0,0 +1,39 @@ +# helper function for _fzf_preview_file +function _fzf_preview_image --description "Render an image preview using the best available tool for the current terminal." + set -f file_path $argv + + set -l cols (set --query FZF_PREVIEW_COLUMNS; and echo $FZF_PREVIEW_COLUMNS; or echo 80) + set -l lines (set --query FZF_PREVIEW_LINES; and echo $FZF_PREVIEW_LINES; or echo 24) + set -l left (set --query FZF_PREVIEW_LEFT; and echo $FZF_PREVIEW_LEFT; or echo 0) + set -l top (set --query FZF_PREVIEW_TOP; and echo $FZF_PREVIEW_TOP; or echo 0) + + # Terminals that implement the kitty graphics protocol (kitty itself, + # WezTerm, and Ghostty) can render via `kitten icat` even when it's not + # the active terminal, since `kitten` is just an escape-sequence emitter. + set -l kitty_capable 0 + if set --query KITTY_WINDOW_ID + or test "$TERM" = xterm-kitty + or contains -- "$TERM_PROGRAM" WezTerm ghostty + or set --query GHOSTTY_RESOURCES_DIR + set kitty_capable 1 + end + + if test $kitty_capable -eq 1; and command -q kitten + # --place is measured from the top-left of the whole terminal, not the + # preview pane, so FZF_PREVIEW_LEFT/TOP (added to fzf specifically for + # this integration) are required to land the image in the right spot. + command kitten icat --clear --transfer-mode=memory --unicode-placeholder \ + --stdin=no --place="$cols"x"$lines"@"$left"x"$top" -- "$file_path" 2>/dev/null + else if command -q chafa + command chafa --size="$cols"x"$lines" -- "$file_path" + else if command -q viu + command viu --width $cols -- "$file_path" + else if command -q timg + command timg -g "$cols"x"$lines" -- "$file_path" + else + set_color yellow + echo "No image preview tool available (install kitty, chafa, viu, or timg)." + set_color normal + command file --brief -- "$file_path" + end +end