Last active
September 5, 2023 21:29
-
-
Save tkapias/532e5ad7bc03b7a4000d9deed361096d to your computer and use it in GitHub Desktop.
fzf-img.sh - Image fuzzy finder with preview using fzf and ueberzug
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# This is just an example how ueberzug can be used with fzf. | |
# Copyright (C) 2019 Nico Bäurer | |
# Copyright (C) 2022 Tomasz Kapias | |
# - Updated: | |
# - optional PATH as only option | |
# - internal FDfind query for images | |
# - display SVGs after caching a converted png | |
# - Imagemagick's identify infos as header with margin | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <https://www.gnu.org/licenses/>. | |
readonly BASH_BINARY="$(which bash)" | |
readonly REDRAW_COMMAND="toggle-preview+toggle-preview" | |
readonly REDRAW_KEY="µ" | |
declare -r -x DEFAULT_PREVIEW_POSITION="right" | |
declare -r -x UEBERZUG_FIFO="$(mktemp --dry-run --suffix "fzf-$$-ueberzug")" | |
declare -r -x PREVIEW_ID="preview" | |
function start_ueberzug { | |
mkfifo "${UEBERZUG_FIFO}" | |
<"${UEBERZUG_FIFO}" \ | |
ueberzug layer --parser bash --silent & | |
# prevent EOF | |
3>"${UEBERZUG_FIFO}" \ | |
exec | |
} | |
function finalise { | |
3>&- \ | |
exec | |
&>/dev/null \ | |
rm "${UEBERZUG_FIFO}" | |
&>/dev/null \ | |
kill $(jobs -p) | |
} | |
function calculate_position { | |
# TODO costs: creating processes > reading files | |
# so.. maybe we should store the terminal size in a temporary file | |
# on receiving SIGWINCH | |
# (in this case we will also need to use perl or something else | |
# as bash won't execute traps if a command is running) | |
< <(</dev/tty stty size) \ | |
read TERMINAL_LINES TERMINAL_COLUMNS | |
case "${PREVIEW_POSITION:-${DEFAULT_PREVIEW_POSITION}}" in | |
left|up|top) | |
X=1 | |
Y=1 | |
;; | |
right) | |
X=$((TERMINAL_COLUMNS - COLUMNS - 2)) | |
Y=1 | |
;; | |
down|bottom) | |
X=1 | |
Y=$((TERMINAL_LINES - LINES - 1)) | |
;; | |
esac | |
} | |
function draw_preview { | |
calculate_position | |
>"${UEBERZUG_FIFO}" declare -A -p cmd=( \ | |
[action]=add [identifier]="${PREVIEW_ID}" \ | |
[x]="${X}" [y]="$(( ${Y} + 2 ))" \ | |
[width]="${COLUMNS}" [height]="$(( ${LINES} - 2 ))" \ | |
[scaler]=contain \ | |
[path]="${@}") | |
# add [synchronously_draw]=True if you want to see each change | |
} | |
function svg_preview { | |
CACHEDIR="$HOME/.cache/fzf-img" | |
mkdir $CACHEDIR | |
SVGCACHE="$CACHEDIR/thumbnail.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | \ | |
sha256sum | awk '{print $1}')" | |
[ ! -f "$SVGCACHE" ] && convert -background none "${@}" "${SVGCACHE}.png" | |
calculate_position | |
>"${UEBERZUG_FIFO}" declare -A -p cmd=( \ | |
[action]=add [identifier]="${PREVIEW_ID}" \ | |
[x]="${X}" [y]="$(( ${Y} + 2 ))" \ | |
[width]="${COLUMNS}" [height]="$(( ${LINES} - 2 ))" \ | |
[scaler]=contain \ | |
[path]="${SVGCACHE}.png") | |
# add [synchronously_draw]=True if you want to see each change | |
} | |
function print_on_winch { | |
# print "$@" to stdin on receiving SIGWINCH | |
# use exec as we will only kill direct childs on exiting, | |
# also the additional bash process isn't needed | |
</dev/tty \ | |
exec perl -e ' | |
require "sys/ioctl.ph"; | |
while (1) { | |
local $SIG{WINCH} = sub { | |
ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV; | |
}; | |
sleep; | |
}' \ | |
"${@}" & | |
} | |
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then | |
trap finalise EXIT | |
# print the redraw key twice as there's a run condition we can't circumvent | |
# (we can't know the time fzf finished redrawing it's layout) | |
print_on_winch "${REDRAW_KEY}${REDRAW_KEY}" | |
start_ueberzug | |
export -f draw_preview svg_preview calculate_position | |
SHELL="${BASH_BINARY}" \ | |
fdfind -0a -tf -tl -e jpg -e jpeg -e png -e gif -e svg -e ico -e webp -e tif "^.+$" "$([[ -z $1 ]] && echo $PWD || realpath $1)" | \ | |
xargs -r -0 exa --colour=always | \ | |
fzf -m --ansi --keep-right --header "jpg/jpeg/gif/svg/ico/tif/webp files in $([[ -z $1 ]] && echo $PWD || realpath $1)" \ | |
--preview "identify {} | awk '{print \$2,\$3,\$4,\$5,\$6,\$7}'; [[ \$(file --mime {}) =~ svg ]] && svg_preview {} || draw_preview {}" \ | |
--preview-window "${DEFAULT_PREVIEW_POSITION}" \ | |
--bind "${REDRAW_KEY}:${REDRAW_COMMAND}" | |
fi |
This is too handy!
Nicely done
so great, one of the most useful scripts for fzf improved nicely.
welp, using this script as a base i built this thing... https://github.com/eylles/wal-choose
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Customized version from ueberzug repo.
I use it in complement of vifm (customized with vifmimg).
The original is an example.
Require:
Screenshot:
