about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-11-24 17:57:24 +0100
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-11-24 18:24:57 +0100
commit5d64cd10907acc67b9d3575dc59b3cefe74b8592 (patch)
tree00a1868cf44f890b1e43a86baa7ebe2c52cb8297
parentfeat(modules/lf): Dynamically generate the cd script (diff)
downloadnixos-config-5d64cd10907acc67b9d3575dc59b3cefe74b8592.tar.gz
nixos-config-5d64cd10907acc67b9d3575dc59b3cefe74b8592.zip
feat(modules/lf/ctpv): Correct configure
This also ensures, that all the needed previewers are available
-rw-r--r--modules/by-name/lf/lf/ctpv/default.nix274
-rw-r--r--modules/by-name/lf/lf/ctpv/helpers.sh56
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/any.sh16
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/atool.sh11
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/audio.sh21
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/bat.sh19
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/delta.sh11
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/elinks.sh18
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/font.sh18
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/glow.sh13
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/gpg.sh13
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/image.sh11
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/jq.sh11
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/libreoffice.sh27
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/ls.sh15
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/pdf.sh22
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/svg.sh17
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/symlink.sh14
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/torrent.sh13
-rw-r--r--modules/by-name/lf/lf/ctpv/prev/video.sh17
-rw-r--r--modules/by-name/lf/lf/module.nix12
21 files changed, 625 insertions, 4 deletions
diff --git a/modules/by-name/lf/lf/ctpv/default.nix b/modules/by-name/lf/lf/ctpv/default.nix
new file mode 100644
index 00000000..9667bc48
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/default.nix
@@ -0,0 +1,274 @@
+{
+  pkgs,
+  sysLib,
+  lib,
+  ...
+}: let
+  functionCall = {
+    name,
+    dependencies,
+    replacementStrings,
+    ...
+  }:
+    sysLib.writeShellScript {
+      inherit name;
+      src = ./prev/${name}.sh;
+      keepPath = false;
+      dependencies = dependencies ++ (builtins.attrValues {inherit (pkgs) dash coreutils;});
+      inherit replacementStrings;
+    }
+    + "/bin/${name}";
+
+  mkPreview = name: {
+    mime_matches ? [],
+    extension_matches ? [],
+    priority ? 0,
+    dependencies ? [],
+    replacementStrings ? {},
+  }: let
+    mkMimePath = val: let
+      split = lib.strings.splitString "/" val;
+      rhs = builtins.elemAt split 0;
+      lhs = builtins.elemAt split 1;
+    in
+      assert builtins.length split == 2; ''"${rhs}"/"${lhs}"'';
+
+    extensions = lib.strings.concatStringsSep " " (builtins.map (val: ''."${val}"'') extension_matches);
+    mimes = lib.strings.concatStringsSep " " (builtins.map mkMimePath mime_matches);
+    function = functionCall {
+      inherit name dependencies;
+      replacementStrings = {HELPERS = ./helpers.sh;} // replacementStrings;
+    };
+  in ''
+    preview ${name} ${extensions} ${mimes} {{
+      ${function}
+    }}
+    priority ${name} ${builtins.toString priority}
+  '';
+
+  mkRemove = name: ''
+    remove ${name}
+  '';
+
+  mkConfigFile = attrs:
+    lib.strings.concatStringsSep "\n\n"
+    (builtins.attrValues
+      (lib.attrsets.mapAttrs (name: value:
+        if value == null
+        then mkRemove name
+        else mkPreview name value)
+      attrs));
+in
+  mkConfigFile
+  {
+    # Remove all the default ones.
+    "cat" = null;
+    "colordiff" = null;
+    "diff_so_fancy" = null;
+    "highlight" = null;
+    "lynx" = null;
+    "mdcat" = null;
+    "source_highlight" = null;
+    "w3m" = null;
+
+    any = {
+      priority = -1;
+      dependencies = [
+        pkgs.exiftool
+        pkgs.vim # For xxd
+      ];
+    };
+
+    audio = {
+      mime_matches = ["audio/*"];
+      dependencies = [
+        pkgs.ffmpegthumbnailer
+        pkgs.ffmpeg
+      ];
+    };
+
+    delta = {
+      priority = 1;
+      mime_matches = ["text/x-diff" "text/x-patch"];
+      dependencies = [
+        pkgs.delta
+      ];
+    };
+    # TODO: I might want to use lynx/w3m instead <2024-11-24>
+    elinks = {
+      priority = 1;
+      mime_matches = ["text/html"];
+      dependencies = [
+        pkgs.elinks
+      ];
+    };
+    bat = {
+      mime_matches = ["text/*"];
+      dependencies = [
+        pkgs.bat
+      ];
+    };
+
+    svg = {
+      priority = 1;
+      mime_matches = ["image/svg+xml"];
+      dependencies = [
+        pkgs.imagemagick
+      ];
+    };
+    image = {
+      mime_matches = ["image/*"];
+      dependencies = [
+        pkgs.chafa
+      ];
+    };
+
+    jq = {
+      priority = 1;
+      mime_matches = ["application/json"];
+      dependencies = [
+        pkgs.jq
+      ];
+    };
+    pdf = {
+      priority = 1;
+      mime_matches = ["application/pdf"];
+      dependencies = [
+        pkgs.poppler_utils # for `pdftoppm`
+      ];
+    };
+
+    ls = {
+      priority = 1;
+      mime_matches = ["inode/directory"];
+      dependencies = [];
+    };
+    symlink = {
+      priority = 1;
+      mime_matches = ["inode/symlink"];
+      dependencies = [];
+    };
+
+    font = {
+      mime_matches = ["font/*"];
+      dependencies = [
+        pkgs.fontforge # for `fontimage`
+      ];
+    };
+    video = {
+      mime_matches = ["video/*"];
+      dependencies = [
+        pkgs.ffmpegthumbnailer
+      ];
+    };
+
+    libreoffice = {
+      extension_matches = [
+        "csv"
+        "doc"
+        "docx"
+        "fodp"
+        "fods"
+        "fodt"
+        "odp"
+        "ods"
+        "odt"
+        "ppt"
+        "pptx"
+        "xls"
+        "xlsx"
+      ];
+      dependencies = [
+        pkgs.libreoffice
+      ];
+    };
+
+    atool = {
+      extension_matches = [
+        "7z"
+        "Z"
+        "a"
+        "ace"
+        "alz"
+        "arc"
+        "arj"
+        "bz"
+        "bz2"
+        "cab"
+        "cpio"
+        "deb"
+        "gz"
+        "jar"
+        "lha"
+        "lrz"
+        "lz"
+        "lzh"
+        "lzma"
+        "lzo"
+        "rar"
+        "rpm"
+        "rz"
+        "t7z"
+        "tZ"
+        "tar"
+        "tar.7z"
+        "tar.Z"
+        "tar.bz"
+        "tar.bz2"
+        "tar.gz"
+        "tar.lz"
+        "tar.lzo"
+        "tar.xz"
+        "tbz"
+        "tbz2"
+        "tgz"
+        "tlz"
+        "txz"
+        "tzo"
+        "war"
+        "xz"
+        "zip"
+      ];
+      dependencies = [
+        pkgs.atool
+
+        # archive tools
+        pkgs.file
+        pkgs.gnutar
+        pkgs.gzip
+        pkgs.pbzip2
+        pkgs.plzip
+        pkgs.lzop
+        pkgs.xz
+        pkgs.zip
+        pkgs.unzip
+        pkgs.arj
+        pkgs.rpm
+        pkgs.cpio
+        pkgs.archiver # for arc
+        pkgs.p7zip
+
+        # Unfree stuff
+        # pkgs.rar
+        # pkgs.lha
+      ];
+    };
+    glow = {
+      extension_matches = ["md"];
+      dependencies = [
+        pkgs.glow
+      ];
+    };
+    gpg = {
+      extension_matches = ["gpg" "asc" "key" "pgp" "sig"];
+      dependencies = [
+        pkgs.sequoia-sq
+      ];
+    };
+    torrent = {
+      extension_matches = ["torrent"];
+      dependencies = [
+        pkgs.transmission_4 # for `transmission-show`
+      ];
+    };
+  }
diff --git a/modules/by-name/lf/lf/ctpv/helpers.sh b/modules/by-name/lf/lf/ctpv/helpers.sh
new file mode 100644
index 00000000..50a0e7cd
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/helpers.sh
@@ -0,0 +1,56 @@
+#! /usr/bin/env dash
+
+# shellcheck disable=SC2269
+cache_f="$cache_f"
+# shellcheck disable=SC2269
+id="$id"
+# shellcheck disable=SC2269
+m="$m"
+# shellcheck disable=SC2269
+fifo="$fifo"
+# shellcheck disable=SC2269
+w="$w"
+# shellcheck disable=SC2269
+h="$h"
+
+echo_err() {
+    echo "$@" >&2
+}
+
+noimages() {
+    [ -n "$noimages" ]
+}
+
+autochafa() {
+    [ -n "$autochafa" ]
+}
+
+chafasixel() {
+    [ -n "$chafasixel" ]
+}
+
+chafa_run() {
+    format='-f symbols'
+    autochafa && format=
+    chafasixel && format='-f sixels'
+
+    # The `$format` variable needs to expand to two arguments
+    # shellcheck disable=SC2086
+    chafa --size "${w}x${h}" $format "$1" | sed 's/#/\n#/g'
+}
+
+send_image() {
+    noimages && return 127
+
+    chafa_run "$1"
+}
+
+convert_and_show_image() {
+    noimages && return 127
+    [ -n "$cache_valid" ] || "$@" || exit "$?"
+    send_image "$cache_f"
+}
+
+isBinary() {
+    LC_ALL=C LC_MESSAGES=C grep --with-filename --max-count=1 '^' "$1" 2>&1 | grep --quiet 'binary file matches$'
+}
diff --git a/modules/by-name/lf/lf/ctpv/prev/any.sh b/modules/by-name/lf/lf/ctpv/prev/any.sh
new file mode 100644
index 00000000..9eb3a422
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/any.sh
@@ -0,0 +1,16 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+
+. %HELPERS
+
+if exiftool "$f" >/dev/null 2>&1; then
+    exiftool -- "$f"
+else
+    # Exiftool did not recognize the file.
+    xxd -- "$f"
+fi
diff --git a/modules/by-name/lf/lf/ctpv/prev/atool.sh b/modules/by-name/lf/lf/ctpv/prev/atool.sh
new file mode 100644
index 00000000..5f4baac7
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/atool.sh
@@ -0,0 +1,11 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+
+. %HELPERS
+
+atool --list -- "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/audio.sh b/modules/by-name/lf/lf/ctpv/prev/audio.sh
new file mode 100644
index 00000000..a828ab6c
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/audio.sh
@@ -0,0 +1,21 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+cache_f="$cache_f"
+
+. %HELPERS
+
+audio() {
+    ffmpegthumbnailer "-i$f" -s0 -q5 -t10 "-o$cache_f" 2>/dev/null
+}
+
+x="$(ffmpeg -hide_banner "-i$f" 2>&1)"
+printf '%s\n' "$x"
+y=$((y + $(printf '%s\n' "$x" | wc -l)))
+
+convert_and_show_image audio
diff --git a/modules/by-name/lf/lf/ctpv/prev/bat.sh b/modules/by-name/lf/lf/ctpv/prev/bat.sh
new file mode 100644
index 00000000..760ad50e
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/bat.sh
@@ -0,0 +1,19 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+w="$w"
+
+. %HELPERS
+
+bat \
+    --color always \
+    --style plain \
+    --paging never \
+    --terminal-width "$w" \
+    --wrap character \
+    -- "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/delta.sh b/modules/by-name/lf/lf/ctpv/prev/delta.sh
new file mode 100644
index 00000000..6a4e9a4e
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/delta.sh
@@ -0,0 +1,11 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+
+. %HELPERS
+
+delta <"$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/elinks.sh b/modules/by-name/lf/lf/ctpv/prev/elinks.sh
new file mode 100644
index 00000000..ca0de22e
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/elinks.sh
@@ -0,0 +1,18 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+w="$w"
+
+. %HELPERS
+
+elinks \
+    -dump 1 -dump-width "$w" \
+    -no-references -no-numbering <"$f"
+
+# lynx -dump -nonumbers -nolist -width="$w" -- "$f"
+# w3m -dump "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/font.sh b/modules/by-name/lf/lf/ctpv/prev/font.sh
new file mode 100644
index 00000000..4065557e
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/font.sh
@@ -0,0 +1,18 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+cache_f="$cache_f"
+
+. %HELPERS
+
+font() {
+    fontimage -o "$cache_f.png" "$f" 2>/dev/null &&
+        mv -- "$cache_f.png" "$cache_f"
+}
+
+convert_and_show_image font
diff --git a/modules/by-name/lf/lf/ctpv/prev/glow.sh b/modules/by-name/lf/lf/ctpv/prev/glow.sh
new file mode 100644
index 00000000..3b3fb609
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/glow.sh
@@ -0,0 +1,13 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+w="$w"
+
+. %HELPERS
+
+glow --style auto --width "$w" "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/gpg.sh b/modules/by-name/lf/lf/ctpv/prev/gpg.sh
new file mode 100644
index 00000000..72cca3a6
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/gpg.sh
@@ -0,0 +1,13 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+w="$w"
+
+. %HELPERS
+
+sq inspect -- "$f" 2>&1
diff --git a/modules/by-name/lf/lf/ctpv/prev/image.sh b/modules/by-name/lf/lf/ctpv/prev/image.sh
new file mode 100644
index 00000000..b5b97668
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/image.sh
@@ -0,0 +1,11 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+
+. %HELPERS
+
+send_image "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/jq.sh b/modules/by-name/lf/lf/ctpv/prev/jq.sh
new file mode 100644
index 00000000..bf807d1d
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/jq.sh
@@ -0,0 +1,11 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+
+. %HELPERS
+
+jq --color-output . <"$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/libreoffice.sh b/modules/by-name/lf/lf/ctpv/prev/libreoffice.sh
new file mode 100644
index 00000000..ec57da0b
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/libreoffice.sh
@@ -0,0 +1,27 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+cache_d="$cache_d"
+# shellcheck disable=SC2269
+cache_f="$cache_f"
+
+. %HELPERS
+
+doc() {
+    # File produced by libreoffice
+    jpg="$(printf '%s\n' "$f" | sed 's|^.*/||; s|\..*$||')"
+
+    libreoffice \
+        --headless \
+        --convert-to jpg \
+        --outdir "$cache_d" \
+        "$f" >/dev/null &&
+        mv -- "$cache_d/$jpg.jpg" "$cache_f"
+}
+
+convert_and_show_image doc
diff --git a/modules/by-name/lf/lf/ctpv/prev/ls.sh b/modules/by-name/lf/lf/ctpv/prev/ls.sh
new file mode 100644
index 00000000..f73bd1c2
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/ls.sh
@@ -0,0 +1,15 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+cache_d="$cache_d"
+# shellcheck disable=SC2269
+cache_f="$cache_f"
+
+. %HELPERS
+
+ls --color --group-directories-first -- "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/pdf.sh b/modules/by-name/lf/lf/ctpv/prev/pdf.sh
new file mode 100644
index 00000000..2f807b1a
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/pdf.sh
@@ -0,0 +1,22 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+cache_f="$cache_f"
+
+. %HELPERS
+
+pdf() {
+    pdftoppm -f 1 -l 1 \
+        -scale-to-x 1920 \
+        -scale-to-y -1 \
+        -singlefile \
+        -jpeg \
+        -- "$f" "$cache_f" && mv -- "$cache_f.jpg" "$cache_f"
+}
+
+convert_and_show_image pdf
diff --git a/modules/by-name/lf/lf/ctpv/prev/svg.sh b/modules/by-name/lf/lf/ctpv/prev/svg.sh
new file mode 100644
index 00000000..0c82025f
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/svg.sh
@@ -0,0 +1,17 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+cache_f="$cache_f"
+
+. %HELPERS
+
+svg() {
+    magick convert "$f" "jpg:$cache_f"
+}
+
+convert_and_show_image svg
diff --git a/modules/by-name/lf/lf/ctpv/prev/symlink.sh b/modules/by-name/lf/lf/ctpv/prev/symlink.sh
new file mode 100644
index 00000000..b30957d0
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/symlink.sh
@@ -0,0 +1,14 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+
+. %HELPERS
+
+#
+# do nothing because in src/ctpv.c some kind of a "preview"
+# is already printed
+#
diff --git a/modules/by-name/lf/lf/ctpv/prev/torrent.sh b/modules/by-name/lf/lf/ctpv/prev/torrent.sh
new file mode 100644
index 00000000..16cfcbcd
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/torrent.sh
@@ -0,0 +1,13 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+cache_f="$cache_f"
+
+. %HELPERS
+
+transmission-show -- "$f"
diff --git a/modules/by-name/lf/lf/ctpv/prev/video.sh b/modules/by-name/lf/lf/ctpv/prev/video.sh
new file mode 100644
index 00000000..e42e3612
--- /dev/null
+++ b/modules/by-name/lf/lf/ctpv/prev/video.sh
@@ -0,0 +1,17 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+# shellcheck disable=SC2269
+f="$f"
+# shellcheck disable=SC2269
+cache_f="$cache_f"
+
+. %HELPERS
+
+video() {
+    ffmpegthumbnailer -i "$f" -o "$cache_f" -s 0 -t 50% 2>/dev/null
+}
+
+convert_and_show_image video
diff --git a/modules/by-name/lf/lf/module.nix b/modules/by-name/lf/lf/module.nix
index 9ca98227..829c05cc 100644
--- a/modules/by-name/lf/lf/module.nix
+++ b/modules/by-name/lf/lf/module.nix
@@ -30,8 +30,11 @@ in {
     ];
 
     home-manager.users.soispha = {
-      xdg.configFile."lf/icons".source = ./icons;
-      xdg.configFile."lf/colors".source = ./colors;
+      xdg.configFile = {
+        "lf/icons".source = ./icons;
+        "lf/colors".source = ./colors;
+        "cptv/config".text = import ./ctpv {inherit pkgs sysLib lib;};
+      };
 
       programs.lf = {
         enable = true;
@@ -40,7 +43,7 @@ in {
 
         previewer = {
           keybinding = "i";
-          source = "${pkgs.ctpv}/bin/ctpv";
+          source = lib.getExe' pkgs.ctpv "ctpv";
         };
         settings = {
           # close the server, after the last client exits
@@ -67,8 +70,9 @@ in {
           shellopts = "-eu"; # e: exit on error; u: error for unset variables
         };
         extraConfig = ''
+          # Keep these here, to ensure they are the last lines of the lfrc file.
           &${pkgs.ctpv}/bin/ctpv -s $id
-          cmd on-quit %${pkgs.ctpv}/bin/ctpv -e $id
+          cmd on-quit %${lib.getExe' pkgs.ctpv "ctpv"} -e $id
           set cleaner ${pkgs.ctpv}/bin/ctpvclear
 
           # Dynamically generate the cd mappings.