From 5bf6a5da5efe384eb8e829b1c936a6860d7263cb Mon Sep 17 00:00:00 2001 From: Sebastian Moser Date: Tue, 4 Mar 2025 20:25:48 +0100 Subject: [PATCH] fixed lf previewer --- programs/bash.nix | 6 +- programs/lf/cleaner | 4 - programs/lf/default.nix | 102 +++++++++------- programs/lf/previewer | 253 +++++++++------------------------------- 4 files changed, 122 insertions(+), 243 deletions(-) delete mode 100755 programs/lf/cleaner diff --git a/programs/bash.nix b/programs/bash.nix index b899429..962e18d 100644 --- a/programs/bash.nix +++ b/programs/bash.nix @@ -113,9 +113,9 @@ fi - # source lfcd - source ${pkgs.lf.src}/etc/lfcd.sh - alias lf="lfcd" + function lf () { + ${config.programs.lf.package}/bin/lf -last-dir-path /tmp/lf-last-path && cd $(cat /tmp/lf-last-path) + } # so that programms i spawn from my shell don't have so high cpu priority diff --git a/programs/lf/cleaner b/programs/lf/cleaner deleted file mode 100755 index a184d84..0000000 --- a/programs/lf/cleaner +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -if [ -n "$FIFO_UEBERZUG" ]; then - printf '{"action": "remove", "identifier": "PREVIEW"}\n' > "$FIFO_UEBERZUG" -fi diff --git a/programs/lf/default.nix b/programs/lf/default.nix index f6e3d36..9dda2c1 100644 --- a/programs/lf/default.nix +++ b/programs/lf/default.nix @@ -2,18 +2,52 @@ { home.file.".config/lf/icons".source = "${self}/programs/lf/icons"; programs.lf = let + + myUeberzug = pkgs.ueberzugpp.overrideAttrs (prev: { + src = pkgs.fetchFromGitHub { + owner = "jstkdng"; + repo = "ueberzugpp"; + rev = "528fb0fd6719477308e779aa6dab6040faa698cc"; + hash = "sha256-VdfpWJOMlC4Ly2lDFvJ+BnOmaM71gLEaIkfwLqzAi/8="; + }; + cmakeFlags = prev.cmakeFlags or [] ++ [ "-DENABLE_SWAY=ON" ]; + }); + mylf = pkgs.lf.overrideAttrs (final: prev: { patches = (prev.patches or [ ]) ++ [ ./lf-filter.patch ]; checkPhase = ""; }); + + myCleaner = pkgs.writeShellApplication { + name = "myCleaner"; + + runtimeInputs = with pkgs; [ myUeberzug ]; + + text = '' + ueberzugpp cmd -s "$UB_SOCKET" -a remove -i PREVIEW + UB_PID=$(cat "$UB_PID_FILE") + kill "$UB_PID" + ''; + }; + myPreviewer = pkgs.writeShellApplication { name = "myPreviewer"; runtimeInputs = with pkgs; [ file + gnumeric + catdoc + odt2txt + transmission_4 + libcdio + p7zip + unrar + xz bat # (text) - ueberzug # (images, videos, pdf, fonts) + exiftool + ffmpegthumbnailer + myUeberzug # (images, videos, pdf, fonts) ffmpegthumbnailer # (videos) exiftool # (metadata/audio, and file detection for .webm files) jq # (json and metadata) @@ -28,60 +62,46 @@ ]; text = builtins.readFile "${self}/programs/lf/previewer"; }; - # use newest version of ueberzug from nixpkgs unstable because: https://github.com/ueber-devel/ueberzug/issues/15 - # mylfWrapper = let myUeberzug = inputs.nixpkgs-unstable.legacyPackages.${system}.ueberzug; - mylfWrapper = let myUeberzug = pkgs.ueberzug.overrideAttrs (final: prev: { version = "18.2.2"; }); - in pkgs.writeShellApplication { + + mylfWrapper = pkgs.writeShellApplication { name = "lf"; - #runtimeInputs = with pkgs; [ curl w3m ]; + runtimeInputs = with pkgs; [ mylf myUeberzug util-linux ]; text = '' - # got it FROM: https://codeberg.org/tplasdio/lf-config/src/branch/main/.local/bin/lfub - - # Envolvedor de lf, que permite crear previsualizaciones de imágenes - # con ueberzug, en conjunto con mi configuración 'previewer' y 'cleaner' para lf - # Taken from: https://github.com/LukeSmithxyz/voidrice/blob/master/.local/bin/lfub - # TODO: - # - Capturar cuando se cierre/mate la ventana conteniendo la terminal que corre - # este script, pues si no se quedarán procesos huérfanos 'lf' 'lfub' 'ueberzug' + # This is a wrapper script for lf that allows it to create image previews with + # ueberzug. This works in concert with the lf configuration file and the + # lf-cleaner script. set -e - set +u - : "''${XDG_CACHE_HOME:="''${HOME}/.cache"}" + set +o nounset - cleanup() { - exec 3>&- - # FIXME: - # after SIGINT commands that expected some arguments, previews for that directory - # are stuck in "loading", because there's no fifo file to remove or something - # Example: - # gpg -d # ← Forgot to type $f for decrypting a file - # Ctrl-C # ← Back to lf, previews are stuck - rm "$FIFO_UEBERZUG" - } + UB_PID=0 + UB_SOCKET="" - main() { - if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then + case "$(uname -a)" in + *Darwin*) UEBERZUG_TMP_DIR="$TMPDIR" ;; + *) UEBERZUG_TMP_DIR="/tmp" ;; + esac + + if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then ${mylf}/bin/lf "$@" - else - [ -d "''${XDG_CACHE_HOME}/lf" ] || mkdir -p "''${XDG_CACHE_HOME}/lf" - export FIFO_UEBERZUG="''${XDG_CACHE_HOME}/lf/ueberzug-$$" - mkfifo "$FIFO_UEBERZUG" - ${myUeberzug}/bin/ueberzug layer -s < "$FIFO_UEBERZUG" -p json & - exec 3> "$FIFO_UEBERZUG" - trap cleanup HUP INT QUIT TERM PWR EXIT - ${mylf}/bin/lf "$@" 3>&- - fi - } + else + [ ! -d "$HOME/.cache/lf" ] && mkdir -p "$HOME/.cache/lf" + UB_PID_FILE="$UEBERZUG_TMP_DIR/.$(uuidgen)" + ueberzugpp layer --silent --no-stdin --use-escape-codes --pid-file "$UB_PID_FILE" + UB_PID=$(cat "$UB_PID_FILE") + UB_SOCKET="$UEBERZUG_TMP_DIR/ueberzugpp-''${UB_PID}.socket" + export UB_PID UB_SOCKET - main "$@" || exit $? + ${mylf}/bin/lf "$@" + fi ''; }; in { - package = mylfWrapper; + package = mylfWrapper // { inherit myUeberzug; }; enable = true; commands = { @@ -144,7 +164,7 @@ }} source ${self}/programs/lf/opener - set cleaner "${self}/programs/lf/cleaner" + set cleaner "${myCleaner}/bin/myCleaner" set cursorpreviewfmt "\033[7m" set previewer "${myPreviewer}/bin/myPreviewer" set period "1" diff --git a/programs/lf/previewer b/programs/lf/previewer index e95ef0f..fe6041b 100755 --- a/programs/lf/previewer +++ b/programs/lf/previewer @@ -1,202 +1,65 @@ -#!/bin/bash -# shellcheck disable=SC2222 +#!/bin/sh -# File preview handler for lf. -# Dependencies: -# - GNU 'file' or similar (file detection) -# - bat (text) -# - uebergzug (images, videos, pdf, fonts) -# - ffmpegthumbnailer (videos) -# - exiftool (metadata/audio, and file detection for .webm files) -# - jq (json and metadata) -# - lynx (html/web pages) -# - pdftoppm (pdf) -# - odt2txt (odt) -# - convert from imagemagick (fonts) -# - atool (archives) -# - gpg (PGP encrypted files) -# - man (troff manuals) -# - Other: stat, cut, sha256sum - -# Notes: -# - If using alacritty's same process: 'alacritty msg create-window', previews only show in first window - -set -C -f -IFS=' -' - -# Display an image with certain path, width, height, x, y -# Usage: image "$path_to_image" "$width" "$height" "$x" "$y" "$fallback_path" image() { - # shellcheck disable=all - set +u - set +e - if [ -f "$1" ] && [ "$DISPLAY" ] && [ ! "$WAYLAND_DISPLAY" ] - then - printf '{"action": "add", "identifier": "PREVIEW", "path": "%s", "width": "%s", "height": "%s", "scaler": "contain", "x": "%s", "y": "%s"}\n' \ - "$1" "$(($2-1))" "$(($3-1))" "$4" "$5" > "$FIFO_UEBERZUG" - else - exiftool -j "$6" | jq -C - fi + FILE_PATH="$1" + X=$4 + Y=$5 + MW=$(($2 - 1)) + MH=$3 + ueberzug cmd -s "$UB_SOCKET" -a add -i PREVIEW -x "$X" -y "$Y" --max-width "$MW" --max-height "$MH" -f "$FILE_PATH" + exit 1 } -ifub() { - # shellcheck disable=all - if [ "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ]; then - command -V ueberzug >/dev/null 2>&1 - fi +batorcat() { + file="$1" + shift + if command -v bat >/dev/null 2>&1; then + bat --color=always --style=plain --pager=never "$file" "$@" + else + cat "$file" + fi } -# Note that the cache file name is a function of file information, meaning if -# an image appears in multiple places across the machine, it will not have to -# be regenerated once seen. +CACHE="$HOME/.cache/lf/thumbnail.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | sha256sum | awk '{print $1}'))" -create_cache() { - # shellcheck disable=all - CACHE="${XDG_CACHE_HOME:-"$HOME/.cache"}/lf/thumb.$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' \ - -- "$(readlink -f "$1" || realpath "$1" )" \ - | sha256sum \ - | cut -d' ' -f1)" -} - -mime_preview() { - # shellcheck disable=all - # The 'ran_guard' variable is there in case I need to do recursion - # because the initial mime_type variable wasn't enough to determine - # an adequate preview - case "$mime_type","$ran_guard" in - (image/svg+xml,0 | image/svg) - create_cache "$1" - [ -f "$CACHE.png" ] \ - || rsvg-convert -o "$CACHE.png" -a -w "1000" -b '#1f2430' "$1" - image "$CACHE.png" "$2" "$3" "$4" "$5" "$1" - ;; - (image/*,0) - image "$1" "$2" "$3" "$4" "$5" "$1" - ;; - (text/html,0) - lynx -width="$4" -display_charset=utf-8 -dump -- "$1" - ;; - (text/troff,0) - case "${1##*.}" in - ([0-9] | [01]p | [23]*) - man ./ "$1" | col -b - ;; - (*) - bat --terminal-width "$(($4*7/9))" -f "$1" --style=numbers - esac - ;; - (text/*,0 | */xml,0 | application/javascript,0 | application/x-subrip,0 ) - bat --terminal-width "$(($4*7/9))" -f "$1" --style=numbers - ;; - ( application/x-pie-executable,0 | application/x-executable,0 | \ - application/x-sharedlib,0) - objdump -d "$1" -M intel - #readelf -WCa "$1" - #hexdump -C "$1" || xxd "$1" - ;; - (application/json,0) - case "${1##*.}" in - (ipynb) - # Needs my fork of ipynb-py-convert - ipynb-py-convert --stdout "$1" \ - | bat --terminal-width "$(($4*7/9))" --color=always -l python --style=numbers - ;; - (*) jq -C < "$1" ;; - esac - ;; - (application/zip,0 | application/x-7z-compressed,0 ) - atool --list -- "$1" - ;; - (audio/*,[01]) - exiftool -j "$1" | jq -C - ;; - (video/webm,0) - # file --mime-type doesn't distinguish well between "video/webm" - # actual webm videos or webm audios, but exiftool does, thus - # re-run this function with new mimetype - mime_type="$(exiftool -s3 -MIMEType "$1")" \ - ran_guard=$((ran_guard+1)) - mime_preview "$@" - ;; - (video/*,[01]) - create_cache "$1" - [ -f "$CACHE" ] \ - || ffmpegthumbnailer -i "$1" -o "$CACHE" -s 0 - image "$CACHE" "$2" "$3" "$4" "$5" "$1" - ;; - (*/pdf,0 | */postscript,0) # .pdf, .ps - create_cache "$1" - [ -f "$CACHE.jpg" ] \ - || pdftoppm -jpeg -f 1 -singlefile "$1" "$CACHE" - image "$CACHE.jpg" "$2" "$3" "$4" "$5" "$1" - ;; - (application/font*,0 | application/*opentype,0 | font/sfnt,0) # .ttf, .otf - create_cache "$1" - [ -f "$CACHE.png" ] \ - || convert -size "800x800" "xc:#000000" -fill "#ffffff" \ - -pointsize "72" -font "$1" -gravity center -annotate +0+0 \ - "ABCDEFGHIJKLM\nNOPQRSTUVWXYZ\nabcdefghijklm\nnopqrstuvwxyz\n1234567890\n!@#$\%^&*,.;:\n_-=+'\"|\\(){}[]" \ - "$CACHE.png" - image "$CACHE.png" "$2" "$3" "$4" "$5" "$1" - ;; - (*opendocument*,0) # .odt, .ods - CCt=' ' \ - bytes=$(du -sb "$1") bytes="${bytes%%"$CCt"*}" - if [ "$bytes" -lt 150000 ]; then - odt2txt "$1" - else - printf "file too big too preview quickly\n" - fi - ;; - (*ms-excel,0) # .xls - xls2csv -- "$1" \ - | bat --terminal-width "$(($4*7/9))" --color=always -l csv --style=numbers - ;; - #(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet) # .xslx - # https://github.com/dilshod/xlsx2csv - #xlsx2csv -- "$1" - #;; - #(text/rtf,0 | *msword,0 ) # .doc, doesn't always work - #catdoc -- "$1" - #;; - #(*wordprocessingml.document|*/epub+zip|*/x-fictionbook+xml) # .docx - #pandoc -s -t markdown -- "$1" - #;; - #(message/rfc822) - # https://github.com/djcb/mu - #mu view -- "${FILE_PATH}" && exit 5 - #;; - # TODO: add lf command to decrypt it and show the decrypted file in preview window - (application/pgp-encrypted,0) - printf "PGP armored ASCII \033[1;31mencrypted\033[m file,\ntry using gpg to decrypt it\n\n" - cat "$1" - #gpg -d -- "$1" - ;; - (application/octet-stream,0) - #extension="${1##*.}" extension="${extension%"$1"}" - case "${1##*.}" in - (gpg) - printf "OpenPGP \033[1;31mencrypted\033[m file,\ntry using gpg to decrypt it\n\n" - ;; - (*) exiftool -j "$1" | jq -C - esac - ;; - (application/vnd.sqlite3,0) - # TODO: handle multiple tables, maybe it's better to show tables and columns in a tree format - table=$(sqlite3 "$1" '.tables') - sqlite3 "$1" ".headers on" ".mode markdown" "select * from $table" - ;; - esac - return 1 -} - -main() { - # shellcheck disable=all - mime_type="$(file --dereference -b --mime-type -- "$1")" - "echo hiiiiiiiiiiiiiiiiii $mime_type" - ran_guard=0 - mime_preview "$@" || return $? -} - -main "$@" || exit $? +case "$(printf "%s\n" "$(readlink -f "$1")" | tr '[:upper:]' '[:lower:]')" in + *.tgz | *.tar.gz) tar tzf "$1" ;; + *.tar.bz2 | *.tbz2) tar tjf "$1" ;; + *.tar.txz | *.txz) xz --list "$1" ;; + *.tar) tar tf "$1" ;; + *.zip | *.jar | *.war | *.ear | *.oxt) unzip -l "$1" ;; + *.rar) unrar l "$1" ;; + *.7z) 7z l "$1" ;; + *.[1-8]) man "$1" | col -b ;; + *.o) nm "$1" ;; + *.torrent) transmission-show "$1" ;; + *.iso) iso-info --no-header -l "$1" ;; + *.odt | *.ods | *.odp | *.sxw) odt2txt "$1" ;; + *.doc) catdoc "$1" ;; + *.docx) docx2txt "$1" - ;; + *.xls | *.xlsx) + ssconvert --export-type=Gnumeric_stf:stf_csv "$1" "fd://1" | batorcat --language=csv + ;; + *.wav | *.mp3 | *.flac | *.m4a | *.wma | *.ape | *.ac3 | *.og[agx] | *.spx | *.opus | *.as[fx] | *.mka) + exiftool "$1" + ;; + *.pdf) + [ ! -f "${CACHE}.jpg" ] && pdftoppm -jpeg -f 1 -singlefile "$1" "$CACHE" + image "${CACHE}.jpg" "$2" "$3" "$4" "$5" + ;; + *.avi | *.mp4 | *.wmv | *.dat | *.3gp | *.ogv | *.mkv | *.mpg | *.mpeg | *.vob | *.fl[icv] | *.m2v | *.mov | *.webm | *.ts | *.mts | *.m4v | *.r[am] | *.qt | *.divx) + [ ! -f "${CACHE}.jpg" ] && ffmpegthumbnailer -i "$1" -o "${CACHE}.jpg" -s 0 -q 5 + image "${CACHE}.jpg" "$2" "$3" "$4" "$5" + ;; + *.bmp | *.jpg | *.jpeg | *.png | *.xpm | *.webp | *.gif | *.jfif) + image "$1" "$2" "$3" "$4" "$5" + ;; + *.svg) + [ ! -f "${CACHE}.jpg" ] && convert "$1" "${CACHE}.jpg" + image "${CACHE}.jpg" "$2" "$3" "$4" "$5" + ;; + *) + batorcat "$1" + ;; +esac +exit 0