diff options
Diffstat (limited to 'files')
38 files changed, 784 insertions, 197 deletions
diff --git a/files/.config/nnn/plugins/.iconlookup b/files/.config/nnn/plugins/.iconlookup index 49b4764..453110b 100755 --- a/files/.config/nnn/plugins/.iconlookup +++ b/files/.config/nnn/plugins/.iconlookup @@ -329,7 +329,7 @@ awk 'BEGIN { if ($0 ~/^\.$/) next ent = ($0 ~/^\.\//) ? substr($0, 3, length($0) - 2) : $0 - ext = $NF + ext = ($NF ~/\*$/) ? substr($NF, 1, length($NF) - 1) : $NF # Print icons, set color and bold directories by using ansi escape codes if (ext in icons) diff --git a/files/.config/nnn/plugins/.nmv b/files/.config/nnn/plugins/.nmv index eaebda6..bc3727f 100755 --- a/files/.config/nnn/plugins/.nmv +++ b/files/.config/nnn/plugins/.nmv @@ -31,8 +31,10 @@ case "$NNN_TRASH" in RM_UTIL="trash-put" ;; 2) RM_UTIL="gio trash" ;; + "") + RM_UTIL="rm -ri --" ;; *) - RM_UTIL="rm -ri" ;; + RM_UTIL="$NNN_TRASH" ;; esac exit_status=0 @@ -64,7 +66,7 @@ lines=$(printf "%s\n" "$arr" | wc -l) width=${#lines} dst_file=$(mktemp "$TMPDIR/.nnnXXXXXX") -trap 'rm -f "$dst_file"' EXIT +trap 'rm -f -- "$dst_file"' EXIT printf "%s" "$arr" | awk '{printf("%'"${width}"'d %s\n", NR, $0)}' > "$dst_file" @@ -122,7 +124,7 @@ while read -r num name; do tmp="$tmp~$c" done - if mv "$name" "$tmp"; then + if mv -- "$name" "$tmp"; then if [ "$VERBOSE" -ne 0 ]; then printf "'%s' -> '%s'\n" "$name" "$tmp" fi @@ -133,6 +135,7 @@ while read -r num name; do for key in "${!items[@]}"; do if [ "${items[$key]}" = "$name" ]; then + # shellcheck disable=2004 items[$key]="$tmp" fi done @@ -142,12 +145,13 @@ while read -r num name; do if [ ! -d "$dir" ] && ! mkdir -p "$dir"; then printf "%s: failed to create directory tree %s\n" "$0" "$dir" > /dev/stderr exit_status=1 - elif ! mv -i "$src" "$name"; then + elif ! mv -i -- "$src" "$name"; then printf "%s: failed to rename %s to %s: %s\n" "$0" "$name" "$tmp" "$!" > /dev/stderr exit_status=1 else if [ -d "$name" ]; then for key in "${!items[@]}"; do + # shellcheck disable=2004 items[$key]=$(printf "%s" "${items[$key]}" | sed "s|^$src\(\$\|\/\)|$name\1|") done diff --git a/files/.config/nnn/plugins/.npreview b/files/.config/nnn/plugins/.npreview new file mode 100755 index 0000000..d63db1b --- /dev/null +++ b/files/.config/nnn/plugins/.npreview @@ -0,0 +1,135 @@ +#!/usr/bin/env sh + +# Description: Preview plugin for nnn's built-in preview pane +# Auto-detected from plugins dir +# Usage: .npreview <filepath> <width> <height> +# All dependencies optional — graceful fallback to head/file/strings + +set -euf + +F="$1" +W="${2:-80}" +H="${3:-25}" +ext="${F##*.}" +ext="$(printf "%s" "$ext" | tr '[:upper:]' '[:lower:]')" + +has() { type "$1" >/dev/null 2>&1; } +hd() { head -n "$H"; } + +# --- Handlers --- + +show_dir() { + has tree && { tree -L 1 -n --dirsfirst --noreport "$F" | hd; return; } + find "$F" -maxdepth 1 -print 2>/dev/null | hd +} + +show_text() { + has bat && { bat --style=plain --color=never --paging=never --line-range=":${H}" -- "$F" 2>/dev/null; return; } + has batcat && { batcat --style=plain --color=never --paging=never --line-range=":${H}" -- "$F" 2>/dev/null; return; } + head -n "$H" "$F" +} + +show_pdf() { + has pdftotext && { pdftotext -l 1 -nopgbrk -q -- "$F" - 2>/dev/null | hd; return; } + has mutool && { mutool draw -F txt -i -- "$F" 1 2>/dev/null | hd; return; } + show_meta +} + +show_archive() { + case "$ext" in + rar) has unrar && { unrar lt -p- -- "$F" 2>/dev/null | hd; return; } ;; + 7z) has 7z && { 7z l -p -- "$F" 2>/dev/null | hd; return; } ;; + esac + has atool && { atool --list -- "$F" 2>/dev/null | hd; return; } + has bsdtar && { bsdtar --list --file "$F" 2>/dev/null | hd; return; } + has tar && { tar tf "$F" 2>/dev/null | hd; return; } + has unzip && [ "$ext" = "zip" ] && { unzip -l "$F" 2>/dev/null | hd; return; } + printf "[archive %s]\n" "$(du -h "$F" 2>/dev/null | cut -f1)" +} + +show_image() { + has img2txt && { img2txt --gamma=0.6 --width="$W" -- "$F" 2>/dev/null | hd; return; } + show_meta +} + +show_meta() { + has exiftool && { exiftool "$F" 2>/dev/null | hd; return; } + has mediainfo && { mediainfo "$F" 2>/dev/null | hd; return; } + has file && { file -b "$F"; return; } + printf "[no metadata tool]\n" +} + +show_json() { + has jq && { head -c 65536 "$F" | jq --monochrome-output . 2>/dev/null | hd; return; } + has python3 && { head -c 65536 "$F" | python3 -m json.tool 2>/dev/null | hd; return; } + show_text +} + +show_md() { + has glow && { glow -s notty "$F" 2>/dev/null | hd; return; } + has lowdown && { lowdown -Tterm "$F" 2>/dev/null | hd; return; } + show_text +} + +show_html() { + has w3m && { w3m -dump "$F" 2>/dev/null | hd; return; } + has lynx && { lynx -dump -- "$F" 2>/dev/null | hd; return; } + show_text +} + +show_elf() { + has readelf && { readelf -h "$F" 2>/dev/null | hd; return; } + has objdump && { objdump -f "$F" 2>/dev/null | hd; return; } + has file && file -b "$F" +} + +show_doc() { + has odt2txt && { odt2txt "$F" 2>/dev/null | hd; return; } + show_meta +} + +show_bin() { + has strings && { printf "[binary]\n"; strings "$F" 2>/dev/null | hd; return; } + printf "[binary %s]\n" "$(du -h "$F" 2>/dev/null | cut -f1)" +} + +# --- Directory --- +[ -d "$F" ] && { show_dir; exit 0; } + +# --- Dispatch by extension --- +case "$ext" in + a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|\ + rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tz|tzo|war|xpi|xz|z|zip|rar|7z|zst) + show_archive; exit 0 ;; + pdf) show_pdf; exit 0 ;; + md|mkd|markdown) show_md; exit 0 ;; + htm|html|xhtml) show_html; exit 0 ;; + json) show_json; exit 0 ;; + odt|ods|odp|sxw) show_doc; exit 0 ;; + torrent) has transmission-show && { transmission-show -- "$F" 2>/dev/null | hd; exit 0; } ;; + sqlite|sqlite3|db) has sqlite3 && { printf ".tables\n" | sqlite3 "$F" 2>/dev/null | hd; exit 0; } ;; + o|so|dylib) show_elf; exit 0 ;; + c|cc|cpp|h|hpp|rs|go|py|rb|js|ts|java|sh|bash|zsh|pl|lua|vim|el|\ + css|scss|yaml|yml|toml|ini|conf|xml|sql|diff|patch|awk|sed|make) + show_text; exit 0 ;; +esac + +# --- Dispatch by mime type --- +has file || { show_text; exit 0; } +mime="$(file -bL --mime-type -- "$F" 2>/dev/null)" + +case "$mime" in + text/*|*/xml) show_text ;; + application/json) show_json ;; + application/pdf) show_pdf ;; + application/zip|application/x-tar|application/x-rar*|\ + application/x-7z*|application/x-bzip*|application/x-xz|\ + application/x-compress*|application/gzip|application/zstd) + show_archive ;; + image/*) show_image ;; + audio/*|video/*) show_meta ;; + application/x-executable|application/x-sharedlib|application/x-pie-executable|\ + application/x-object) show_elf ;; + application/vnd.openxmlformats*|application/vnd.oasis.opendocument*) show_doc ;; + *) show_bin ;; +esac diff --git a/files/.config/nnn/plugins/autojump b/files/.config/nnn/plugins/autojump index 6a24a52..795c434 100755 --- a/files/.config/nnn/plugins/autojump +++ b/files/.config/nnn/plugins/autojump @@ -15,7 +15,7 @@ # to make z.lua work, you need to set $NNN_ZLUA to the path of script z.lua # # Shell: POSIX compliant -# Authors: Marty Buchaus, Dave Snider, Tim Adler, Nick Waywood +# Authors: Marty Buchaus, Dave Snider, Tim Adler, Nick Waywood, Markus Meier if [ ! -p "$NNN_PIPE" ]; then printf 'ERROR: NNN_PIPE is not set!' @@ -24,33 +24,35 @@ if [ ! -p "$NNN_PIPE" ]; then fi if type jump >/dev/null 2>&1; then - printf "jump to : " + printf "jump to: " IFS= read -r line # shellcheck disable=SC2086 odir="$(jump cd ${line})" printf "%s" "0c$odir" > "$NNN_PIPE" elif type autojump >/dev/null 2>&1; then - printf "jump to : " + printf "jump to: " read -r dir odir="$(autojump "$dir")" printf "%s" "0c$odir" > "$NNN_PIPE" elif type zoxide >/dev/null 2>&1; then if type fzf >/dev/null 2>&1; then - odir="$(zoxide query -i --)" - printf "%s" "0c$odir" > "$NNN_PIPE" + odir="$(zoxide query -i --)" + printf "%s" "0c$odir" > "$NNN_PIPE" else - printf "jump to : " - read -r dir - odir="$(zoxide query -- "$dir")" - printf "%s" "0c$odir" > "$NNN_PIPE" + printf "jump to: " + read -r dir + odir="$(zoxide query -- "$dir")" + printf "%s" "0c$odir" > "$NNN_PIPE" fi elif type lua >/dev/null 2>&1 && [ -n "$NNN_ZLUA" ]; then - printf "jump to : " - read -r line if type fzf >/dev/null 2>&1; then - odir="$(lua "$NNN_ZLUA" -l "$line" | fzf --nth 2.. --reverse --inline-info --tac +s -e --height 35%)" - printf "%s" "0c$(echo "$odir" | awk '{print $2}')" > "$NNN_PIPE" + odir="$(lua "$NNN_ZLUA" -l \ + | awk '{print $2}' \ + | fzf --nth -1 --delimiter=/ --reverse --inline-info --tac +s -e --height 35%)" + printf "0c%s" "$odir" > "$NNN_PIPE" else + printf "jump to: " + read -r line odir="$(lua "$NNN_ZLUA" -e "$line")" printf "%s" "0c$odir" > "$NNN_PIPE" fi diff --git a/files/.config/nnn/plugins/bulknew b/files/.config/nnn/plugins/bulknew index 64331e4..7780961 100755 --- a/files/.config/nnn/plugins/bulknew +++ b/files/.config/nnn/plugins/bulknew @@ -29,4 +29,4 @@ $EDITOR "$tmpfile" sed "/^\//d" "$tmpfile" | xargs -n1 -I{} sh -c "$cmd" -rm "$tmpfile" +rm -- "$tmpfile" diff --git a/files/.config/nnn/plugins/cbcopy-mac b/files/.config/nnn/plugins/cbcopy-mac new file mode 100755 index 0000000..a117a72 --- /dev/null +++ b/files/.config/nnn/plugins/cbcopy-mac @@ -0,0 +1,16 @@ +#!/usr/bin/osascript + +# Description: Copy the hovered file to MacOS clipboard. +# +# Note: Supports only MacOS +# +# Shell: POSIX compliant +# Author: Syed Umar Anis + + +on run args + set filePath to (second item of args & "/" & first item of args) + tell application "Finder" + set the clipboard to (filePath as POSIX file) + end tell +end diff --git a/files/.config/nnn/plugins/cbpaste-mac b/files/.config/nnn/plugins/cbpaste-mac new file mode 100755 index 0000000..5edf9c6 --- /dev/null +++ b/files/.config/nnn/plugins/cbpaste-mac @@ -0,0 +1,24 @@ +#!/usr/bin/env sh +# shellcheck disable=all + +# Description: Paste the clipboard files into the current directory. +# Only works if clipboard contents are files. +# +# Note: Supports only MacOS +# +# Shell: POSIX compliant +# Author: Syed Umar Anis + + +fs=($( osascript -e "use framework \"Foundation\" + property this : a reference to the current application + property NSPasteboard : a reference to NSPasteboard of this + property NSURL : a reference to NSURL of this + property pb : a reference to NSPasteboard's generalPasteboard + + property text item delimiters : linefeed + + pb's readObjectsForClasses:[NSURL] options:[] + (result's valueForKey:\"path\") as list as text" )) + +cp -R -- "${fs[@]}" "$2/" diff --git a/files/.config/nnn/plugins/chksum b/files/.config/nnn/plugins/chksum index 9441cc1..68aeec4 100755 --- a/files/.config/nnn/plugins/chksum +++ b/files/.config/nnn/plugins/chksum @@ -48,7 +48,7 @@ fi if [ "$resp" = "s" ]; then checksum_type - sed 's|'"$PWD/"'||g' < "$selection" | xargs -0 -I{} ${chsum}sum {} > "checksum_$(date '+%Y%m%d%H%M').$chsum" + sed 's|'"$PWD/"'||g' < "$selection" | xargs -0 -I{} "${chsum}sum" {} > "checksum_$(date '+%Y%m%d%H%M').$chsum" # Clear selection if [ -p "$NNN_PIPE" ]; then @@ -66,10 +66,10 @@ elif [ -n "$1" ]; then done checksum_type file=$(basename "$1").$chsum - ${chsum}sum "$1" > "$file" + "${chsum}"sum "$1" > "$file" elif [ -d "$1" ]; then checksum_type file=$(basename "$1").$chsum - find "$1" -type f -exec ${chsum}sum "{}" + > "$file" + find "$1" -type f -exec "${chsum}sum" "{}" + > "$file" fi fi diff --git a/files/.config/nnn/plugins/diffs b/files/.config/nnn/plugins/diffs index 0464781..16adc4b 100755 --- a/files/.config/nnn/plugins/diffs +++ b/files/.config/nnn/plugins/diffs @@ -25,7 +25,7 @@ dirdiff() { ls -A1 "$1" > "$dir1" ls -A1 "$2" > "$dir2" $diffcmd "$dir1" "$dir2" - rm "$dir1" "$dir2" + rm -- "$dir1" "$dir2" } if [ -s "$selection" ]; then diff --git a/files/.config/nnn/plugins/dragdrop b/files/.config/nnn/plugins/dragdrop index 812f970..01e4d19 100755 --- a/files/.config/nnn/plugins/dragdrop +++ b/files/.config/nnn/plugins/dragdrop @@ -1,11 +1,12 @@ #!/usr/bin/env sh - # Description: Open a Drag and drop window, to drop files onto other programs. # Also provides drag and drop window for files. # -# Dependencies: dragon - https://github.com/mwh/dragon +# Dependencies: +# - dragon (https://github.com/mwh/dragon), or +# - kitty (https://github.com/kovidgoyal/kitty) # -# Notes: +# Notes if using dragon: # 1. Files that are dropped will be added to nnn's selection # Some web-based files will be downloaded to current dir # with curl and it may overwrite some existing files @@ -14,6 +15,9 @@ # Shell: POSIX compliant # Author: 0xACE +# If you want system notification, put this equal to 1 +notify=0 + selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection} resp=f all= @@ -21,16 +25,18 @@ if type dragon-drag-and-drop >/dev/null 2>&1; then dnd="dragon-drag-and-drop" elif type dragon-drop >/dev/null 2>&1; then dnd="dragon-drop" +elif [ "$TERM" = "xterm-kitty" ]; then + dnd="kitten dnd" else dnd="dragon" fi -add_file () +add_file() { - printf '%s\0' "$@" >> "$selection" + printf '%s\0' "$@" >>"$selection" } -use_all () +use_all() { printf "mark --all (a) [default=none]: " read -r resp @@ -52,26 +58,58 @@ else fi fi -if [ "$resp" = "s" ]; then - use_all - sed -z 's|'"$PWD/"'||g' < "$selection" | xargs -0 "$dnd" "$all" & -elif [ "$resp" = "d" ]; then - use_all - "$dnd" "$all" "$PWD/"* & -elif [ "$resp" = "r" ]; then - true > "$selection" - "$dnd" --print-path --target | while read -r f - do - if printf "%s" "$f" | grep '^\(https\?\|ftps\?\|s\?ftp\):\/\/' ; then - curl -LJO "$f" - add_file "$PWD/$(basename "$f")" +clear_tui() +{ + pid=$! + reset # nnn to dnd + wait $pid + reset # dnd to nnn +} + +if [ "$dnd" = "kitten dnd" ]; then + if [ "$resp" = "s" ]; then + # shellcheck disable=SC2086 + xargs -0 $dnd 2>/dev/null <"$selection" & + elif [ "$resp" = "d" ]; then + $dnd "$PWD/"* 2>/dev/null & + else # send one or receive + $dnd "$1" 2>/dev/null & + fi + + clear_tui + + if [ "$resp" = "s" ]; then + [ -p "$NNN_PIPE" ] && printf "-" >"$NNN_PIPE" # clear selection + fi +else + if [ "$resp" = "s" ]; then + use_all + sed -z 's|'"$PWD/"'||g' <"$selection" | xargs -0 "$dnd" "$all" 2>/dev/null & + elif [ "$resp" = "d" ]; then + use_all + "$dnd" "$all" "$PWD/"* 2>/dev/null & + elif [ "$resp" = "r" ]; then + true >"$selection" + "$dnd" --print-path --target 2>/dev/null | while read -r f; do + if printf "%s" "$f" | grep -q '^\(https\?\|ftps\?\|s\?ftp\)://'; then + if output=$(curl -fsLJOS "$f" 2>&1); then + filename="$(basename "${f%%\?*}")" + add_file "$PWD/$filename" + if [ $notify = 1 ]; then + notify-send "Download Complete" "Finished downloading $filename" + fi + else + if [ $notify = 1 ]; then + notify-send "Download Failed" "$output" + else + echo "Download Failed: $output" + fi + fi elif [ -e "$f" ]; then - add_file "$f" + add_file "$f" fi - done & -else - if [ -n "$1" ] && [ -e "$1" ]; then - "$dnd" "$1" & + done & + elif [ -n "$1" ] && [ -e "$1" ]; then + "$dnd" "$1" 2>/dev/null & fi fi - diff --git a/files/.config/nnn/plugins/dups b/files/.config/nnn/plugins/dups index 27c1807..d402367 100755 --- a/files/.config/nnn/plugins/dups +++ b/files/.config/nnn/plugins/dups @@ -58,13 +58,13 @@ read -r force if [ "$force" = "f" ]; then #shellcheck disable=SC2016 - sed -e "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -f "$0" "$@" </dev/tty' + sed -e "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -f -- "$0" "$@" </dev/tty' else #shellcheck disable=SC2016 - sed -e "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -i "$0" "$@" </dev/tty' + sed -e "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -i -- "$0" "$@" </dev/tty' fi -rm "$tmpfile" +rm -- "$tmpfile" printf "Press any key to exit" read -r _ diff --git a/files/.config/nnn/plugins/finder b/files/.config/nnn/plugins/finder index bdd2e69..fc85c33 100755 --- a/files/.config/nnn/plugins/finder +++ b/files/.config/nnn/plugins/finder @@ -84,6 +84,6 @@ if [ -n "$fexpr" ]; then if [ -n "$fexpr" ]; then tail -n"$NNN_FINDHISTLEN" "$NNN_FINDHIST" > "$TMPDIR/finderbms" printf "%s\n" "$fexpr" >> "$TMPDIR/finderbms" - mv "$TMPDIR/finderbms" "$NNN_FINDHIST" + mv -- "$TMPDIR/finderbms" "$NNN_FINDHIST" fi fi diff --git a/files/.config/nnn/plugins/fixname b/files/.config/nnn/plugins/fixname index 4047152..2b0ec1b 100755 --- a/files/.config/nnn/plugins/fixname +++ b/files/.config/nnn/plugins/fixname @@ -65,7 +65,7 @@ for i in "${targets[@]}"; do if [ -e "$(cleanup "$i")" ]; then tmp='_' fi - mv "$i" "$tmp$(cleanup "$i")"; + mv -- "$i" "$tmp$(cleanup "$i")"; fi done diff --git a/files/.config/nnn/plugins/fzcd b/files/.config/nnn/plugins/fzcd index 125092c..35fae7e 100755 --- a/files/.config/nnn/plugins/fzcd +++ b/files/.config/nnn/plugins/fzcd @@ -60,7 +60,7 @@ if [ -n "$LIST" ]; then # Alternative for 'fd' # sel=$(xargs -d '\n' < "$tmpfile" fd . | fzf --delimiter / --tiebreak=begin --info=hidden) - rm "$tmpfile" + rm -- "$tmpfile" else printf "find missing" read -r _ diff --git a/files/.config/nnn/plugins/fzhist b/files/.config/nnn/plugins/fzhist index 111bc22..de10c2a 100755 --- a/files/.config/nnn/plugins/fzhist +++ b/files/.config/nnn/plugins/fzhist @@ -3,7 +3,9 @@ # Description: Fuzzy find a command from history, # edit in $EDITOR and run as a command # -# Note: Supports only bash and fish history +# Note: Supports only bash, zsh and fish history +# +# TODO: For zsh there's also $ZDOTDIR which might need to be checked as well for the -z $HISTFILE && -n $ZDOTDIR case. # # Shell: POSIX compliant # Author: Arun Prakash Jana @@ -17,7 +19,18 @@ fi shellname="$(basename "$SHELL")" if [ "$shellname" = "bash" ]; then - hist_file="$HOME/.bash_history" + if [ -f "$HISTFILE" ]; then + hist_file="$HISTFILE" + else + hist_file="$HOME/.bash_history" + fi + entry="$("$fuzzy" < "$hist_file")" +elif [ "$shellname" = "zsh" ]; then + if [ -f "$HISTFILE" ]; then + hist_file="$HISTFILE" + else + hist_file="$HOME/.zsh_history" + fi entry="$("$fuzzy" < "$hist_file")" elif [ "$shellname" = "fish" ]; then hist_file="$HOME/.local/share/fish/fish_history" @@ -33,7 +46,7 @@ if [ -n "$entry" ]; then $SHELL -c "$(cat "$tmpfile")" fi - rm "$tmpfile" + rm -- "$tmpfile" printf "Press any key to exit" read -r _ diff --git a/files/.config/nnn/plugins/fzopen b/files/.config/nnn/plugins/fzopen index 17b0585..4303dc3 100755 --- a/files/.config/nnn/plugins/fzopen +++ b/files/.config/nnn/plugins/fzopen @@ -59,25 +59,27 @@ if [ "$3" ]; then exit 0 fi -if [ "$USE_NUKE" -ne 0 ]; then - "$NUKE" "$entry" - exit 0 -fi +if [ "$entry" ]; then + if [ "$USE_NUKE" -ne 0 ]; then + "$NUKE" "$entry" + exit 0 + fi -# Open the file (works for a single file only) -cmd_file="" -cmd_open="" -if uname | grep -q "Darwin"; then - cmd_file="file -bIL" - cmd_open="open" -else - cmd_file="file -biL" - cmd_open="xdg-open" -fi + # Open the file (works for a single file only) + cmd_file="" + cmd_open="" + if uname | grep -q "Darwin"; then + cmd_file="file -bIL" + cmd_open="open" + else + cmd_file="file -biL" + cmd_open="xdg-open" + fi -case "$($cmd_file "$entry")" in - *text*) - "${VISUAL:-$EDITOR}" "$entry" ;; - *) - $cmd_open "$entry" >/dev/null 2>&1 ;; -esac + case "$($cmd_file "$entry")" in + *text*) + "${VISUAL:-$EDITOR}" "$entry" ;; + *) + $cmd_open "$entry" >/dev/null 2>&1 ;; + esac +fi diff --git a/files/.config/nnn/plugins/fzplug b/files/.config/nnn/plugins/fzplug index 11dcf7f..1069f43 100755 --- a/files/.config/nnn/plugins/fzplug +++ b/files/.config/nnn/plugins/fzplug @@ -34,7 +34,7 @@ if type bat >/dev/null; then BAT="bat --terminal-width='$(tput cols)' --decorations=always --color=always --style='${BAT_STYLE:-header,numbers}'" fi -plugin=$(find "$nnnpluginsdir" "$CUSTOMDIR1" "$CUSTOMDIR2" \ +plugin=$(find -L "$nnnpluginsdir" "$CUSTOMDIR1" "$CUSTOMDIR2" \ -maxdepth 3 -perm -111 -type f 2>/dev/null | fzf --ansi --preview \ "${BAT:-cat} {}" --preview-window="right:66%:wrap" --delimiter / \ --with-nth -1 --bind="?:toggle-preview") diff --git a/files/.config/nnn/plugins/getplugs b/files/.config/nnn/plugins/getplugs index 361a605..30dbf7b 100755 --- a/files/.config/nnn/plugins/getplugs +++ b/files/.config/nnn/plugins/getplugs @@ -24,7 +24,7 @@ prompt () { if [ "$operation" = "m" ]; then op="merge" elif [ "$operation" = "o" ]; then - op="cp -vRf" + op="cp -vRf --" else op="true" fi @@ -62,7 +62,7 @@ for f in $(find . -maxdepth 1 \( ! -iname "." ! -iname "*.md" \)); do $op "$f" ../../plugins/ fi else - cp -vRf "$f" ../../plugins/ + cp -vRf -- "$f" ../../plugins/ fi done cd ../.. || exit 1 diff --git a/files/.config/nnn/plugins/gpgs b/files/.config/nnn/plugins/gpgs new file mode 100755 index 0000000..3d434c3 --- /dev/null +++ b/files/.config/nnn/plugins/gpgs @@ -0,0 +1,42 @@ +#!/usr/bin/env sh + +# Description: signs selected files using gpg. +# includes options for clearsigning and +# detached signing documents as well +# +# signed and detach signed files are stored with extension .sig +# whereas clearsigned one are stored as .asc [by default by gpg] +# +# Note: The chosen method of signing is applied to all selected files [if selection is chosen] +# +# Shell: POSIX compliant +# Author: wassup05 + +file=$1 +selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection} + +printf "(s)election/(c)urrent? [default=c] " +read -r file_resp +printf "(s)ign/(c)learsign/(d)etach-sig? [default=s] " +read -r sig_resp + +getfiles(){ + if [ "$file_resp" = "s" ]; then + cat "$selection" + else + printf "%s\0" "$file" + fi +} + +if [ "$sig_resp" = "c" ]; then + getfiles | xargs -0 -I{} gpg --clearsign {} +elif [ "$sig_resp" = "d" ]; then + getfiles | xargs -0 -I{} gpg --detach-sig --output "{}.sig" +else + getfiles | xargs -0 -I{} gpg --sign --output "{}.sig" {} +fi + +# Clear selection +if [ "$file_resp" = "s" ] && [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" +fi diff --git a/files/.config/nnn/plugins/gpgv b/files/.config/nnn/plugins/gpgv new file mode 100755 index 0000000..23e52e7 --- /dev/null +++ b/files/.config/nnn/plugins/gpgv @@ -0,0 +1,28 @@ +#!/usr/bin/env sh + +# Description: verifies signed files using gpg. +# includes options for detached signing +# (in which case it asks for a document to verify) +# as well as normal signing +# +# Note: Uses the current file only [selections not supported] +# +# Shell: POSIX compliant +# Author: wassup05 + +file=$1 + +printf "(s)ign/(d)etach-sig [default=s] " +read -r sig_resp + +if [ "$sig_resp" = "d" ]; then + printf "Enter document name: " + read -r doc_name + command gpg --verify "$file" "$doc_name" +else + command gpg --verify "$file" +fi + +printf "\n" +# shellcheck disable=SC2034 +read -r resp # Waiting for input to go back to nnn diff --git a/files/.config/nnn/plugins/imgur b/files/.config/nnn/plugins/imgur index 16d21bc..e5981fc 100755 --- a/files/.config/nnn/plugins/imgur +++ b/files/.config/nnn/plugins/imgur @@ -583,7 +583,7 @@ for upload_file in "${upload_files[@]}"; do # delete file if configured if [ "${keep_file}" = "false" ] && [ -z "${1}" ]; then echo "Deleting temp file ${file_dir}/${img_file}" - rm -rf "${img_file}" + rm -rf -- "${img_file}" fi echo "" diff --git a/files/.config/nnn/plugins/imgview b/files/.config/nnn/plugins/imgview index d8cc247..0337511 100755 --- a/files/.config/nnn/plugins/imgview +++ b/files/.config/nnn/plugins/imgview @@ -54,7 +54,7 @@ make_thumbs() { done for file in "$NNN_PREVIEWDIR$dir"/*; do filename="$(basename "$file" .jpg)" - [ ! -e "$dir/$filename" ] && rm "$file" 2>/dev/null + [ ! -e "$dir/$filename" ] && rm -- "$file" 2>/dev/null done } diff --git a/files/.config/nnn/plugins/mimelist b/files/.config/nnn/plugins/mimelist index ccfe05a..3813c09 100755 --- a/files/.config/nnn/plugins/mimelist +++ b/files/.config/nnn/plugins/mimelist @@ -2,8 +2,12 @@ # Description: Find and list files by mime type in smart context # +# Dependencies: +# - file +# - mimetype (optional, PERL File MimeInfo) +# # Shell: POSIX compliant -# Author: Arun Prakash Jana +# Author: Arun Prakash Jana, Michel DHOOGE # shellcheck disable=SC1090,SC1091 . "$(dirname "$0")"/.nnn-plugin-helper @@ -12,4 +16,8 @@ printf "mime (e.g., video/audio/image): " read -r mime printf "%s" "+l" > "$NNN_PIPE" -find . | file -if- | grep "$mime" | awk -F: '{printf "%s\0", $1}' > "$NNN_PIPE" +if type mimetype >/dev/null 2>&1; then + find . | mimetype -f - | grep "$mime" | awk -F: '{printf "%s%c", $1, 0}' > "$NNN_PIPE" +else + find . | file -if- | grep "$mime" | awk -F: '{printf "%s%c", $1, 0}' > "$NNN_PIPE" +fi diff --git a/files/.config/nnn/plugins/nbak b/files/.config/nnn/plugins/nbak index f9cb644..9950026 100755 --- a/files/.config/nnn/plugins/nbak +++ b/files/.config/nnn/plugins/nbak @@ -34,7 +34,7 @@ fi cd "$tempdir/$outdir" || exit 1 # Backing up config dir content -cp -r "$configdir" . || exit 1 +cp -r -- "$configdir" . || exit 1 # Environment config env | sed "s/'/'\\\\''/" |\ @@ -72,4 +72,4 @@ printf "Saving as '%s' ... " "$workdir/$outfile" tar caf "$workdir/$outfile" "$outdir" && echo "Done" || echo "Failed" -cd "$workdir" && rm -rf "$tempdir" +cd "$workdir" && rm -rf -- "$tempdir" diff --git a/files/.config/nnn/plugins/nmount b/files/.config/nnn/plugins/nmount index e05453f..b484b08 100755 --- a/files/.config/nnn/plugins/nmount +++ b/files/.config/nnn/plugins/nmount @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash # Description: Toggle mount status of a device using pmount # If the device is not mounted, it will be mounted. @@ -6,7 +6,7 @@ # # Dependencies: lsblk, pmount (optional), udisks2 # -# Usage: Runs `lsblk` on 'l', exits on 'Return`. +# Usage: Runs `lsblk` on 'l', unmounts all USB HDDs on 'u', exits on 'Return`. # # Notes: # - The script uses Linux-specific lsblk to list block devices. Alternatives: @@ -15,22 +15,89 @@ # - The script uses udisksctl (from udisks2) to power down devices. This is also Linux-specific. # Users on non-Linux platforms can comment it and use an alternative to power-down disks. # -# Shell: POSIX compliant +# Shell: Bash # Author: Arun Prakash Jana -prompt="device name [e.g. sdXn] ('l'ist, 'q'uit): " +prompt="device name [e.g. sdXn] ('l'ist, 'u'nmount all USB, 'q'uit): " +previous_input="" + +restore_previous_input() { + if [ -n "$previous_input" ]; then + READLINE_LINE="$previous_input" + READLINE_POINT=${#READLINE_LINE} + fi +} + +clear_input() { + READLINE_LINE="" + READLINE_POINT=0 +} + +bind -x '"\e[A":restore_previous_input' +bind -x '"\e[B":clear_input' lsblk printf "\nEnsure you aren't still in the mounted device.\n" -printf "%s" "$prompt" -read -r dev +read -r -e -p "$prompt" dev while [ -n "$dev" ]; do + previous_input="$dev" if [ "$dev" = "l" ]; then lsblk elif [ "$dev" = "q" ]; then exit + elif [ "$dev" = "u" ]; then + usb_devs=$(lsblk -ndo NAME,TRAN | awk '$2=="usb"{print $1}') + if [ -z "$usb_devs" ]; then + echo "No USB block devices found." + else + for disk in $usb_devs; do + # Get only real partitions (e.g. sda1), skip device-mapper entries like luks-* + parts=$(lsblk -nlpo NAME,TYPE "/dev/$disk" | awk '$2=="part"{print $1}') + if [ -z "$parts" ]; then + echo "/dev/$disk has no partitions, skipping." + continue + fi + mounted=0 + for part in $parts; do + mnt=$(lsblk -n "$part" -o MOUNTPOINT | sed '/^$/d') + # Check if this partition or any child (e.g. LUKS) is mounted + child_mnt=$(lsblk -nro MOUNTPOINT "$part" | sed '/^$/d') + if [ -z "$mnt" ] && [ -z "$child_mnt" ]; then + continue + fi + mounted=1 + if type pumount >/dev/null 2>&1; then + sync "$child_mnt" + pumount "$part" + prc=$? + elif lsblk -n "$part" -o FSTYPE | grep -q "crypto_LUKS"; then + dev_map=$(udisksctl info -b "$part" | grep "CleartextDevice" | grep -o "dm_2d[[:digit:]]*" | sed "s/_2d/-/") + sync "$child_mnt" + udisksctl unmount -b "/dev/$dev_map" --no-user-interaction >/dev/null + prc=$? + udisksctl lock -b "$part" --no-user-interaction >/dev/null + else + sync "$mnt" + udisksctl unmount -b "$part" --no-user-interaction >/dev/null + prc=$? + fi + if [ $prc -eq 0 ]; then + echo "$part unmounted." + else + echo "Failed to unmount $part." + fi + done + if [ $mounted -eq 0 ]; then + echo "/dev/$disk has no mounted partitions, skipping." + continue + fi + if udisksctl power-off -b "/dev/$disk" --no-user-interaction 2>/dev/null; then + echo "/dev/$disk ejected." + fi + done + fi else # LUKS volumes mounted with udisksctl appear differently than with pmount if grep -qs "$dev " /proc/mounts || [ -n "$(lsblk -n "/dev/$dev" -o MOUNTPOINT)" ]; then @@ -83,6 +150,5 @@ while [ -n "$dev" ]; do fi echo - printf "%s" "$prompt" - read -r dev + read -r -e -p "$prompt" dev done diff --git a/files/.config/nnn/plugins/nuke b/files/.config/nnn/plugins/nuke index b3eafc8..44e2540 100755 --- a/files/.config/nnn/plugins/nuke +++ b/files/.config/nnn/plugins/nuke @@ -226,7 +226,8 @@ handle_extension() { glow -sdark "${FPATH}" | eval "$PAGER" exit 0 elif type lowdown >/dev/null 2>&1; then - lowdown -Tterm "${FPATH}" | eval "$PAGER" + cols=$(tput cols) + lowdown -Tterm --term-width="$cols" --term-column="$cols" "${FPATH}" | eval "$PAGER" exit 0 fi ;; @@ -271,13 +272,13 @@ abspath() { listimages() { find -L "///${1%/*}" -maxdepth 1 -type f -print0 | grep -izZE '\.(jpe?g|png|gif|webp|tiff|bmp|ico|svg)$' | - sort -z | tee "$tmp" + sort -zV | tee "$tmp" } load_dir() { abspath "$2" tmp="${TMPDIR:-/tmp}/nuke_$$" - trap 'rm -f $tmp' EXIT + trap 'rm -f -- "$tmp"' EXIT count="$(listimages "$abs_target" | grep -a -m 1 -ZznF "$abs_target" | cut -d: -f1)" if [ -n "$count" ]; then @@ -402,7 +403,7 @@ handle_multimedia() { # "${FPATH}"; # then # convert -- "${preview_png}" "${IMAGE_CACHE_PATH}" \ - # && rm "${preview_png}" \ + # && rm -- "${preview_png}" \ # && exit 6 # else # exit 1 @@ -544,12 +545,13 @@ handle_bin() { esac } -MIMETYPE="$( file -bL --mime-type -- "${FPATH}" )" handle_extension +MIMETYPE="$( file -bL --mime-type -- "${FPATH}" )" handle_multimedia "${MIMETYPE}" handle_mime "${MIMETYPE}" [ "$BIN" -ne 0 ] && [ -x "${FPATH}" ] && handle_bin handle_blocked "${MIMETYPE}" handle_fallback +# shellcheck disable=SC2317 exit 1 diff --git a/files/.config/nnn/plugins/organize b/files/.config/nnn/plugins/organize index fb70aaf..81cc9df 100755 --- a/files/.config/nnn/plugins/organize +++ b/files/.config/nnn/plugins/organize @@ -13,36 +13,36 @@ organize() { case "$(file -biL "$1")" in *video*) [ ! -d "Videos" ] && mkdir "Videos" - mv "$1" "Videos/$1" + mv -- "$1" "Videos/$1" printf "Moved %s to Videos\n" "$1" ;; *audio*) [ ! -d "Audio" ] && mkdir "Audio" - mv "$1" "Audio/$1" + mv -- "$1" "Audio/$1" printf "Moved %s to Audio\n" "$1" ;; *image*) [ ! -d "Images" ] && mkdir "Images" - mv "$1" "Images/$1" + mv -- "$1" "Images/$1" printf "Moved %s to Images\n" "$1" ;; *pdf*|*document*|*epub*|*djvu*|*cb*) [ ! -d "Documents" ] && mkdir "Documents" - mv "$1" "Documents/$1" + mv -- "$1" "Documents/$1" printf "Moved %s to Documents\n" "$1" ;; *text*) [ ! -d "Plaintext" ] && mkdir "Plaintext" - mv "$1" "Plaintext/$1" + mv -- "$1" "Plaintext/$1" printf "Moved %s to Plaintext\n" "$1" ;; *tar*|*xz*|*compress*|*7z*|*rar*|*zip*) [ ! -d "Archives" ] && mkdir "Archives" - mv "$1" "Archives/$1" + mv -- "$1" "Archives/$1" printf "Moved %s to Archives\n" "$1" ;; *binary*) [ ! -d "Binaries" ] && mkdir "Binaries" - mv "$1" "Binaries/$1" + mv -- "$1" "Binaries/$1" printf "Moved %s to Binaries\n" "$1" ;; esac } diff --git a/files/.config/nnn/plugins/pdfread b/files/.config/nnn/plugins/pdfread index 1e889be..9f65728 100755 --- a/files/.config/nnn/plugins/pdfread +++ b/files/.config/nnn/plugins/pdfread @@ -15,7 +15,7 @@ if [ -n "$1" ]; then pico2wave -w "$tmpf".wav -l en-GB "$(tr '\n' ' ' < "$tmpf".txt)" - rm "$tmpf".txt + rm -- "$tmpf".txt else pico2wave -w "$tmpf".wav -l en-GB "$(tr '\n' ' ' < "$1")" fi @@ -26,5 +26,5 @@ if [ -n "$1" ]; then # flat read but better quality # play -qV0 "$tmpf".wav treble 2 gain -l 2 - rm "$tmpf".wav + rm -- "$tmpf".wav fi diff --git a/files/.config/nnn/plugins/preview-tabbed b/files/.config/nnn/plugins/preview-tabbed index 5235c1e..2493fdf 100755 --- a/files/.config/nnn/plugins/preview-tabbed +++ b/files/.config/nnn/plugins/preview-tabbed @@ -4,7 +4,7 @@ # # Dependencies: # - tabbed (https://tools.suckless.org/tabbed): xembed host -# - xterm (or urxvt or st) : xembed client for text-based preview +# - xterm (or urxvt or st or alacritty) : xembed client for text-based preview # - mpv (https://mpv.io): xembed client for video/audio # - sxiv (https://github.com/muennich/sxiv) or, # - nsxiv (https://codeberg.org/nsxiv/nsxiv) : xembed client for images @@ -57,16 +57,21 @@ if [ -n "$WAYLAND_DISPLAY" ] ; then exit 1 fi -if type xterm >/dev/null 2>&1 ; then - TERMINAL="xterm -into" -elif type urxvt >/dev/null 2>&1 ; then - TERMINAL="urxvt -embed" +if type alacritty >/dev/null 2>&1 ; then + TERMINAL="alacritty --embed" elif type st >/dev/null 2>&1 ; then TERMINAL="st -w" +elif type urxvt >/dev/null 2>&1 ; then + TERMINAL="urxvt -embed" +elif type xterm >/dev/null 2>&1 ; then + TERMINAL="xterm -into" else echo "No xembed term found" >&2 fi +if type xdg-user-dir >/dev/null 2>&1 ; then + PICTURES_DIR=$(xdg-user-dir PICTURES) +fi term_nuke () { # $1 -> $XID, $2 -> $FILE @@ -90,7 +95,7 @@ start_tabbed () { read -r XID < "$FIFO" - rm "$FIFO" + rm -- "$FIFO" } get_viewer_pid () { @@ -175,7 +180,17 @@ previewer_loop () { fi ;; inode/directory) - $TERMINAL "$XID" -e nnn "$FILE" & + if [[ -n $PICTURES_DIR && "$FILE" == "$PICTURES_DIR"* ]] ; then + if type sxiv >/dev/null 2>&1 ; then + sxiv -te "$XID" "$FILE" & + elif type nsxiv >/dev/null 2>&1 ; then + nsxiv -te "$XID" "$FILE" & + else + $TERMINAL "$XID" -e nnn "$FILE" & + fi + else + $TERMINAL "$XID" -e nnn "$FILE" & + fi ;; text/*) if [ -x "$NUKE" ] ; then @@ -189,7 +204,8 @@ previewer_loop () { if [ -x "$NUKE" ] ; then term_nuke "$XID" "$FILE" else - $TERMINAL "$XID" -e sh -c "file '$FILE' | $PAGER -" & + SAFE_FILE=$(printf "%s" "$FILE" | sed "s/'/'\\\\''/g") + $TERMINAL "$XID" -e sh -c "file '$SAFE_FILE' | $PAGER -" & fi ;; esac diff --git a/files/.config/nnn/plugins/preview-tui b/files/.config/nnn/plugins/preview-tui index e78b110..7fc48e7 100755 --- a/files/.config/nnn/plugins/preview-tui +++ b/files/.config/nnn/plugins/preview-tui @@ -5,15 +5,16 @@ # Note: This plugin needs a "NNN_FIFO" to work. See man. # # Dependencies: -# - Supports 6 independent methods to preview with: +# - Supports 7 independent methods to preview with: # - tmux (>=3.0), or # - kitty with allow_remote_control and listen_on set in kitty.conf, or # - wezterm (https://wezfurlong.org/wezterm), or # - QuickLook on WSL (https://github.com/QL-Win/QuickLook), or # - Windows Terminal (https://github.com/Microsoft/Terminal | https://aka.ms/terminal) with WSL, or +# - zellij (https://github.com/zellij-org/zellij) or # - $NNN_TERMINAL set to a terminal (it's xterm by default). # - less or $NNN_PAGER -# - tree or exa or (GNU) ls +# - tree or exa/eza or (GNU) ls # - mediainfo or file # - mktemp # - unzip @@ -21,8 +22,12 @@ # - man # - optional: bsdtar or atool for additional archive preview # - optional: bat for code syntax highlighting -# - optional: ueberzug, kitty terminal, wezterm terminal, viu, catimg or chafa for images -# - optional: convert(ImageMagick) for playing gif preview (required for kitty image previews) +# - optional: ueberzug, kitty terminal, wezterm terminal, img2sixel, viu, catimg, timg or chafa for images +# - optional: convert(ImageMagick) for playing gif preview (mandatory for kitty image previews) +# - optional: mpv for gif and video +# Also requires a terminal supporting the sixel (https://www.arewesixelyet.com/) +# or kitty (https://sw.kovidgoyal.net/kitty/graphics-protocol) video_output backends. +# Requires tmux compiled with `./configure --enable-sixel` if used. # - optional: ffmpegthumbnailer for video thumbnails (https://github.com/dirkvdb/ffmpegthumbnailer) # - optional: ffmpeg for audio thumbnails # - optional: libreoffce for opendocument/officedocument preview @@ -40,6 +45,7 @@ # - optional: pistol file viewer (https://github.com/doronbehar/pistol). # 1. install pistol # 2. set/export $NNN_PISTOL as 1 +# - optional: librsvg for rsvg-convert # # Usage: # You need to set a NNN_FIFO path and a key for the plugin with NNN_PLUG, @@ -68,6 +74,12 @@ # With ImageMagick installed, this terminal can use the icat kitten to display images. # Refer to kitty documentation for further details. # +# Users with both tmux and kitty can leverage image previews inside tmux with kitty's icat kitten +# - setup kitty as stated above +# - tmux >= v3.3a required +# - add the following to your tmux.conf: +# - `set -g allow-passthrough on` +# # Wezterm should work out of the box. If `NNN_PREVIEWIMGPROG` is not specified it will use # built in iTerm2 image protocol. # @@ -84,28 +96,33 @@ # 'no_focus [title="preview-tui"]' to your i3 config file. # # Shell: Bash (for environment manipulation through arrays) -# Authors: Todd Yamakawa, Léo Villeveygoux, @Recidiviste, Mario Ortiz Manero, Luuk van Baal, @WanderLanz +# Authors: Todd Yamakawa, Léo Villeveygoux, @Recidiviste, Mario Ortiz Manero, Luuk van Baal, @WanderLanz, @flipflop133 -NNN_SPLIT=${NNN_SPLIT:-} # Set permanent split direction -NNN_TERMINAL=${NNN_TERMINAL:-} # Set external terminal to be used -NNN_SPLITSIZE=${NNN_SPLITSIZE:-50} # Set previewer split size percentage -TMPDIR=${TMPDIR:-/tmp} +# Configurable environment variables: +NNN_SPLIT=${NNN_SPLIT:-} # permanent split direction +NNN_TERMINAL=${NNN_TERMINAL:-} # external terminal to be used +NNN_SPLITSIZE=${NNN_SPLITSIZE:-50} # previewer split size percentage +TMPDIR=${TMPDIR:-/tmp} # location of temporary files +ENVVARS=( + "NNN_SCOPE=${NNN_SCOPE:-0}" # use scope + "NNN_PISTOL=${NNN_PISTOL:-0}" # use pistol + "NNN_ICONLOOKUP=${NNN_ICONLOOKUP:-0}" # use .iconlookup + "NNN_PAGER=${NNN_PAGER:-less -P?n -R -C}" # pager options + "NNN_BATTHEME=${NNN_BATTHEME:-ansi}" # bat theme + "NNN_BATSTYLE=${NNN_BATSTYLE:-numbers}" # bat style + "NNN_PREVIEWWIDTH=${NNN_PREVIEWWIDTH:-1920}" # width of generated preview images + "NNN_PREVIEWHEIGHT=${NNN_PREVIEWHEIGHT:-1080}" # height of generated preview images + "NNN_PREVIEWDIR=${NNN_PREVIEWDIR:-$TMPDIR/nnn/previews}" # location of generated preview images + "NNN_PREVIEWIMGPROG=${NNN_PREVIEWIMGPROG:-}" # command used to preview images + "NNN_PREVIEWVIDEO=${NNN_PREVIEWVIDEO:-}" # mpv backend used to preview video +) +# Non-configurable environment variables NNN_PARENT=${NNN_FIFO#*.} [ "$NNN_PARENT" -eq "$NNN_PARENT" ] 2>/dev/null || NNN_PARENT="" # Make empty if non-numeric -ENVVARS=( +ENVVARS+=( "PWD=$PWD" "PATH=$PATH" "NNN_FIFO=$NNN_FIFO" - "NNN_SCOPE=${NNN_SCOPE:-0}" - "NNN_PISTOL=${NNN_PISTOL:-0}" - "NNN_ICONLOOKUP=${NNN_ICONLOOKUP:-0}" - "NNN_PAGER=${NNN_PAGER:-less -P?n -R -C}" - "NNN_BATTHEME=${NNN_BATTHEME:-ansi}" - "NNN_BATSTYLE=${NNN_BATSTYLE:-numbers}" - "NNN_PREVIEWWIDTH=${NNN_PREVIEWWIDTH:-1920}" - "NNN_PREVIEWHEIGHT=${NNN_PREVIEWHEIGHT:-1080}" - "NNN_PREVIEWDIR=${NNN_PREVIEWDIR:-$TMPDIR/nnn/previews}" - "NNN_PREVIEWIMGPROG=${NNN_PREVIEWIMGPROG:-}" "FIFOPID=$TMPDIR/nnn-preview-tui-fifopid.$NNN_PARENT" "FIFOPATH=$TMPDIR/nnn-preview-tui-fifo.$NNN_PARENT" "PREVIEWPID=$TMPDIR/nnn-preview-tui-previewpid.$NNN_PARENT" @@ -132,14 +149,20 @@ pidkill() { start_preview() { if [ -e "${TMUX%%,*}" ] && tmux -V | grep -q '[ -][3456789]\.'; then NNN_TERMINAL=tmux + exists mpv && tmux display -p '#{client_termfeatures}' | grep -q 'sixel' && ENVVARS+=("NNN_PREVIEWVIDEO=sixel") elif [ -n "$KITTY_LISTEN_ON" ]; then NNN_TERMINAL=kitty + exists mpv && ENVVARS+=("NNN_PREVIEWVIDEO=kitty") elif [ -n "$WEZTERM_PANE" ]; then NNN_TERMINAL=wezterm + exists mpv && ENVVARS+=("NNN_PREVIEWVIDEO=kitty") elif [ -z "$NNN_TERMINAL" ] && [ "$TERM_PROGRAM" = "iTerm.app" ]; then NNN_TERMINAL=iterm + exists mpv && ENVVARS+=("NNN_PREVIEWVIDEO=sixel") elif [ -n "$WT_SESSION" ]; then NNN_TERMINAL=winterm + elif [ -n "$ZELLIJ" ]; then + NNN_TERMINAL=zellij else NNN_TERMINAL="${NNN_TERMINAL:-xterm}" fi @@ -152,7 +175,7 @@ start_preview() { ENVVARS+=("NNN_TERMINAL=$NNN_TERMINAL" "NNN_SPLIT=$NNN_SPLIT" "QLPATH=$2" "PREVIEW_MODE=1") case "$NNN_TERMINAL" in - iterm|winterm) # need run in separate shell command: escape + iterm|winterm) # has to run in separate shell command: escape ENVVARS=("${ENVVARS[@]/#/\\\"}") ENVVARS=("${ENVVARS[@]/%/\\\"}") command="$SHELL -c 'env ${ENVVARS[*]} \\\"$0\\\" \\\"$1\\\"'" ;; @@ -162,7 +185,7 @@ start_preview() { tmux) # tmux splits are inverted ENVVARS=("${ENVVARS[@]/#/-e}") if [ "$NNN_SPLIT" = "v" ]; then split="h"; else split="v"; fi - tmux split-window "${ENVVARS[@]}" -d"$split" -p"$NNN_SPLITSIZE" "$0" "$1" ;; + tmux split-window -l"$NNN_SPLITSIZE"% "${ENVVARS[@]}" -d"$split" -p"$NNN_SPLITSIZE" "$0" "$1" ;; kitty) # Setting the layout for the new window. It will be restored after the script ends. ENVVARS=("${ENVVARS[@]/#/--env=}") kitty @ goto-layout splits @@ -187,6 +210,17 @@ EOF winterm) if [ "$NNN_SPLIT" = "h" ]; then split="H"; else split="V"; fi wt -w 0 sp -$split -s"0.$NNN_SPLITSIZE" "$command" \; -w 0 mf previous 2>/dev/null ;; + zellij) + case "$NNN_SPLIT" in + h) + direction="down" ;; + *) + direction=right ;; + esac + zellij run --name "nnn preview" --close-on-exit \ + --direction "$direction" -- env "${ENVVARS[@]}" "$0" "$1" & + (sleep 0.2 && zellij action focus-previous-pane) & + ;; *) if [ -n "$2" ]; then env "${ENVVARS[@]}" QUICKLOOK=1 "$0" "$1" & else @@ -240,7 +274,7 @@ fifo_pager() { fi ) - rm "$FIFOPATH" + rm -- "$FIFOPATH" } # Binary file: show file info inside the pager @@ -282,7 +316,7 @@ handle_ext() { md) if exists glow; then fifo_pager glow -s dark "$1" elif exists lowdown; then - fifo_pager lowdown -Tterm "$1" + fifo_pager lowdown -Tterm --term-width="$cols" --term-column="$cols" "$1" else fifo_pager pager "$1" fi ;; @@ -303,6 +337,12 @@ handle_ext() { elif exists bsdtar; then fifo_pager bsdtar -tvf "$1" fi ;; + json) + if exists jq; then + fifo_pager jq --color-output '.' "$1" + else + fifo_pager pager "$1" + fi ;; *) if [ "$3" = "bin" ]; then fifo_pager print_bin_info "$1" else @@ -349,7 +389,9 @@ preview_file() { elif exists tree; then fifo_pager tree --filelimit "$(find . -maxdepth 1 | wc -l)" -L 3 -C -F --dirsfirst --noreport elif exists exa; then - exa -G --group-directories-first --colour=always + fifo_pager exa -T --group-directories-first --colour=always -L 3 . + elif exists eza; then # eza is a community fork of exa (exa is unmaintained) + fifo_pager eza -T --group-directories-first --colour=always -L 3 . else fifo_pager ls -F --group-directories-first --color=always fi @@ -364,6 +406,9 @@ preview_file() { generate_preview() { if [ -n "$QLPATH" ] && stat "$3"; then f="$(wslpath -w "$3")" && "$QLPATH" "$f" & + elif [ -n "$NNN_PREVIEWVIDEO" ] && [[ "$4" == +(gif|video) ]]; then + [ "$4" = "video" ] && args=(--start=10% --length=4) || args=() + video_preview "$1" "$2" "$3" "${args[@]}" && return elif [ ! -f "$NNN_PREVIEWDIR/$3.jpg" ] || [ -n "$(find -L "$3" -newer "$NNN_PREVIEWDIR/$3.jpg")" ]; then mkdir -p "$NNN_PREVIEWDIR/${3%/*}" case $4 in @@ -387,25 +432,30 @@ generate_preview() { done & printf "%s" "$!" > "$PREVIEWPID" return + elif [ -n "$NNN_PREVIEWVIDEO" ]; then + video_preview "$1" "$2" "$3" && return else - image_preview "$1" "$2" "$3" - return + image_preview "$1" "$2" "$3" && return fi ;; - image) if exists convert; then + image) if exists rsvg-convert && [[ "${3##*.}" == "svg" ]]; then + rsvg-convert -a -w "$NNN_PREVIEWWIDTH" -h "$NNN_PREVIEWHEIGHT" -f png -o "$NNN_PREVIEWDIR/$3.png" "$3" + elif exists convert; then convert "$3" -flatten -resize "$NNN_PREVIEWWIDTH"x"$NNN_PREVIEWHEIGHT"\> "$NNN_PREVIEWDIR/$3.jpg" else image_preview "$1" "$2" "$3" && return fi ;; office) libreoffice --convert-to jpg "$3" --outdir "$NNN_PREVIEWDIR/${3%/*}" filename="$(printf "%s" "${3##*/}" | cut -d. -f1)" - mv "$NNN_PREVIEWDIR/${3%/*}/$filename.jpg" "$NNN_PREVIEWDIR/$3.jpg" ;; + mv -- "$NNN_PREVIEWDIR/${3%/*}/$filename.jpg" "$NNN_PREVIEWDIR/$3.jpg" ;; pdf) pdftoppm -jpeg -f 1 -singlefile "$3" "$NNN_PREVIEWDIR/$3" ;; djvu) ddjvu -format=ppm -page=1 "$3" "$NNN_PREVIEWDIR/$3.jpg" ;; - video) ffmpegthumbnailer -m -s0 -i "$3" -o "$NNN_PREVIEWDIR/$3.jpg" || rm "$NNN_PREVIEWDIR/$3.jpg" ;; + video) video_preview "$1" "$2" "$3" && return ;; esac fi if [ -f "$NNN_PREVIEWDIR/$3.jpg" ]; then image_preview "$1" "$2" "$NNN_PREVIEWDIR/$3.jpg" + elif [[ "${3##*.}" == "svg" ]] && [ -f "$NNN_PREVIEWDIR/$3.png" ]; then + image_preview "$1" "$2" "$NNN_PREVIEWDIR/$3.png" else fifo_pager print_bin_info "$3" fi @@ -414,24 +464,33 @@ generate_preview() { image_preview() { clear exec >/dev/tty - if [ "$NNN_TERMINAL" = "kitty" ] && [ -z "$NNN_PREVIEWIMGPROG" ]; then + if [ "$NNN_TERMINAL" = "kitty" ] && [[ "$NNN_PREVIEWIMGPROG" == +(|icat) ]]; then kitty +kitten icat --silent --scale-up --place "$1"x"$2"@0x0 --transfer-mode=stream --stdin=no "$3" & - elif [ "$NNN_TERMINAL" = "wezterm" ] && [ -z "$NNN_PREVIEWIMGPROG" ]; then + elif [ "$NNN_TERMINAL" = "tmux" ] && [[ -n "$KITTY_LISTEN_ON" ]] && [[ "$NNN_PREVIEWIMGPROG" == +(|icat) ]]; then + kitty +kitten icat --silent --scale-up --place "$(($1 - 1))x$(($2 - 1))"@0x0 --transfer-mode=memory --stdin=no "$3" & + elif [ "$NNN_TERMINAL" = "wezterm" ] && [[ "$NNN_PREVIEWIMGPROG" == +(|imgcat) ]]; then wezterm imgcat "$3" & - elif exists ueberzug && { [ -z "$NNN_PREVIEWIMGPROG" ] || [ "$NNN_PREVIEWIMGPROG" = "ueberzug" ] ;}; then + elif exists ueberzug && [[ "$NNN_PREVIEWIMGPROG" == +(|ueberzug) ]]; then ueberzug_layer "$1" "$2" "$3" && return - elif exists catimg && { [ -z "$NNN_PREVIEWIMGPROG" ] || [ "$NNN_PREVIEWIMGPROG" = "catimg" ] ;}; then - catimg "$3" & - elif exists viu && { [ -z "$NNN_PREVIEWIMGPROG" ] || [ "$NNN_PREVIEWIMGPROG" = "viu" ] ;}; then - viu -t "$3" & - elif exists chafa && { [ -z "$NNN_PREVIEWIMGPROG" ] || [ "$NNN_PREVIEWIMGPROG" = "chafa" ] ;}; then - chafa "$3" & + elif exists "${NNN_PREVIEWIMGPROG%% *}"; then # can include command flags; only check first word + $NNN_PREVIEWIMGPROG "$3" & else fifo_pager print_bin_info "$3" && return fi printf "%s" "$!" > "$PREVIEWPID" } +video_preview() { + clear + exec >/dev/tty + if [ -n "$NNN_PREVIEWVIDEO" ]; then + mpv --no-config --really-quiet --vo="$NNN_PREVIEWVIDEO" --profile=sw-fast --loop-file --no-audio "$4" "$3" & + else + ffmpegthumbnailer -m -s0 -i "$3" -o "$NNN_PREVIEWDIR/$3.jpg" || rm -- "$NNN_PREVIEWDIR/$3.jpg" & + fi + printf "%s" "$!" > "$PREVIEWPID" +} + ueberzug_layer() { [ -f "$POSOFFSET" ] && read -r x y < "$POSOFFSET" printf '{"action": "add", "identifier": "nnn_ueberzug", "x": %d, "y": %d, "width": "%d", "height": "%d", "scaler": "fit_contain", "path": "%s"}\n'\ @@ -457,6 +516,7 @@ preview_fifo() { if [ -n "$selection" ]; then pidkill "$PREVIEWPID" [ -p "$FIFO_UEBERZUG" ] && ueberzug_remove + [ -n "$KITTY_LISTEN_ON" ] && kitty +kitten icat --clear --stdin=no >/dev/tty 2>/dev/null [ "$selection" = "close" ] && break preview_file "$selection" printf "%s" "$selection" > "$CURSEL" @@ -467,18 +527,20 @@ preview_fifo() { } if [ "$PREVIEW_MODE" -eq 1 ] 2>/dev/null; then - if [ "$NNN_TERMINAL" != "kitty" ] && exists ueberzug; then + if exists ueberzug && [ "$NNN_TERMINAL" != "kitty" ] && [[ "$NNN_PREVIEWIMGPROG" == +(|ueberzug) ]]; then mkfifo "$FIFO_UEBERZUG" tail --follow "$FIFO_UEBERZUG" | ueberzug layer --silent --parser json & fi preview_file "$PWD/$1" - preview_fifo & + preview_fifo & WAITPID=$! printf "%s" "$!" > "$FIFOPID" printf "%s" "$PWD/$1" > "$CURSEL" - trap 'winch_handler; wait' WINCH - trap 'rm "$PREVIEWPID" "$CURSEL" "$FIFO_UEBERZUG" "$FIFOPID" "$POSOFFSET" 2>/dev/null' INT HUP EXIT - wait "$!" 2>/dev/null + trap 'winch_handler' WINCH + trap 'rm -- "$PREVIEWPID" "$CURSEL" "$FIFO_UEBERZUG" "$FIFOPID" "$POSOFFSET" 2>/dev/null' INT HUP EXIT + while kill -s 0 $WAITPID; do + wait $WAITPID 2>/dev/null + done exit 0 else if [ ! -r "$NNN_FIFO" ]; then diff --git a/files/.config/nnn/plugins/renamer b/files/.config/nnn/plugins/renamer index 51c586e..9d5b2e9 100755 --- a/files/.config/nnn/plugins/renamer +++ b/files/.config/nnn/plugins/renamer @@ -6,7 +6,7 @@ # - Try to mimic current batch rename functionality but with correct # handling of edge cases by qmv or vidir. # - Qmv opens with hidden files if no selection is used. Selected -# directories are shown. +# directories are shown. # - Vidir don't show directories nor hidden files. # # Shell: POSIX compliant @@ -15,11 +15,11 @@ selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection} if type qmv >/dev/null 2>&1; then - batchrenamesel="qmv -fdo -da" - batchrename="qmv -fdo -a" + batchrenamesel="qmv -fdo -da" + batchrename="qmv -fdo -a" elif type vidir >/dev/null 2>&1; then - batchrenamesel="vidir" - batchrename="vidir" + batchrenamesel="vidir" + batchrename="vidir" else printf "there is not batchrename program installed." exit @@ -32,6 +32,7 @@ fi if [ "$resp" = "y" ]; then # -o flag is necessary for interactive editors + # shellcheck disable=SC2086 xargs -o -0 $batchrenamesel < "$selection" # Clear selection @@ -40,6 +41,6 @@ if [ "$resp" = "y" ]; then fi elif [ ! "$(LC_ALL=C ls -a)" = ". .." ]; then - # On older systems that don't have ls -A + # On older systems that don't have ls -A $batchrename fi diff --git a/files/.config/nnn/plugins/stats b/files/.config/nnn/plugins/stats new file mode 100755 index 0000000..bafd74a --- /dev/null +++ b/files/.config/nnn/plugins/stats @@ -0,0 +1,71 @@ +#!/usr/bin/env sh + +# Description: Show file stats similar to nnn show_stats() output in a pager +# Dependencies: file, stat, pager (PAGER/NNN_PAGER/less) +# Shell: POSIX compliant + +entry=${1:-} +dir=${2:-} + +if [ -z "$entry" ]; then + printf '%s\n' "No hovered entry provided." >&2 + exit 1 +fi + +case "$entry" in + /*) target=$entry ;; + *) + if [ -n "$dir" ]; then + target=$dir/$entry + else + target=$PWD/$entry + fi + ;; +esac + +os=$(uname -s 2>/dev/null || printf '%s' unknown) + +# Match nnn FILE_MIME_OPTS handling. +file_mime_opts='' +case "$os" in + Darwin) + file_mime_opts='-bIL' + ;; + SunOS) + file_mime_opts='' + ;; + *) + file_mime_opts='-biL' + ;; +esac + +# Match nnn stat behavior. +stat_x=0 +case "$os" in + FreeBSD|OpenBSD|NetBSD|Darwin|DragonFly) + stat_x=1 + ;; +esac + +tmpfile=$(mktemp "${TMPDIR:-/tmp}/nnn-stats.XXXXXX") || exit 1 +trap 'rm -f "$tmpfile"' EXIT HUP INT TERM + +{ + if [ "$stat_x" -eq 1 ]; then + stat -x "$target" + else + stat "$target" + fi + + file -b "$target" + + if [ -n "$file_mime_opts" ]; then + file "$file_mime_opts" "$target" + fi +} >"$tmpfile" 2>&1 + +pager_cmd=${NNN_PAGER:-${PAGER:-less}} + +# Allow pager command with options (e.g. "less -R"). +# shellcheck disable=SC2086 +$pager_cmd "$tmpfile" || cat "$tmpfile" diff --git a/files/.config/nnn/plugins/suedit b/files/.config/nnn/plugins/suedit index 21dddf4..03608e8 100755 --- a/files/.config/nnn/plugins/suedit +++ b/files/.config/nnn/plugins/suedit @@ -7,10 +7,10 @@ EDITOR="${EDITOR:-vim}" -if type sudo >/dev/null 2>&1; then +if type sudoedit >/dev/null 2>&1; then + sudoedit "$1" +elif type sudo >/dev/null 2>&1; then sudo -E "$EDITOR" "$1" -elif type sudoedit >/dev/null 2>&1; then - sudoedit -E "$1" elif type doas >/dev/null 2>&1; then doas "$EDITOR" "$1" fi diff --git a/files/.config/nnn/plugins/tnp b/files/.config/nnn/plugins/tnp new file mode 100755 index 0000000..8c484a2 --- /dev/null +++ b/files/.config/nnn/plugins/tnp @@ -0,0 +1,47 @@ +#!/usr/bin/env sh + +# Description: Only works inside a tmux session - Opens files in Neovim. +# If $NVIM is set and its server is alive, files are opened +# in that server. Otherwise, a new pane is split on the left +# and files are opened there until the nnn pane is closed. +# +# Dependencies: tmux neovim +# +# Tip: Exec nnn inside Neovim pane via a leader key +# +# vim.keymap.set("n", "<Leader>n", function() +# if vim.env.TMUX then +# vim.fn.system({ +# "tmux", "split-window", "-h", +# "-c", vim.fn.getcwd(), +# "-e", "NVIM=" .. vim.v.servername, +# "exec nnn" +# }) +# end +# end) +# +# Shell: POSIX compliant +# Author: 8lackfish + +fpath="${2:+$2/}$1" + +if [ -n "$TMUX" ]; then + if [ -S "$NVIM" ]; then + svname="$NVIM" + nvim --server "$svname" --remote "$fpath" + else + id=$(tmux display-message -p '#{pane_id}.#{window_id}.#{session_id}' | tr -d '%@$') + svname="${XDG_RUNTIME_DIR:-/tmp}/nvim.nnn-tnp.$id" + if [ -S "$svname" ]; then + nvim --server "$svname" --remote "$fpath" + else + tmux split-pane -bdh "nvim --listen \"${svname}\" \"${fpath}\"" + fi + fi + until nvim --headless --server "$svname" \ + --remote-expr "execute('%argdelete')" >/dev/null 2>&1 + do :; done +else + printf "\n'%s' only works inside a tmux session" "$(basename "$0")" + printf "\n\n'Enter' to return"; read -r _ +fi diff --git a/files/.config/nnn/plugins/upload b/files/.config/nnn/plugins/upload index 4948587..e225d20 100755 --- a/files/.config/nnn/plugins/upload +++ b/files/.config/nnn/plugins/upload @@ -1,12 +1,11 @@ #!/usr/bin/env sh -# Description: Selections are uploaded using Firefox Send +# Description: Selections are archived into a tar file (uncompressed) and uploaded to file.io # For single files: -# Upload to Firefox Send if ffsend is found, else -# Paste contents of a text a file http://ix.io +# Paste contents of a text file to http://ix.io # Upload a binary file to file.io # -# Dependencies: ffsend (https://github.com/timvisee/ffsend), curl, jq, tr +# Dependencies: curl, jq, tar, file with `--mime-type` support # # Note: Binary file set to expire after a week # @@ -15,30 +14,24 @@ selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection} if [ -s "$selection" ]; then - if type ffsend >/dev/null 2>&1; then - # File name will be randomized foo.tar - xargs -0 < "$selection" ffsend u - else - printf "ffsend is required to upload selection." - fi + xargs -0 tar -c < "$selection" | \ + curl -s -F "file=@/dev/stdin;filename=selection.tar" 'https://file.io/?expires=1w' | \ + jq '.link' | tr -d '"' # Clear selection printf "-" > "$NNN_PIPE" else if [ -n "$1" ] && [ -s "$1" ]; then - if type ffsend >/dev/null 2>&1; then - ffsend -fiq u "$1" - elif [ "$(mimetype --output-format %m "$1" | awk -F '/' '{print $1}')" = "text" ]; then - curl -F "f:1=@$1" ix.io - else - # Upload the file, show the download link and wait till user presses any key - curl -s -F "file=@$1" https://file.io/?expires=1w | jq '.link' | tr -d '"' - - # To write download link to "$1".loc and exit - # curl -s -F "file=@$1" https://file.io/?expires=1w -o `basename "$1"`.loc - fi + if file --mime-type "$1" | grep -q -F "text/"; then + curl -F "file=@$1" https://0x0.st + else + # Upload the file, show the download link and wait till user presses any key + curl -s -F "file=@$1" https://file.io/?expires=1w | jq '.link' | tr -d '"' + # To write download link to "$1".loc and exit + # curl -s -F "file=@$1" https://file.io/?expires=1w -o `basename "$1"`.loc + fi else - printf "empty file!" + printf "empty file!" fi fi diff --git a/files/.config/nnn/plugins/wallpaper b/files/.config/nnn/plugins/wallpaper index 2017fbd..966e7ce 100755 --- a/files/.config/nnn/plugins/wallpaper +++ b/files/.config/nnn/plugins/wallpaper @@ -8,11 +8,19 @@ # Shell: POSIX compliant # Author: juacq97 +resp= + if [ -n "$1" ]; then if [ "$(file --mime-type "$1" | awk '{print $NF}' | awk -F '/' '{print $1}')" = "image" ]; then if [ "$XDG_SESSION_TYPE" = "x11" ]; then if type nitrogen >/dev/null 2>&1; then - nitrogen --set-zoom-fill --save "$1" + printf "Set to full desktop or a specific monitors? [0, 1, etc. Defaults to full.]" + read -r resp + if [ "$resp" != "" ]; then + nitrogen --set-zoom-fill --save "$1" --head="$resp" + else + nitrogen --set-zoom-fill --save "$1" + fi elif type wal >/dev/null 2>&1; then wal -i "$1" else diff --git a/files/.config/nnn/plugins/x2sel b/files/.config/nnn/plugins/x2sel index 95414fc..4682e51 100755 --- a/files/.config/nnn/plugins/x2sel +++ b/files/.config/nnn/plugins/x2sel @@ -8,7 +8,7 @@ # - pbpaste (macOS) # - termux-clipboard-get (Termux) # - powershell (WSL) -# - cygwim's /dev/clipboard (Cygwin) +# - cygwin's /dev/clipboard (Cygwin) # - wl-paste (Wayland) # - clipboard (Haiku) # @@ -26,6 +26,9 @@ getclip () { if [ "$XDG_SESSION_TYPE" = "wayland" ]; then # Wayland wl-paste + elif type powershell.exe >/dev/null 2>&1; then + # WSL + powershell.exe -noprofile -command Get-Clipboard | tr -d '\r' elif type xsel >/dev/null 2>&1; then # Linux xsel -bo @@ -38,9 +41,6 @@ getclip () { elif type termux-clipboard-get >/dev/null 2>&1; then # Termux termux-clipboard-get - elif type powershell.exe >/dev/null 2>&1; then - # WSL - powershell.exe Get-Clipboard elif [ -r /dev/clipboard ] ; then # Cygwin cat /dev/clipboard @@ -52,9 +52,15 @@ getclip () { CLIPBOARD=$(getclip) +if [ -z "$CLIPBOARD" ]; then + echo "No content in clipboard" + exit 1 +fi + # Check if clipboard actually contains a file list for file in $CLIPBOARD ; do if [ ! -e "$file" ] ; then + echo "'$file' is not a file" exit 1; fi done diff --git a/files/.config/nnn/plugins/xdgdefault b/files/.config/nnn/plugins/xdgdefault index cf64a2f..27934c9 100755 --- a/files/.config/nnn/plugins/xdgdefault +++ b/files/.config/nnn/plugins/xdgdefault @@ -40,7 +40,10 @@ while [ -n "$dirs" ]; do dirs=${dirs#*:} done -app=$(find "$@" -iname '*.desktop' -exec grep '^Name=' {} + \ +# see PR #2102 +# shellcheck disable=SC2038 +app=$(find "$@" -iname '*.desktop' -exec grep -l "MimeType=.*$ftype" {} + 2>/dev/null \ + | xargs -I {} grep '^Name=' {} /dev/null \ | sort -u -t ':' -k 1,1 \ | sed -e 's;..*/\(..*desktop\):Name=\(..*\);\2:\1;' \ | sort -t ':' -k 1,1 \ |
