From ebfb50b2fb5ebb00afafb3b97c7c7eebfaa40467 Mon Sep 17 00:00:00 2001
From: Luca Bilke <bilke@tralios.de>
Date: Thu, 23 May 2024 17:15:30 +0200
Subject: [PATCH] Update lfrc
---
.config/lf/colors | 2 +-
.config/lf/lfrc | 360 ++++++++++++++++++++++++------------
.config/lf/preview | 61 ------
.config/lf/preview/clean | 5 +
.config/lf/preview/preview | 137 ++++++++++++++
.config/lf/preview/vidthumb | 36 ++++
.config/lf/rifle.conf | 85 +++++++++
.config/lf/shortcutrc | 7 -
.config/lf/shortcuts | 22 +++
9 files changed, 526 insertions(+), 189 deletions(-)
delete mode 100755 .config/lf/preview
create mode 100755 .config/lf/preview/clean
create mode 100755 .config/lf/preview/preview
create mode 100755 .config/lf/preview/vidthumb
create mode 100644 .config/lf/rifle.conf
delete mode 100644 .config/lf/shortcutrc
create mode 100644 .config/lf/shortcuts
diff --git a/.config/lf/colors b/.config/lf/colors
index 17e8c99..eb37bfc 100644
--- a/.config/lf/colors
+++ b/.config/lf/colors
@@ -1,4 +1,4 @@
-# vim:ft=dircolors
+
# (This is not a dircolors file but it helps to highlight colors and comments)
# default values from dircolors
diff --git a/.config/lf/lfrc b/.config/lf/lfrc
index 7424576..a3f9707 100644
--- a/.config/lf/lfrc
+++ b/.config/lf/lfrc
@@ -1,17 +1,4 @@
-# Basic vars
-set ratios 1:2:4
-set shellopts '-eu'
-set ifs "\n"
-set findlen 1
-set scrolloff 10
-set icons
-set wrapscroll
-set period 1
-set previewer ~/.config/lf/preview
-# set cleaner ~/.config/lf/clean
-set cursorpreviewfmt "\033[7;90m"
-set promptfmt "\033[34;1m%u\033[36m@\033[34m%h \033[35m[\033[0;1m%d\033[35m]\033[32m » \033[33m%f\033[0m"
-
+# Functions
cmd open ${{
case $(file --mime-type "$(readlink -f $f)" -b) in
text/*|application/json|inode/x-empty) $EDITOR $fx;;
@@ -19,27 +6,18 @@ cmd open ${{
esac
}}
-cmd mkdir $mkdir -p "$(echo $* | tr ' ' '\ ')"
-
-cmd lazygit ${{
- clear
- if [ ! -e "$PWD/.git" ]; then
- echo "Not in a git repository. Create a new git repository? (y/n): "
- [ $(echo "Yes\nNo" | fzf) = "Yes" ] && git init && lazygit -p $PWD
- else
- lazygit -p $PWD
- fi
+cmd pushedit %{{
+ set +u
+ files=$1
+ [ -z $files ] && {
+ echo "Open: " && read -r files
+ echo
+ }
+ echo $files | xargs -r touch
+ lf -remote "send $id \$$OPENER $files"
}}
-cmd dupe %{{
- for file in $fx; do
- find "$PWD" "$file" -maxdepth 0 | grep -oP '(?<=.\.~)\d+(?=~$)' | sort -n | tail -1 | (
- ext=$(($(cat /dev/stdin)+1))
- filedest="$(echo "$file" | sed 's/.~[[:digit:]]*~$//').~$ext~"
- cp -r "$file" "$filedest"
- )
- done
-}}
+cmd open-with $mimeopen -a $f
cmd trash ${{
clear; tput cup $(($(tput lines)/3)); tput bold
@@ -55,20 +33,20 @@ cmd trash ${{
fi
}}
-cmd rsyncto ${{
- clear; tput cup $(($(tput lines)/3)); tput bold
- set -f
- clear; echo -n "rsync -azvhP <selected files> "
- read dest
- clear
- for x in $fx; do
- eval rsync -azvhP \"$x\" \"$dest\"
- done &&
- notify-send "File(s) rsynced." "File(s) copies to $dest."
+cmd trash-restore $trash-restore $PWD
+
+cmd lazygit %{{
+ dir=$(dirname "$(realpath "${f:-_}")"})
+ if ! git --noglob-pathspecs -C $dir status >/dev/null 2>&1; then
+ echo "Initialize git repo in '${dir}' [Y/n]:" && read yn &&
+ case $yn in
+ "" | [Yy]*) git -C ${dir} init >/dev/null 2>&1; break ;;
+ [Nn]*) ;;
+ esac
+ fi
+ lf -remote "send $id \$cd '$dir' && lazygit"
}}
-# y (select for copy) and P to paste soft-link
-# d (select for cut) and P to paste hard-link
cmd link &{{
set -- $(cat ~/.local/share/lf/files)
mode="$1"
@@ -78,9 +56,7 @@ cmd link &{{
exit 0
fi
case "$mode" in
- # symbolically copy mode is indicating a soft link
copy) ln -sr -t . -- "$@";;
- # while a move mode is indicating a hard link
move) ln -t . -- "$@";;
esac
rm ~/.local/share/lf/files
@@ -90,101 +66,245 @@ cmd link &{{
cmd bulkrename $vidir
cmd on-cd &{{
- printf "%b" "\033]0;$(zsh -c 'source $XDG_CONFIG_HOME/zsh/configs/autogenerated/hashes; print -Pn "$USER@$HOST [%3~]"') \007" > /dev/tty
- fmt="\033[34;1m%u\033[36m@\033[34m%h \033[35m[\033[0;1m$(zsh -c 'source $XDG_CONFIG_HOME/zsh/configs/autogenerated/hashes; print -Pn "%3~"')\033[35m]\033[32m » \033[33m%f\033[0m"
- lf -remote "send $id set promptfmt \"$fmt\""
+ lf -remote "send $id set promptfmt \"$(zsh -c 'source $ZDOTDIR/configs/prompt; source $ZDOTDIR/configs/hashes; print -P $LF_PROMPT')\""
+ printf "%b" "\033]0;$(zsh -c 'source $ZDOTDIR/configs/prompt; source $ZDOTDIR/configs/hashes; print -P $LF_TITLE')\007" > /dev/tty
}}
-on-cd
-cmd on-quit ${{
- DIR=$(echo $PWD | sed "s|$HOME|~|")
- printf "\033]0; $DIR\007" > /dev/tty
-}}
+cmd on-quit &printf "\033]0; $(echo $PWD | sed "s|$HOME|~|")\007" > /dev/tty
cmd paste &{{
set -- $(cat ~/.local/share/lf/files)
mode="$1"
shift
case "$mode" in
- copy)
- rsync -av --ignore-existing --progress -- "$@" . |
- stdbuf -i0 -o0 -e0 tr '\r' '\n' |
- while IFS= read -r line; do
- lf -remote "send $id echo $line"
+ copy)
+ rsync -aP --del -- "$@" . &
+ i=0
+ while ps -p "$!" >/dev/null; do
+ i=$(((i + 1) % 3))
+ dots=""
+ for i in $(seq 0 $i); do
+ dots="${dots}."
done
- ;;
- move) mv -n -- "$@" .;;
+ lf -remote "send $id echo 'Copying$dots'"
+ sleep 0.3
+ done
+ ;;
+ move) mv -n -- "$@" . ;;
esac
rm ~/.local/share/lf/files
lf -remote "send clear"
}}
-cmd fzfsearch ${{
- file="$(fzf)"
- [ -d $file ] && lf -remote "send $id cd $file" && return 0
- [ -f $file ] && lf -remote "send $id select $file"
+cmd dupe &{{
+ for file in $fx; do
+ find "$PWD" "$file" -maxdepth 0 | grep -oP '(?<=.\.~)\d+(?=~$)' | sort -n | tail -1 | (
+ ext=$(($(cat /dev/stdin)+1))
+ filedest="$(echo "$file" | sed 's/.~[[:digit:]]*~$//').~$ext~"
+ cp -r "$file" "$filedest"
+ )
+ done
}}
-cmd fzftags ${{
- file="$(cat ${XDG_DATA_HOME:-$HOME/.local/share}/lf/tags | sed 's/:\*$//' | fzf)"
- [ -d $file ] && lf -remote "send $id cd $file" && return 0
- [ -f $file ] && lf -remote "send $id select $file"
+
+cmd fzf ${{
+ name="$1" input="$2" delimiter="$3" field="$4" path_field="$5" width="$6" query="${7:-}"
+ histfile="$XDG_DATA_HOME/lf/$(echo $name | tr '[:upper:]' '[:lower:]')_history"
+
+ clear
+ file="$(eval "$input" | fzf \
+ --query "$query" \
+ --delimiter "$delimiter" \
+ --cycle \
+ --nth="$field" \
+ --with-nth="$field" \
+ --preview-window="right,$width" \
+ --bind="space:accept,focus:transform-preview-label(echo {} | cut -d '$delimiter' -f '$path_field')" \
+ --scheme='history' \
+ --history="$histfile" \
+ --header="$name" \
+ --preview='
+ file=$(echo {} | cut -d '$delimiter' -f '$path_field')
+ if [ -f "$file" ] && [ -r "$file" ]; then
+ head -$LINES "$file"
+ elif [ -d "$file" ] && [ -r "$file" ]; then
+ ls -pLHAN1 --color=always --group-directories-first "$file"
+ fi
+ ' |
+ cut -d "$delimiter" -f "$path_field" |
+ tr -d '\n'
+ )"
+ [ -d "$file" ] && lf -remote "send $id cd $file"
+ [ -f "$file" ] && lf -remote "send $id select $file"
+ return 0
}}
-cmd fzfmarks ${{
- file="$(cat ${XDG_DATA_HOME:-$HOME/.local/share}/lf/marks | sed 's/^.://' | fzf)"
- [ -d $file ] && lf -remote "send $id cd $file" && return 0
- [ -f $file ] && lf -remote "send $id select $file"
-}}
-cmd fzfshortcut ${{
- file="$(cat ${XDG_CONFIG_HOME:-$HOME/.config}/lf/shortcutrc | cut -d '"' -f2 | fzf)"
- [ -d $file ] && lf -remote "send $id cd $file" && return 0
- [ -f $file ] && lf -remote "send $id select $file"
-}}
-cmd fzfgrep ${{
- RG_PREFIX="rg --column --line-number --no-heading --color=always --smart-case "
+
+cmd find_word ${{
+ set +ue
+ RG_PREFIX="rg --hidden --column --line-number --no-heading --color=always --smart-case --follow --no-ignore "
res="$(
FZF_DEFAULT_COMMAND="$RG_PREFIX ''" \
- fzf --bind "change:reload:$RG_PREFIX {q} || true" \
- --ansi --layout=reverse --header 'Search in files' \
- | cut -d':' -f1 | sed 's/\\/\\\\/g;s/"/\\"/g'
+ fzf --bind "change:reload:$RG_PREFIX {q} || true" \
+ --ansi --layout=reverse --header 'Searching file contents' |\
+ grep -iv -e 'Trash/files' -e 'Trash/info'
)"
- [ -n "$res" ] && lf -remote "send $id select \"$res\""
+ file="$(realpath "$(echo "$res" | cut -d':' -f1 | sed 's/\\/\\\\/g;s/"/\\"/g')" 2>/dev/null)"
+ row="$(echo "$res" | cut -d':' -f2)"
+ column="$(echo "$res" | cut -d':' -f3)"
+ if [ -n "$res" ]; then
+ if { [ "$EDITOR" = "nvim" ] || [ "$EDITOR" = "vim" ]; } && [ -n "$EMBEDDED" ]; then
+ lf -remote "send $id \$$EDITOR +'call cursor($row, $column)' -- $([ -n "$EMBEDDED" ] && echo "--") '$file'"
+ else
+ lf -remote "send $id \$$EDITOR '$file'"
+ fi
+ fi
+ return 0
}}
+# cmd find_project ${{
+# dirs=$(echo $XDG_DOCUMENTS_DIR/dev/*/*)
+# histfile="$XDG_DATA_HOME/lf/project_history"
+#
+# clear
+# project="$(echo $dirs | xargs -n1 basename | fzf \
+# --cycle \
+# --preview-window="right,33%" \
+# --bind="space:accept,focus:transform-preview-label(echo {})" \
+# --scheme='history' \
+# --history="$histfile" \
+# --header="Projects" \
+# --preview='
+# f={}
+# file=$(echo $XDG_DOCUMENTS_DIR/dev/*/* | xargs -n1 | sed -n "/\/$f$/p")
+# if [ -f "$file" ] && [ -r "$file" ]; then
+# head -$LINES "$file"
+# elif [ -d "$file" ] && [ -r "$file" ]; then
+# ls -pLHAN1 --color=always --group-directories-first "$file"
+# fi
+# ' |
+# tr -d '\n'
+# )"
+# file=$(echo $dirs | xargs -n1 | sed -n "/\/$project$/p")
+# [ -d "$file" ] && lf -remote "send $id cd $file"
+# [ -f "$file" ] && lf -remote "send $id select $file"
+# return 0
+# }}
+
+cmd extract ${{
+ for f in $fx; do
+ aunpack "$f"
+ done
+}}
+
+# HACK: This is a dirty hack to have an lf terminal that I can "exit" out of into a shell
+# cmd new_lf_term &{{
+# mapcmd='map q $sh -c "tmux; kill $id"'
+# $TERMINAL -e lfX -command "$mapcmd"
+# }}
+
+cmd confirm_delete %{{
+ echo Delete? [y/N] && read -r v
+ echo
+ [ "$v" = y ] && rm -rf -- $fx
+}}
+
+on-cd
+
+# Basic vars
+set ratios 1:2:5
+set shellopts '-eu'
+set ifs "\n"
+set findlen 1
+set scrolloff 10
+set icons
+set wrapscroll
+set period 1
+set cursorpreviewfmt "\033[7;90m"
+set promptfmt # this is set in a function later
+set sixel
+set previewer ~/.config/lf/preview/preview
+set cleaner ~/.config/lf/preview/clean
+
# Bindings
-map <c-c>a fzfsearch
-map <c-c>t fzftags
-map <c-c>m fzfmarks
-map <c-c>f fzfshortcut
-map <c-c>g fzfgrep
-map T trash
-map <c-t> $trash-restore $PWD
-map <c-d> &rm -rf -- $fx
-map <c-e> $aunpack $fx
-map R rsyncto
-map P link
-map <c-g> lazygit
-map <c-v> push :!$EDITOR<space>
-map <c-n> push :mkdir<space>
-map <c-t> push :&touch<space>
-map <c-r> reload
-map <c-s> set hidden!
+clearmaps
+
+map <esc> quit
+map <space> :toggle; down
map <enter> shell
+map <a-enter> shell-wait
+# map <tab><tab> find_project
+map <tab>t fzf 'Tags' 'cat $XDG_DATA_HOME/lf/tags 2>/dev/null' ':' '1' '1' '50%'
+map <tab>m fzf 'Marks' 'cat $XDG_DATA_HOME/lf/marks 2>/dev/null' ':' '1' '2' '85%' '^'
+map <tab>f fzf 'Files' 'find -L $PWD' ':' '1' '1' '50%'
+map <tab>g find_word
+map "'" mark-load
+map '"' mark-remove
+map "$" shell
+map "!" shell-wait
+map "&" shell-async
+map "%" shell-pipe
+map ";" find-next
+map "," find-prev
+map "/" search
+map a :rename; cmd-end # rename from end
+map <c-b> page-up
+map b dupe
+map B bulkrename
+map <c-c> quit
+map c push r<c-u> # new rename
+map <c-d> confirm_delete
+map d cut
+# map D &dragon-drop -a -x $fx
+map <c-e> scroll-down
+map e :set user_multiedit "true" ; open; set user_multiedit "false"
+map E $sudo -e $f
+map f find
+map F find-back
+map <c-g> lazygit
+map <a-g> $gdu
+map gg top
+map g/ cd /
+# NOTE: g* is used for shortcuts generated by the shortcuts script
+source ~/.config/lf/shortcuts
+map G bottom
+map h updir
+map i :rename; cmd-home # rename from beginning
+map j down
+map k up
+map l open
+map m mark-save
+map <c-n> push :&mkdir<space>-p<space>
+map n search-next
+map N search-prev
+map o open-with
+map O $less $f
+map p paste
+map P link
+map q quit
+map <c-r> reload
+map r :rename # before extension
+map R $lf -remote "send $id :select \"$(readlink $f)\""
+map sh :set hidden!
+map sn :set sortby natural; set info
+map ss :set sortby size; set info size
+map st :set sortby time; set info time
+map sa :set sortby atime; set info atime
+map sc :set sortby ctime; set info ctime
+map se :set sortby ext; set info
+map <c-t> trash-restore
+map t tag-toggle
+map T trash
+map u :clear; unselect
+map <c-v> pushedit
+map v invert
+# map W new_lf_term
map x $$f
map X !$f
-map o &mimeopen $f
-map O $mimeopen -a $f
-map a :rename; cmd-home # rename from beginning
-map r :rename; cmd-end # rename from end
-map i :rename # before extension
-map c push r<c-u> # new rename
-map B bulkrename
-map b dupe
-map u :clear; unselect
-map n &echo $f | xclip -r -selection c
-map <esc> quit
-map g/ cd "/"
-map e $$EDITOR $f
-map E $sudo -e $f
-
-# Load bookmark shortcuts
-source "~/.config/lf/shortcutrc"
+map <c-y> scroll-down
+map y copy
+map Y &echo $f | xclip -r -selection c
+map zh set hidden!
+map zr set reverse!
+map zn set info
+map zs set info size
+map zt set info time
+map za set info size:time
diff --git a/.config/lf/preview b/.config/lf/preview
deleted file mode 100755
index 7499826..0000000
--- a/.config/lf/preview
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/env bash
-image() {
- f=$1
- w=$2
- h=$3
- x=$4
- y=$5
- chafa "$f" -f symbols -s "$((w-2))x$h" && exit 1
- echo -e "\e[31mImage previewer not installed\e[0m"
- exit 1
-}
-
-video() {
- f=$1
- w=$2
- h=$3
- x=$4
- y=$5
- thumb="$(vidthumb "$f")" || ( echo -e "\e[31mvidthumb script not in path\e[0m" && return 1 )
- image "$thumb" "$w" "$h" "$x" "$y"
- return 1
-}
-
-batorcat() {
- f=$1
- w=$2
- command -v bat > /dev/null 2>&1 && bat --color=always --style=plain --pager=never --terminal-width "$((w-2))" "$f" && exit 0
- command -v batcat > /dev/null 2>&1 && batcat --color=always --style=plain --pager=never --terminal-width "$((w-2))" "$f" && exit 0
- cat "$f" && exit 0
-}
-
-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}'))"
-
-case "$(xdg-mime query filetype "$1")" in
- */x-bzip-compressed-tar|*/x-compressed-tar|*/x-xz-compressed-tar) als -- "$1" && exit 0 || echo -e "\e[31matools not installed\e[0m" && exit 1;;
- */x-7z-compressed|*/vnd.rar|*/x-tar|*/zip|*/x-java-archive|*/x-xz) 7z l "$1" | sed 1,11d && exit 0 || echo -e "\e[31m7zip not installed\e[0m" && exit 1;;
- */x-cd-image) iso-info --no-header -l "$1" && exit 0 || echo -e "\e[31mlibcdio not installed\e[0m" && exit 1;;
- */x-bittorrent) transmission-show "$1" && exit 0 || echo -e "\e[31mtransmission-cli not installed\e[0m" && exit 1;;
- */vnd.sun.xml.writer) odt2txt "$1" && exit 0 || echo -e "\e[31modt2txt not installed\e[0m" && exit 1;;
- */msword) catdoc "$1" && exit 0 || echo -e "\e[31mcatdoc not installed\e[0m" && exit 1;;
- */vnd.openxmlformats-officedocument.wordprocessingml.document) docx2txt < "$1" && exit 0 || echo -e "\e[31mdocx2txt not installed\e[0m" && exit 1;;
- */vnd.ms-excel) ssconvert --export-type=Gnumeric_stf:stf_csv "$1" "fd://1" | batorcat --language=csv && exit 0 || echo -e "\e[31mgnumeric not installed\e[0m" && exit 1;;
- */vnd.openxmlformats-officedocument.spreadsheetml.sheet) ssconvert --export-type=Gnumeric_stf:stf_csv "$1" "fd://1" | batorcat --language=csv && exit 0 || echo -e "\e[31mgnumeric not installed\e[0m" && exit 1;;
- */epub+zip) [ ! -f "$CACHE" ] && epub-thumbnailer "$1" "$CACHE" 1024; image "$CACHE" "$2" "$3" "$4" "$5" && exit 0 || echo -e "\e[31mepubthumbnailer not installed (https://github.com/marianosimone/epub-thumbnailer)\e[0m" && exit 1;;
- */pgp-encrypted) gpg -d -- "$1" && exit 0 || echo -e "\e[31mgpg not installed\e[0m" && exit 1;;
- */pkix-cert) openssl x509 -text -noout -in "$1" && exit 0 || echo -e "\e[31mopenssl not installed\e[0m" && exit 1;;
- image/*) image "$1" "$2" "$3" "$4" "$5" ;;
- video/*) video "$1" "$2" "$3" "$4" "$5" ;;
- *opendocument*) odt2txt "$1" && exit 0 || echo -e "\e[31modt2txt not installed\e[0m" && exit 1;;
- */markdown) lowdown -Tterm "$1" && exit 0 || echo -e "\e[31mlowdown not installed \e[0m" && exit 1;;
- */html) lynx -dump "$1" && exit 0 || w3m -dump "$1" && exit 0 || echo -e "\e[31neither lynx nor w3m installed\e[0m" && exit 1;;
- text/*|*/json|*/xml) batorcat "$1" "$2" ;;
- */pdf) [ ! -f "${CACHE}.jpg" ] && pdftoppm -jpeg -f 1 -singlefile "$1" "$CACHE"; image "${CACHE}.jpg" "$2" "$3" "$4" "$5" && exit 0 || echo -e "\e[31mpoppler-utils/poppler not installed\e[0m" && exit 1;;
-esac
-case "$(file -bL --mime-type "$1")" in
- text/*) batorcat "$1" "$2" ;;
-esac
-xdg-mime query filetype "$1"
-mediainfo "$1"
-exit 1
-
diff --git a/.config/lf/preview/clean b/.config/lf/preview/clean
new file mode 100755
index 0000000..acab52f
--- /dev/null
+++ b/.config/lf/preview/clean
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ -n "$FIFO_UEBERZUG" ]; then
+ printf '{"action": "remove", "identifier": "PREVIEW"}\n' > "$FIFO_UEBERZUG"
+fi
diff --git a/.config/lf/preview/preview b/.config/lf/preview/preview
new file mode 100755
index 0000000..a9361a9
--- /dev/null
+++ b/.config/lf/preview/preview
@@ -0,0 +1,137 @@
+#!/bin/sh
+
+RED="\033[31m"
+RESET="\033[0m"
+
+set -C -f
+
+f="$(realpath "$1")" w=$2 h=$3 # x=$4 y=$5
+
+image() {
+ file=${1:-$f}
+ # shellcheck disable=2086
+ chafa -f sixel -s "${w}x${h}" --polite on --animate false "$file"
+ exit 0
+}
+
+video() {
+ thumb="$("$HOME/.config/lf/preview/vidthumb" "$f")" || {
+ printf "%b" "${RED}vidthumb failed to execute${RESET}"
+ return 1
+ }
+ image "$thumb"
+}
+
+text() {
+ bat --color=always --style=plain --pager=never --terminal-width "$((w - 2))" "$@" "$f"
+ exit 1
+}
+
+run() {
+ #shellcheck disable=SC2068
+ if ! command -v "$1" >/dev/null 2>&1; then
+ printf "%b" "${RED}Cannot execute ${1}${RESET}"
+ elif "$@"; then
+ :
+ else
+ printf "%b" "${RED}Failed to run command: ${RESET}"
+ for l in "$@"; do
+ printf "%b" "\n${RED} ${l}${RESET}"
+ done
+ fi
+}
+
+mimetest() {
+ case "$1" in
+ */pdf)
+ [ ! -f "${CACHE}.jpg" ] && run pdftoppm -jpeg -f 1 -singlefile "$f" "$CACHE"
+ image "${CACHE}.jpg"
+ ;;
+ */x-bzip-compressed-tar | */x-compressed-tar | */x-xz-compressed-tar)
+ run als -- "$f"
+ exit 1
+ ;;
+ */x-7z-compressed | */vnd.rar | */x-tar | */zip | */x-java-archive | */x-xz | */gzip)
+ run 7z l "$f" | sed 1,11d
+ exit 1
+ ;;
+ */x-cd-image)
+ run iso-info --no-header -l "$f"
+ exit 1
+ ;;
+ */x-bittorrent)
+ run transmission-show "$f"
+ exit 1
+ ;;
+ */vnd.sun.xml.writer)
+ run odt2txt "$f"
+ exit 1
+ ;;
+ */msword)
+ run catdoc "$f"
+ exit 1
+ ;;
+ */vnd.openxmlformats-officedocument.wordprocessingml.document)
+ run docx2txt <"$f"
+ exit 1
+ ;;
+ */vnd.ms-excel)
+ run ssconvert --export-type=Gnumeric_stf:stf_csv "$f" "fd://1" | text --language=csv
+ exit 1
+ ;;
+ */vnd.openxmlformats-officedocument.spreadsheetml.sheet)
+ run ssconvert --export-type=Gnumeric_stf:stf_csv "$f" "fd://1" | text --language=csv
+ exit 1
+ ;;
+ */epub+zip)
+ [ ! -f "$CACHE" ] && run epub-thumbnailer "$f" "$CACHE" 1024
+ image "$CACHE"
+ ;;
+ */pgp-encrypted)
+ run gpg -d -- "$f"
+ exit 1
+ ;;
+ */pkix-cert)
+ run openssl x509 -text -noout -in "$f"
+ exit 1
+ ;;
+ image/svg+xml)
+ [ ! -f "${CACHE}.png" ] && run inkscape --convert-dpi-method=none -o "${CACHE}.png" --export-overwrite -D --export-png-color-mode=RGBA_16 "$f"
+ image "${CACHE}.png"
+ ;;
+ image/*) image ;;
+ video/*) video ;;
+ *opendocument*)
+ run odt2txt "$f"
+ exit 1
+ ;;
+ */markdown)
+ run glow -s "$XDG_CONFIG_HOME/glow/style.json" "$f" --width "$w"
+ exit 1
+ ;;
+ */html)
+ run lynx -dump "$f"
+ exit 1
+ ;;
+ *) return 1 ;;
+ esac
+}
+
+CACHE="${XDG_CACHE_HOME}/lf/thumbnail-$(stat --printf '%n\0%i\0%F\0%s\0%W\0%Y' -- "$(readlink -f "$1")" | sha256sum | awk '{print $1}')"
+
+filerun="$(file --brief --dereference --mime-type "$f")"
+mimetest "$filerun" && exit 1
+
+if command -v gio 1>/dev/null 2>&1; then
+ giorun="$(gio info "$f" 2>/dev/null | grep standard::content-type | cut -d' ' -f4)"
+ mimetest "$giorun" && exit 1
+fi
+
+case "$(file -b "$f")" in
+ *text*) text ;;
+ *)
+ printf "%b" "\$(file --mime-type)\t\t\t : $filerun\n"
+ [ -n "$giorun" ] && printf "%b" "\$(gio info)\t\t\t\t : $giorun\n"
+ mediainfo "$1" | head -n -2 | grep -v -e "Complete name" -e "General"
+ ;;
+esac
diff --git a/.config/lf/preview/vidthumb b/.config/lf/preview/vidthumb
new file mode 100755
index 0000000..1056221
--- /dev/null
+++ b/.config/lf/preview/vidthumb
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+if ! [ -f "$1" ]; then
+ exit 1
+fi
+
+cache="$XDG_CACHE_HOME/lf"
+index="$cache/index.json"
+file="$(realpath "$1")"
+
+mkdir -p "$cache"
+
+if [ -f "$index" ]; then
+ thumbnail="$(jq -r ". \"$file\"" <"$index")"
+ if [ "$thumbnail" != "null" ]; then
+ if [ ! -f "$cache/$thumbnail" ]; then
+ exit 1
+ fi
+ echo "$cache/$thumbnail"
+ exit 0
+ fi
+fi
+
+thumbnail="$(uuidgen).jpg"
+
+if ! ffmpegthumbnailer -i "$file" -o "$cache/$thumbnail" -s 0 2>/dev/null; then
+ exit 1
+fi
+
+if [ ! -f "$index" ]; then
+ echo "{\"$file\": \"$thumbnail\"}" >"$index"
+fi
+json="$(jq -r --arg "$file" "$thumbnail" ". + {\"$file\": \"$thumbnail\"}" <"$index")"
+echo "$json" >"$index"
+
+echo "$cache/$thumbnail"
diff --git a/.config/lf/rifle.conf b/.config/lf/rifle.conf
new file mode 100644
index 0000000..6622ff8
--- /dev/null
+++ b/.config/lf/rifle.conf
@@ -0,0 +1,85 @@
+# vim: ft=cfg
+
+#-------------------------------------------
+# Environment checks
+#-------------------------------------------
+
+#-------------------------------------------
+# Websites
+#-------------------------------------------
+ext x?html?, has lynx, terminal = lynx -- "$@"
+ext x?html?, has w3m, terminal = w3m "$@"
+
+#-------------------------------------------
+# Misc
+#-------------------------------------------
+label editor, mime ^text|x-empty$ = ${VISUAL:-$EDITOR} -- "$@"
+label pager, mime ^text|x-empty$ = $PAGER -- "$@"
+label editor, ext xml|json|csv|tex|py|pl|rb|rs|js|sh|php|dart = ${VISUAL:-$EDITOR} -- "$@"
+label pager, ext xml|json|csv|tex|py|pl|rb|rs|js|sh|php|dart = $PAGER -- "$@"
+
+#--------------------------------------------
+# Audio without X
+#-------------------------------------------
+
+#--------------------------------------------
+# Video/Audio with a GUI
+#-------------------------------------------
+
+#--------------------------------------------
+# Video without X:
+#-------------------------------------------
+
+#-------------------------------------------
+# Documents
+#-------------------------------------------
+ext docx?, has catdoc, terminal = catdoc -- "$@" | $PAGER
+ext sc, has sc, = sc -- "$@"
+
+#-------------------------------------------
+# Images
+#-------------------------------------------
+
+#-------------------------------------------
+# Archives
+#-------------------------------------------
+ext 7z, has 7z = 7z -p l "$@" | $PAGER
+ext ace|ar|arc|bz2?|cab|cpio|cpt|deb|dgc|dmg|gz, has atool = atool --list --each -- "$@" | $PAGER
+ext iso|jar|msi|pkg|rar|shar|tar|tgz|xar|xpi|xz|zip, has atool = atool --list --each -- "$@" | $PAGER
+ext 7z|ace|ar|arc|bz2?|cab|cpio|cpt|deb|dgc|dmg|gz, has atool = atool --extract --each -- "$@"
+ext iso|jar|msi|pkg|rar|shar|tar|tgz|xar|xpi|xz|zip, has atool = atool --extract --each -- "$@"
+
+# Listing and extracting archives without atool:
+ext tar|gz|bz2|xz, has tar = tar vvtf "$1" | $PAGER
+ext tar|gz|bz2|xz, has tar = for file in "$@"; do tar vvxf "$file"; done
+ext bz2, has bzip2 = for file in "$@"; do bzip2 -dk "$file"; done
+ext zip, has unzip = unzip -l "$1" | less
+ext zip, has unzip = for file in "$@"; do unzip -d "${file%.*}" "$file"; done
+ext ace, has unace = unace l "$1" | less
+ext ace, has unace = for file in "$@"; do unace e "$file"; done
+ext rar, has unrar = unrar l "$1" | less
+ext rar, has unrar = for file in "$@"; do unrar x "$file"; done
+
+#-------------------------------------------
+# Fonts
+#-------------------------------------------
+
+#-------------------------------------------
+# Flag t fallback terminals
+#-------------------------------------------
+
+
+#-------------------------------------------
+# Fallback
+#-------------------------------------------
+else = ask
+label open, has xdg-open = xdg-open "$@"
+label open, has open = open -- "$@"
+
+######################################################################
+# The actions below are left so low down in this file on purpose, so #
+# they are never triggered accidentally. #
+######################################################################
+
+# Execute a file as program/script.
+mime application/x-executable = "$1"
diff --git a/.config/lf/shortcutrc b/.config/lf/shortcutrc
deleted file mode 100644
index de2cedc..0000000
--- a/.config/lf/shortcutrc
+++ /dev/null
@@ -1,7 +0,0 @@
-map gh cd "~"
-map gmn cd "/mnt"
-map g/ cd "/"
-map go cd "/opt"
-map ge cd "/etc"
-map gl cd "/var/log"
-map gt cd "/tank"
diff --git a/.config/lf/shortcuts b/.config/lf/shortcuts
new file mode 100644
index 0000000..3bddf01
--- /dev/null
+++ b/.config/lf/shortcuts
@@ -0,0 +1,22 @@
+# NOTE: Managed by shortcuts script
+map gcf cd ~/.config
+map gch cd ~/.cache
+map gco cd ~/Documents/dev
+map gdk cd ~/Desktop
+map gdl cd ~/Downloads
+map gdm cd ~/Documents
+map gds cd ~/.local/share/stow/dots
+map gdt cd ~/.local/share
+map ge cd /etc
+map gh cd ~
+map glo cd /usr/local
+map gle cd ~/.local/libexec
+map glg cd /var/log
+map gmn cd /mnt
+map gms cd ~/Music
+map gpc cd ~/Pictures
+map gr cd /
+map gsc cd ~/.local/bin
+map gst cd ~/.local/state
+map gsv cd ~/.local/sv
+map gvd cd ~/Videos