lfrc (10250B)
1 # vim: foldmethod=marker foldlevel=0 filetype=lfrc 2 # General settings {{{ 3 # interpreter for shell commands (needs to be POSIX compatible) 4 set shell bash 5 6 # set '-eu' options for shell commands 7 # These options are used to have safer shell commands. Option '-e' is used to 8 # exit on error and option '-u' is used to give error for unset variables. 9 # Option '-f' disables pathname expansion which can be useful when $f, $fs, and 10 # $fx variables contain names with '*' or '?' characters. However, this option 11 # is used selectively within individual commands as it can be limiting at 12 # times. 13 set shellopts '-eu' 14 15 # set internal field separator (IFS) to "\n" for shell commands 16 # This is useful to automatically split file names in $fs and $fx properly 17 # since default file separator used in these variables (i.e. 'filesep' option) 18 # is newline. You need to consider the values of these options and create your 19 # commands accordingly. 20 set ifs "\n" 21 22 # leave some space at the top and the bottom of the screen 23 set scrolloff 10 24 25 # Set a previewer 26 set previewer ~/.config/lf/preview 27 set preview 28 29 # General options 30 set ignorecase 31 set icons 32 set number 33 set relativenumber 34 35 # Show number of files in dirs instead of single size 36 set info size 37 set dircounts 38 # }}} 39 # Command definitions {{{ 40 # the prefix shows what kind of command it is 41 # $: runs as shell command 42 # %: runs as piped shell command (stdout => statusline) 43 # !: runs as interactive shell command (puts lf in the bg) 44 # :: runs as lf command 45 # 46 # commands run in the shell defined above, you can use $f, $fs, $fx vars. 47 # you can also send remote commands. 48 49 # define a custom 'open' command 50 cmd open $opener $fx 51 52 # define a custom 'rename' command without prompt for overwrite 53 cmd rename %[ -e $1 ] && printf "file exists" || mv $f $1 54 55 # rename multiple files the way nnn does it (open in editable buffer) 56 cmd batch_rename !{{ 57 contentsfile=$(mktemp) 58 trap 'rm $contentsfile' INT TERM EXIT 59 dircontents="$(command ls -1p)" 60 printf "%s" "$dircontents" | nl -n ln > "$contentsfile"; 61 $EDITOR "$contentsfile" 62 printf "%s" "$dircontents" | paste -d '\t' "$contentsfile" - \ 63 | while read -r line; do 64 orig="$(printf "%s" "$line" | cut -f3 | sed 's!/$!!')" 65 new="$(printf "%s" "$line" | cut -f2 | sed 's!/$!!')" 66 if [ "$new" != "$orig" ]; then 67 if [ -e "$new" ]; then 68 printf "%s already exists, not overwriting.\n" "$new" 69 else 70 printf "./%s -> ./%s\n" "$orig" "$new" 71 command mv -i ./"$orig" ./"$new" 72 fi 73 fi 74 done 75 rm "$contentsfile" 76 trap - INT TERM EXIT 77 }} 78 79 # change part of a filename using sed 80 cmd change %{{ 81 printf "Substitute: " 82 read -r sedcmd 83 mv "$f" "$(dirname "$f")/$(printf '%s' "$(basename "$f")" | sed "s$sedcmd")" 84 }} 85 86 # load audio files/playlists in mpd 87 cmd queue %{{ 88 for i in $fx; do 89 mpcq "$i" 90 done 91 }} 92 cmd queuenext %{{ 93 for i in $fx; do 94 case "$i" in 95 *.wav|*.flac|*.mp3|*.m4a|*.opus) 96 mpc -h ~/.local/share/mpd/socket insert "file://$i" 97 printf "Queued: %s" "$i" 98 ;; 99 *.m3u) 100 mpc -h ~/.local/share/mpd/socket load "file://$i" 101 printf "Loaded playlist: %s" "$i" 102 ;; 103 esac 104 done 105 }} 106 107 # extract the current file with the right command 108 # (xkcd link: https://xkcd.com/1168/) 109 cmd extract ${{ 110 set -f 111 case $f in 112 *.tar.bz|*.tar.bz2|*.tbz|*.tbz2) tar xjvf $f;; 113 *.tar.gz|*.tgz) tar xzvf $f;; 114 *.tar.xz|*.txz) tar xJvf $f;; 115 *.zip) unzip $f;; 116 *.rar) unrar x $f;; 117 *.7z) 7z x $f;; 118 *.jar) jar -xvf $f;; 119 *.tar) tar xvf $f;; 120 esac 121 }} 122 123 # copy the path of the highlighted file 124 # relies on my `clc` script 125 cmd copy_path ${{ 126 echo "$f" | tr -d '\n' | clc 127 }} 128 129 # zip directories/files 130 cmd zip ${{ 131 set -f 132 mkdir $f-zip 133 cp -r $fx $f-zip 134 (cd $f-zip/ && zip -r $f.zip .) 135 rm -rf $f-zip/ 136 }} 137 138 # tar directories/files 139 cmd tar ${{ 140 set -f 141 mkdir $f-tgz 142 cp -r $fx $f-tgz 143 (cd $f-tgz && tar cvzf $f.tar.gz .) 144 rm -rf $f-tgz 145 }} 146 147 # custom paste command using rsync/mv 148 cmd paste &{{ 149 load=$(cat ~/.local/share/lf/files) 150 mode=$(echo "$load" | sed -n '1p') 151 list=$(echo "$load" | sed '1d') 152 if [ $mode = 'copy' ]; then 153 rsync -av --ignore-existing --progress $list . \ 154 | stdbuf -i0 -o0 -e0 tr '\r' '\n' \ 155 | while read line; do 156 lf -remote "send $id echo $line" 157 done 158 elif [ $mode = 'move' ]; then 159 mv -n $list . 160 fi 161 lf -remote 'send load' 162 lf -remote 'send clear' 163 }} 164 165 # paste as a symbolic link to original 166 cmd paste_link %{{ 167 if [ "$(wc -l < ~/.local/share/lf/files)" -gt 1 ]; then 168 while read -r file; do 169 case "$file" in 170 copy|move) ;; 171 *) 172 ln -s "$file" . 173 ;; 174 esac 175 done < ~/.local/share/lf/files 176 else 177 lf -remote "send $id echo no files to link." 178 fi 179 }} 180 181 cmd paste_rename %{{ 182 mode="$(head -n 1 ~/.local/share/lf/files)" 183 for fname in $(tail -n +2 ~/.local/share/lf/files); do 184 while [ -z "${newfname:-}" ]; do 185 printf "%s => " "$fname" 186 read -r newfname 187 done 188 if [ "$mode" = 'copy' ]; then 189 cp -n "$fname" ./"$newfname" 190 else 191 mv -n "$fname" ./"$newfname" 192 fi 193 done 194 lf -remote 'send clear' 195 lf -remote 'send load' 196 }} 197 198 # preview the highlighted file with quicklook (macOS) 199 cmd ql_preview &{{ 200 qlmanage -p $fx &> /dev/null; 201 }} 202 203 # open the lfrc, and reload it after saving 204 cmd edit_config :{{ 205 $$EDITOR ~/.config/lf/lfrc 206 source ~/.config/lf/lfrc 207 }} 208 209 cmd z ${{ 210 set +u 211 if [ $# -gt 0 ]; then 212 dest='' 213 if command -v zoxide >/dev/null 2>&1; then 214 dest="$(zoxide query "$@")" 215 fi 216 217 if test -n "${dest}"; then 218 lf -remote "send $id cd '${dest}'" 219 fi 220 fi 221 }} 222 223 # trash command with confirmation 224 cmd trash %{{ 225 for f in $fx; do 226 printf "Trash $f? [Y/n/a] " 227 read -r ans 228 case "$ans" in 229 Y*|y*) trash "$f"; printf 'Deleted %s.\n' "$f";; 230 A*|a*) trash $fx; printf 'Deleted all files.\n'; break;; 231 esac 232 done 233 }} 234 235 # empty the trash 236 cmd trashempty %{{ 237 printf "Empty trash? [Y/n] " 238 read -r ans 239 case "$ans" in 240 Y*|y*) trash -ey; printf "Emptied.";; 241 *) printf "Not emptying.";; 242 esac 243 }} 244 245 # PGP functions 246 cmd pgp_encrypt_recipient %{{ 247 printf "Recipient: " 248 read -r recipient 249 case "$recipient" in 250 "") printf "Cancelled.";; 251 *) gpg --encrypt --sign --recipient "$recipient" $f;; 252 esac 253 }} 254 255 cmd pgp_encrypt_pass ${{ 256 gpg --symmetric $f; 257 }} 258 259 cmd pgp_decrypt ${{ 260 case "$f" in 261 *.gpg) outfile="${f%.gpg}";; 262 *.pgp) outfile="${f%.pgp}";; 263 *) outfile="decrypted-${f}";; 264 esac 265 gpg --output "$outfile" --decrypt "$f" 266 }} 267 268 # Encode input into binary or ASCII-armored output with an integrated signature 269 cmd pgp_sign ${{ 270 gpg --sign $f 271 }} 272 273 # Wrap input in plaintext signature 274 cmd pgp_sign_clear ${{ 275 gpg --clearsign $f 276 }} 277 278 # Create binary or ASCII-armored detached signature from input 279 cmd pgp_sign_detach ${{ 280 gpg --detach-sign $f 281 }} 282 283 # Select files based on glob filter 284 cmd glob-select-wrapper %{{ 285 printf "Filter: " 286 read -r filter_expr 287 lf -remote "send $id unselect" 288 lf -remote "send $id glob-select $filter_expr" 289 }} 290 291 # Remove empty directories in current tree 292 cmd rmempty %find . -type d -empty -depth -delete 293 294 # Use xld to transcode audio 295 cmd xld %open -a XLD $f 296 297 # fzf files 298 cmd fuzzy_select $lf -remote "send $id select \"$(fzf --layout reverse)\"" 299 300 # fuzzy grep files 301 cmd fuzzy_grep ${{ 302 fpath="$(rg --color=always --line-number --no-heading --smart-case "${*:-}" \ 303 | fzf --ansi --delimiter : --preview 'bat --color=always {1} --highlight-line {2}' --preview-window 'up,60%,border-bottom,+{2}+3/3,~3' --bind 'enter:become(printf "%s" {1})')" 304 lf -remote "send $id select $fpath" 305 }} 306 307 # Show file info with exiftool 308 cmd file_info $LESSOPEN='| exiftool %s' LESS='-cRiX' less $f 309 310 # Preview a file 311 cmd file_preview $LESSOPEN='| ~/.config/lf/preview %s' LESS='-cRiX' less $f 312 313 # Scroll parent up/down 314 cmd scroll_parent_up :{{ 315 updir; up 316 %[ -d "$f" ] && lf -remote "send $id open" 317 }} 318 319 cmd scroll_parent_down :{{ 320 updir; down 321 %[ -d "$f" ] && lf -remote "send $id open" 322 }} 323 324 cmd qrsend ${{ 325 clear 326 qrcp send $fx || { clear; qrcp send --interface en0 $fx; } 327 }} 328 # }}} 329 # Mappings {{{ 330 # Mouse 331 map <m-down> down 332 map <m-up> up 333 map <m-1> open 334 map <m-3> updir 335 336 # Enter commands 337 map ; push : 338 map S shell-pipe 339 340 # execute current file (must be executable) 341 map x $$f 342 map X !$f 343 344 # Disk usage 345 map ug %du -sh $f 346 347 # Open (uses the above-defined command) 348 map o open $fx 349 map <enter> open $fx 350 # Open containing dir 351 map O $open $(dirname $f) 352 353 # Listing 354 map r reload 355 map . set hidden! 356 map U redraw 357 358 # Selecting 359 map f fuzzy_select 360 map \\ fuzzy_grep 361 map <esc> unselect; clear 362 map <space> :toggle; down 363 map F glob-select-wrapper 364 map u 365 map uu unselect 366 map uy clear 367 map ud clear 368 map a :unselect; invert 369 370 # Show help 371 map g? $lf -doc | $PAGER; clear 372 373 # Renaming 374 map R push :rename<space> 375 map <c-r> batch_rename 376 map C change 377 map cw push :rename<space> 378 379 # <tab> == <c-i> 380 map <tab> jump-next 381 map <c-o> jump-prev 382 # Delete 383 map D trash 384 385 # Copy (others are defined by default) 386 map Y copy_path 387 388 # Paste 389 map p 390 map pp paste 391 map pl paste_link 392 map pr paste_rename 393 394 # Viewing 395 map i file_info 396 map P file_preview 397 map v ql_preview 398 map <c-v> :set preview!; reload 399 400 # Navigation 401 map z push :z 402 map [ scroll_parent_up 403 map ] scroll_parent_down 404 map gd. cd ~/Documents 405 map gds cd ~/Documents/School 406 map gdw cd ~/Documents/Syncthing/alex.balgavy.eu/ 407 map gdb cd ~/Documents/Syncthing/blog.alex.balgavy.eu/ 408 map gdl cd ~/Documents/Syncthing/lectures.alex.balgavy.eu/ 409 map gb cd ~/Documents/Calibre\ Library/ 410 map gdp cd ~/Documents/Syncthing/Personal\ documents/ 411 map gD cd ~/Desktop 412 map gl cd ~/Downloads 413 map gw cd ~/Documents/Syncthing/vimwiki 414 map gm cd ~/Music/Libraries/Mine 415 map g/ cd / 416 map g. cd $DOTFILES 417 map gv cd /Volumes 418 map gt cd ~/.Trash/ 419 420 # Creating 421 map c 422 map cf push %touch<space> 423 map cd push %mkdir<space> 424 425 # Editing 426 map e 427 map E $$EDITOR $fx 428 map ee $$EDITOR $f 429 map ec edit_config 430 map ce edit_config 431 432 map Q queue 433 434 # Compressing 435 map t 436 map * tag-toggle 437 map tz zip 438 map tt tar 439 map tu extract 440 441 map td &ripdrag $fx 442 443 # PGP 444 map tp 445 map tpe pgp_encrypt_recipient 446 map tpp pgp_encrypt_pass 447 map tpd pgp_decrypt 448 map tps. pgp_sign 449 map tpsc pgp_sign_clear 450 map tpsd pgp_sign_detach 451 452 map tq qrsend