summaryrefslogtreecommitdiff
path: root/nnn
diff options
context:
space:
mode:
author--global <ik.boikov.public@protonmail.com>2021-07-14 23:02:24 +0200
committer--global <ik.boikov.public@protonmail.com>2021-07-14 23:02:24 +0200
commitfd850fb2ed9870edcb1df205e08e8ccb25fb6760 (patch)
tree641b5af724d86a0a383b2c580dd838b03c1cc42c /nnn
parent72000d2f0c23a685f4c4d458158712340f6b9a68 (diff)
more nnn plugins, more luke's scripts
Diffstat (limited to 'nnn')
-rwxr-xr-xnnn/.config/nnn/plugins/.cbcp50
-rwxr-xr-xnnn/.config/nnn/plugins/.nmv153
-rwxr-xr-xnnn/.config/nnn/plugins/.nnn-plugin-helper4
-rwxr-xr-xnnn/.config/nnn/plugins/.ntfy22
-rwxr-xr-xnnn/.config/nnn/plugins/autojump42
-rwxr-xr-xnnn/.config/nnn/plugins/bookmarks61
-rwxr-xr-xnnn/.config/nnn/plugins/boom47
-rwxr-xr-xnnn/.config/nnn/plugins/bulknew32
-rwxr-xr-xnnn/.config/nnn/plugins/chksum66
-rwxr-xr-xnnn/.config/nnn/plugins/diffs56
-rwxr-xr-xnnn/.config/nnn/plugins/dragdrop13
-rwxr-xr-xnnn/.config/nnn/plugins/dups70
-rwxr-xr-xnnn/.config/nnn/plugins/finder28
-rwxr-xr-xnnn/.config/nnn/plugins/fzcd37
-rwxr-xr-xnnn/.config/nnn/plugins/fzhist38
-rwxr-xr-xnnn/.config/nnn/plugins/fzopen38
-rwxr-xr-xnnn/.config/nnn/plugins/fzz26
-rwxr-xr-xnnn/.config/nnn/plugins/getplugs83
-rwxr-xr-xnnn/.config/nnn/plugins/gpgd22
-rwxr-xr-xnnn/.config/nnn/plugins/gpge38
-rwxr-xr-xnnn/.config/nnn/plugins/gutenread49
-rwxr-xr-xnnn/.config/nnn/plugins/hexview15
-rwxr-xr-xnnn/.config/nnn/plugins/imgresize30
-rwxr-xr-xnnn/.config/nnn/plugins/imgthumb17
-rwxr-xr-xnnn/.config/nnn/plugins/imgur595
-rwxr-xr-xnnn/.config/nnn/plugins/imgview70
-rwxr-xr-xnnn/.config/nnn/plugins/ipinfo13
-rwxr-xr-xnnn/.config/nnn/plugins/kdeconnect17
-rwxr-xr-xnnn/.config/nnn/plugins/launch42
-rwxr-xr-xnnn/.config/nnn/plugins/mediainf2
-rwxr-xr-xnnn/.config/nnn/plugins/mimelist12
-rwxr-xr-xnnn/.config/nnn/plugins/moclyrics39
-rwxr-xr-xnnn/.config/nnn/plugins/mocplay84
-rwxr-xr-xnnn/.config/nnn/plugins/mp3conv41
-rwxr-xr-xnnn/.config/nnn/plugins/nbak75
-rwxr-xr-xnnn/.config/nnn/plugins/nmount53
-rwxr-xr-xnnn/.config/nnn/plugins/nuke516
-rwxr-xr-xnnn/.config/nnn/plugins/oldbigfile16
-rwxr-xr-xnnn/.config/nnn/plugins/organize53
-rwxr-xr-xnnn/.config/nnn/plugins/pdfread30
-rwxr-xr-xnnn/.config/nnn/plugins/pdfview24
-rwxr-xr-xnnn/.config/nnn/plugins/preview-tabbed211
-rwxr-xr-xnnn/.config/nnn/plugins/preview-tui231
-rwxr-xr-xnnn/.config/nnn/plugins/pskill35
-rwxr-xr-xnnn/.config/nnn/plugins/renamer41
-rwxr-xr-xnnn/.config/nnn/plugins/ringtone36
-rwxr-xr-xnnn/.config/nnn/plugins/rsynccp26
-rwxr-xr-xnnn/.config/nnn/plugins/splitjoin47
-rwxr-xr-xnnn/.config/nnn/plugins/suedit21
-rwxr-xr-xnnn/.config/nnn/plugins/toggleex21
-rwxr-xr-xnnn/.config/nnn/plugins/treeview8
-rwxr-xr-xnnn/.config/nnn/plugins/uidgid13
-rwxr-xr-xnnn/.config/nnn/plugins/umounttree52
-rwxr-xr-xnnn/.config/nnn/plugins/upgrade25
-rwxr-xr-xnnn/.config/nnn/plugins/upload28
-rwxr-xr-xnnn/.config/nnn/plugins/vidthumb27
-rwxr-xr-xnnn/.config/nnn/plugins/wall30
-rwxr-xr-xnnn/.config/nnn/plugins/x2sel62
58 files changed, 3621 insertions, 12 deletions
diff --git a/nnn/.config/nnn/plugins/.cbcp b/nnn/.config/nnn/plugins/.cbcp
new file mode 100755
index 0000000..04a09dc
--- /dev/null
+++ b/nnn/.config/nnn/plugins/.cbcp
@@ -0,0 +1,50 @@
+#!/usr/bin/env sh
+
+# Description: Copy selection to system clipboard as newline-separated entries
+# Dependencies:
+# - tr
+# - xclip/xsel (Linux)
+# - pbcopy (macOS)
+# - termux-clipboard-set (Termux)
+# - clip.exe (WSL)
+# - clip (Cygwin)
+# - wl-copy (Wayland)
+# - clipboard (Haiku)
+#
+# Limitation: breaks if a filename has newline in it
+#
+# Note: For a space-separated list:
+# xargs -0 < "$SELECTION"
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+IFS="$(printf '%b_' '\n')"; IFS="${IFS%_}" # protect trailing \n
+
+selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+
+if which xsel >/dev/null 2>&1; then
+ # Linux
+ tr '\0' '\n' < "$selection" | xsel -bi
+elif which xclip >/dev/null 2>&1; then
+ # Linux
+ tr '\0' '\n' < "$selection" | xclip -sel clip
+elif which pbcopy >/dev/null 2>&1; then
+ # macOS
+ tr '\0' '\n' < "$selection" | pbcopy
+elif which termux-clipboard-set >/dev/null 2>&1; then
+ # Termux
+ tr '\0' '\n' < "$selection" | termux-clipboard-set
+elif which clip.exe >/dev/null 2>&1; then
+ # WSL
+ tr '\0' '\n' < "$selection" | clip.exe
+elif which clip >/dev/null 2>&1; then
+ # Cygwin
+ tr '\0' '\n' < "$selection" | clip
+elif which wl-copy >/dev/null 2>&1; then
+ # Wayland
+ tr '\0' '\n' < "$selection" | wl-copy
+elif which clipboard >/dev/null 2>&1; then
+ # Haiku
+ tr '\0' '\n' < "$selection" | clipboard --stdin
+fi
diff --git a/nnn/.config/nnn/plugins/.nmv b/nnn/.config/nnn/plugins/.nmv
new file mode 100755
index 0000000..7762546
--- /dev/null
+++ b/nnn/.config/nnn/plugins/.nmv
@@ -0,0 +1,153 @@
+#!/usr/bin/env bash
+
+# Description: An almost fully POSIX compliant batch file renamer
+#
+# Note: nnn auto-detects and invokes this plugin if available
+# Whitespace is used as delimiter for read.
+# The plugin doesn't support filenames with leading or trailing whitespace
+#
+# Capabilities:
+# 1. Basic file rename
+# 2. Detects order change
+# 3. Can move files
+# 4. Can remove files
+# 5. Switch number pairs to swap filenames
+#
+# Shell: bash
+# Author: KlzXS
+
+EDITOR="${EDITOR:-vi}"
+TMPDIR="${TMPDIR:-/tmp}"
+INCLUDE_HIDDEN="${INCLUDE_HIDDEN:-0}"
+VERBOSE="${VERBOSE:-0}"
+
+selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+exit_status=0
+
+dst_file=$(mktemp "$TMPDIR/.nnnXXXXXX")
+
+if [ -s "$selection" ]; then
+ printf "Rename 'c'urrent / 's'election? "
+ read -r resp
+
+ if ! [ "$resp" = "c" ] && ! [ "$resp" = "s" ]; then
+ exit 1
+ fi
+fi
+
+if [ "$resp" = "s" ]; then
+ arr=$(tr '\0' '\n' < "$selection")
+else
+ if [ "$INCLUDE_HIDDEN" -eq 0 ]; then
+ arr=$(find . ! -name . -prune ! -name ".*" -print | sort)
+ else
+ arr=$(find . ! -name . -prune -print | sort)
+ fi
+fi
+
+lines=$(printf "%s\n" "$arr" | wc -l)
+width=${#lines}
+
+printf "%s" "$arr" | awk '{printf("%'"${width}"'d %s\n", NR, $0)}' > "$dst_file"
+
+items=("~")
+while IFS='' read -r line; do
+ items+=("$line");
+done < <(printf "%s\n" "$arr")
+
+$EDITOR "$dst_file"
+
+while read -r num name; do
+ if [ -z "$name" ]; then
+ if [ -z "$num" ]; then
+ continue
+ fi
+
+ printf "%s: unable to parse line, aborting\n" "$0"
+ exit 1
+ fi
+
+ # check if $num is an integer
+ if [ ! "$num" -eq "$num" ] 2> /dev/null; then
+ printf "%s: unable to parse line, aborting\n" "$0"
+ exit 1
+ fi
+
+ src=${items[$num]}
+
+ if [ -z "$src" ]; then
+ printf "%s: unknown item number %s\n" "$0" "$num" > /dev/stderr
+ continue
+ elif [ "$name" != "$src" ]; then
+ if [ -z "$name" ]; then
+ continue
+ fi
+
+ if [ ! -e "$src" ] && [ ! -L "$src" ]; then
+ printf "%s: %s does not exit\n" "$0" "$src" > /dev/stderr
+
+ unset "items[$num]"
+ continue
+ fi
+
+ # handle swaps
+ if [ -e "$name" ] || [ -L "$name" ]; then
+ tmp="$name~"
+ c=0
+
+ while [ -e "$tmp" ] || [ -L "$tmp" ]; do
+ c=$((c+1))
+ tmp="$tmp~$c"
+ done
+
+ if mv "$name" "$tmp"; then
+ if [ "$VERBOSE" -ne 0 ]; then
+ printf "'%s' -> '%s'\n" "$name" "$tmp"
+ fi
+ else
+ printf "%s: failed to rename %s to %s: %s\n" "$0" "$name" "$tmp" "$!" > /dev/stderr
+ exit_status=1
+ fi
+
+ for key in "${!items[@]}"; do
+ if [ "${items[$key]}" = "$name" ]; then
+ items[$key]="$tmp"
+ fi
+ done
+ fi
+
+ dir=$(dirname "$name")
+ 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 "$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
+ items[$key]=$(printf "%s" "${items[$key]}" | sed "s|^$src\(\$\|\/\)|$name\1|")
+ done
+
+ if [ "$VERBOSE" -ne 0 ]; then
+ printf "'%s' => '%s'\n" "$src" "$name"
+ fi
+ else
+ true
+ if [ "$VERBOSE" -ne 0 ]; then
+ printf "'%s' -> '%s'\n" "$src" "$name"
+ fi
+ fi
+ fi
+ fi
+
+ unset "items[$num]"
+done <"$dst_file"
+
+unset "items[0]"
+for item in "${items[@]}"; do
+ rm -ri "$item"
+done
+
+rm "$dst_file"
+exit $exit_status
diff --git a/nnn/.config/nnn/plugins/.nnn-plugin-helper b/nnn/.config/nnn/plugins/.nnn-plugin-helper
index a0377ac..bcb9649 100755
--- a/nnn/.config/nnn/plugins/.nnn-plugin-helper
+++ b/nnn/.config/nnn/plugins/.nnn-plugin-helper
@@ -33,6 +33,6 @@ nnn_cd () {
}
cmd_exists () {
- type "$1" > /dev/null 2>&1
- echo $?
+ which "$1" > /dev/null 2>&1
+ echo $?
}
diff --git a/nnn/.config/nnn/plugins/.ntfy b/nnn/.config/nnn/plugins/.ntfy
new file mode 100755
index 0000000..3a7f27f
--- /dev/null
+++ b/nnn/.config/nnn/plugins/.ntfy
@@ -0,0 +1,22 @@
+#!/usr/bin/env sh
+
+# Description: Show a notification
+#
+# Details: nnn invokes this plugin to show notification when a cp/mv/rm operation is complete.
+#
+# Dependencies: notify-send (Ubuntu)/ntfy (https://github.com/dschep/ntfy)/osascript (macOS)/notify (Haiku)
+#
+# Shell: POSIX compliant
+# Author: Anna Arad
+
+OS="$(uname)"
+
+if which notify-send >/dev/null 2>&1; then
+ notify-send nnn "Done!"
+elif [ "$OS" = "Darwin" ]; then
+ osascript -e 'display notification "Done!" with title "nnn"'
+elif which ntfy >/dev/null 2>&1; then
+ ntfy -t nnn send "Done!"
+elif [ "$OS" = "Haiku" ]; then
+ notify --title "nnn" "Done!"
+fi
diff --git a/nnn/.config/nnn/plugins/autojump b/nnn/.config/nnn/plugins/autojump
new file mode 100755
index 0000000..db10c84
--- /dev/null
+++ b/nnn/.config/nnn/plugins/autojump
@@ -0,0 +1,42 @@
+#!/usr/bin/env sh
+
+# Description: Navigate to directory using jump/autojump/zoxide
+#
+# Dependencies: jump - https://github.com/gsamokovarov/jump
+# OR autojump - https://github.com/wting/autojump
+# OR zoxide - https://github.com/ajeetdsouza/zoxide
+#
+# Note: The dependencies STORE NAVIGATION PATTERNS
+#
+# Shell: POSIX compliant
+# Authors: Marty Buchaus, Dave Snider, Tim Adler
+
+if [ -z "$NNN_PIPE" ]; then
+ echo 'ERROR: NNN_PIPE is not set' | ${PAGER:-less}
+ exit 2
+fi
+
+if which jump >/dev/null 2>&1; then
+ printf "jump to : "
+ read -r dir
+ odir="$(jump cd "$dir")"
+ printf "%s" "0c$odir" > "$NNN_PIPE"
+elif which autojump >/dev/null 2>&1; then
+ printf "jump to : "
+ read -r dir
+ odir="$(autojump "$dir")"
+ printf "%s" "0c$odir" > "$NNN_PIPE"
+elif which zoxide >/dev/null 2>&1; then
+ if which fzf >/dev/null 2>&1; then
+ 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"
+ fi
+else
+ printf "No supported autojump script found. (jump/autojump/zoxide are supported)"
+ read -r _
+fi
diff --git a/nnn/.config/nnn/plugins/bookmarks b/nnn/.config/nnn/plugins/bookmarks
new file mode 100755
index 0000000..9bf491e
--- /dev/null
+++ b/nnn/.config/nnn/plugins/bookmarks
@@ -0,0 +1,61 @@
+#!/usr/bin/env sh
+
+# Description: Use named bookmarks using symlinks
+#
+# Dependencies: fzf
+#
+# Usage:
+# 1. Create a $BOOKMARKS_DIR directory
+# By default, $BOOKMARKS_DIR is set to: ${XDG_CACHE_HOME:-$HOME/.cache}/nnn/bookmarks
+#
+# 2. Create symlinks to directories
+# `cd $BOOKMARKS_DIR`
+# `ln -s /path/to/useful/directory bookmark_name`
+# `ln -s $XDG_CONFIG_HOME/nnn/plugins nnn_plugins"
+# `ln -s /path/to/documents docs`
+# `ln -s /path/to/media media`
+# `ln -s /path/to/movies movies`
+#
+# Bonus tip: Add `$BOOKMARKS_DIR` to your `$CDPATH`
+# https://linux.101hacks.com/cd-command/cdpath/
+#
+# TODO:
+# 1. Remove `fzf` dependency
+#
+# Shell: POSIX compliant
+# Author: Todd Yamakawa
+
+if [ -z "$BOOKMARKS_DIR" ]; then
+ BOOKMARKS_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/nnn/bookmarks"
+fi
+
+# Check if NNN_PIPE is set
+if [ -z "$NNN_PIPE" ]; then
+ echo 'ERROR: NNN_PIPE is not set' | ${PAGER:-less}
+ exit 2
+fi
+
+# Get all directory symlinks
+get_links() {
+ for entry in "$1"/*; do
+
+ # Skip unless directory symlink
+ [ -h "$entry" ] || continue
+ [ -d "$entry" ] || continue
+
+ printf "%20s -> %s\n" "$(basename "$entry")" "$(readlink -f "$entry")"
+ done | fzf |
+ awk 'END {
+ if (length($1) == 0) { print "'"$PWD"'" }
+ else { print "'"$BOOKMARKS_DIR"'/"$1 }
+ }'
+}
+
+# Choose symlink with fzf
+cddir="$(get_links "$BOOKMARKS_DIR")"
+
+# Writing result to NNN_PIPE will change nnn's active directory
+# https://github.com/jarun/nnn/tree/master/plugins#send-data-to-nnn
+context=0
+printf "%s" "${context}c$(readlink -f "$cddir")" > "$NNN_PIPE"
+
diff --git a/nnn/.config/nnn/plugins/boom b/nnn/.config/nnn/plugins/boom
new file mode 100755
index 0000000..5debfad
--- /dev/null
+++ b/nnn/.config/nnn/plugins/boom
@@ -0,0 +1,47 @@
+#!/usr/bin/env sh
+
+# Description: Play random music from current directory. Identifies MP3, FLAC, M4A, WEBM, WMA.
+# You may want to set GUIPLAYER.
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+GUIPLAYER="${GUIPLAYER}"
+NUMTRACKS="${NUMTRACKS:-100}"
+
+if [ ! -z "$GUIPLAYER" ]; then
+ find . -type f \( -iname "*.mp3" -o -iname "*.flac" -o -iname "*.m4a" -o -iname "*.webm" -o -iname "*.wma" \) | shuf -n "$NUMTRACKS" | xargs -d "\n" "$GUIPLAYER" > /dev/null 2>&1 &
+
+ # detach the player
+ sleep 1
+elif which mocp >/dev/null 2>&1; then
+ cmd=$(pgrep -x mocp 2>/dev/null)
+ ret=$cmd
+
+ if [ -z "$ret" ]; then
+ # start MOC server
+ mocp -S
+ mocp -o shuffle
+ else
+ # mocp running, check if it's playing
+ state=$(mocp -i | grep "State:" | cut -d' ' -f2)
+ if [ "$state" = 'PLAY' ]; then
+ # add up to 100 random audio files
+ find . -type f \( -iname "*.mp3" -o -iname "*.flac" -o -iname "*.m4a" -o -iname "*.webm" -o -iname "*.wma" \) | head -n "$NUMTRACKS" | xargs -d "\n" mocp -a
+ exit
+ fi
+ fi
+
+ # clear MOC playlist
+ mocp -c
+ mocp -o shuffle
+
+ # add up to 100 random audio files
+ find . -type f \( -iname "*.mp3" -o -iname "*.flac" -o -iname "*.m4a" -o -iname "*.webm" -o -iname "*.wma" \) | head -n "$NUMTRACKS" | xargs -d "\n" mocp -a
+
+ # start playing
+ mocp -p
+else
+ printf "moc missing"
+ read -r _
+fi
diff --git a/nnn/.config/nnn/plugins/bulknew b/nnn/.config/nnn/plugins/bulknew
new file mode 100755
index 0000000..4010662
--- /dev/null
+++ b/nnn/.config/nnn/plugins/bulknew
@@ -0,0 +1,32 @@
+#!/usr/bin/env sh
+
+# Description: Allows for creation of multiple files/directories at the same time.
+# Plugin opens a temp file where each entry is to be written on a separate line
+#
+# Note: Only relative paths are supported. Absolute paths are ignored
+# Leading and trailing whitespace in path names is also ignored
+#
+# Shell: POSIX compliant
+# Author: KlzXS
+
+EDITOR="${EDITOR:-vi}"
+TMPDIR="${TMPDIR:-/tmp}"
+
+printf "'f'ile / 'd'ir? "
+read -r resp
+
+if [ "$resp" = "f" ]; then
+ #shellcheck disable=SC2016
+ cmd='mkdir -p "$(dirname "{}")" && touch "{}"'
+elif [ "$resp" = "d" ]; then
+ cmd='mkdir -p {}'
+else
+ exit 1
+fi
+
+tmpfile=$(mktemp "$TMPDIR/.nnnXXXXXX")
+$EDITOR "$tmpfile"
+
+sed "/^\//d" "$tmpfile" | xargs -n1 -I{} sh -c "$cmd"
+
+rm "$tmpfile"
diff --git a/nnn/.config/nnn/plugins/chksum b/nnn/.config/nnn/plugins/chksum
new file mode 100755
index 0000000..0a386e5
--- /dev/null
+++ b/nnn/.config/nnn/plugins/chksum
@@ -0,0 +1,66 @@
+#!/usr/bin/env sh
+
+# Description: Create and verify checksums
+#
+# For selection: it will generate one file containing the checksums with file names
+# [and with paths if they are in another directory]
+# the output checksum filename will be checksum_timestamp.checksum_type
+# For file: if the file is a checksum, the plugin does the verification
+# if the file is not a checksum, checksum will be generated for it
+# the output checksum filename will be filename.checksum_type
+# For directory: recursively calculates checksum for all the files in the directory
+# the output checksum filename will be directory.checksum_type
+#
+# Shell: POSIX compliant
+# Authors: ath3, Arun Prakash Jana
+
+selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+resp=f
+chsum=md5
+
+checksum_type()
+{
+ echo "possible checksums: md5, sha1, sha224, sha256, sha384, sha512"
+ printf "create md5 (m), sha256 (s), sha512 (S) (or type one of the above checksums) [default=m]: "
+ read -r chsum_resp
+ for chks in md5 sha1 sha224 sha256 sha384 sha512
+ do
+ if [ "$chsum_resp" = "$chks" ]; then
+ chsum=$chsum_resp
+ return
+ fi
+ done
+ if [ "$chsum_resp" = "s" ]; then
+ chsum=sha256
+ elif [ "$chsum_resp" = "S" ]; then
+ chsum=sha512
+ fi
+}
+
+if [ -s "$selection" ]; then
+ printf "work with selection (s) or current file (f) [default=f]: "
+ read -r resp
+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"
+elif [ -n "$1" ]; then
+ if [ -f "$1" ]; then
+ for chks in md5 sha1 sha224 sha256 sha384 sha512
+ do
+ if echo "$1" | grep -q \.${chks}$; then
+ ${chks}sum -c < "$1"
+ read -r _
+ return
+ fi
+ done
+ checksum_type
+ file=$(basename "$1").$chsum
+ ${chsum}sum "$1" > "$file"
+ elif [ -d "$1" ]; then
+ checksum_type
+ file=$(basename "$1").$chsum
+ find "$1" -type f -exec ${chsum}sum "{}" + > "$file"
+ fi
+fi
diff --git a/nnn/.config/nnn/plugins/diffs b/nnn/.config/nnn/plugins/diffs
new file mode 100755
index 0000000..294c5e7
--- /dev/null
+++ b/nnn/.config/nnn/plugins/diffs
@@ -0,0 +1,56 @@
+#!/usr/bin/env sh
+
+# Description: Show diff of 2 directories or multiple files in vimdiff
+#
+# Note: 1. vim may show the warning: 'Vim: Warning: Input is not from a terminal'
+# press 'Enter' to ignore and proceed.
+# 2. if only one file is in selection, the hovered file is considered as the
+# second file to diff with
+#
+# Shell: POSIX compliant
+# Authors: Arun Prakash Jana, ath3
+
+selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+
+if which nvim >/dev/null 2>&1; then
+ diffcmd="nvim -d"
+else
+ diffcmd="vimdiff +0"
+fi
+
+dirdiff() {
+ dir1=$(mktemp "${TMPDIR:-/tmp}"/nnn-"$(basename "$1")".XXXXXXXX)
+ dir2=$(mktemp "${TMPDIR:-/tmp}"/nnn-"$(basename "$2")".XXXXXXXX)
+ ls -A1 "$1" > "$dir1"
+ ls -A1 "$2" > "$dir2"
+ $diffcmd "$dir1" "$dir2"
+ rm "$dir1" "$dir2"
+}
+
+if [ -s "$selection" ]; then
+ arr=$(tr '\0' '\n' < "$selection")
+ if [ "$(echo "$arr" | wc -l)" -gt 1 ]; then
+ f1="$(echo "$arr" | sed -n '1p')"
+ f2="$(echo "$arr" | sed -n '2p')"
+ if [ -d "$f1" ] && [ -d "$f2" ]; then
+ dirdiff "$f1" "$f2"
+ else
+ # If xargs supports the -o option, use it to get rid of:
+ # Vim: Warning: Input is not from a terminal
+ # xargs -0 -o vimdiff < $selection
+
+ eval xargs -0 "$diffcmd" < "$selection"
+ fi
+ elif ! [ -z "$1" ]; then
+ f1="$(echo "$arr" | sed -n '1p')"
+ if [ -d "$f1" ] && [ -d "$1" ]; then
+ dirdiff "$f1" "$1"
+ elif [ -f "$f1" ] && [ -f "$1" ]; then
+ $diffcmd "$f1" "$1"
+ else
+ echo "cannot compare file with directory"
+ fi
+ else
+ echo "needs at least 2 files or directories selected for comparison"
+ fi
+fi
diff --git a/nnn/.config/nnn/plugins/dragdrop b/nnn/.config/nnn/plugins/dragdrop
index 8623f24..a69ed84 100755
--- a/nnn/.config/nnn/plugins/dragdrop
+++ b/nnn/.config/nnn/plugins/dragdrop
@@ -3,13 +3,13 @@
# 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: https://github.com/mwh/dragon
#
# Notes:
-# 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
-# 2. The user has to mm to clear nnn's selection first
+# - Files that are dropped will be added to nnn's selection
+# Some webbased files will be downloaded to current directory with curl
+# and it may overwrite some existing files
+# - The user has to mm to clear nnn's selection first
#
# Shell: POSIX compliant
# Author: 0xACE
@@ -17,7 +17,7 @@
selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
resp=f
all=
-if type dragon-drag-and-drop >/dev/null 2>&1; then
+if which dragon-drag-and-drop >/dev/null 2>&1; then
dnd="dragon-drag-and-drop"
else
dnd="dragon"
@@ -72,3 +72,4 @@ else
"$dnd" "$1" &
fi
fi
+
diff --git a/nnn/.config/nnn/plugins/dups b/nnn/.config/nnn/plugins/dups
new file mode 100755
index 0000000..98e8f72
--- /dev/null
+++ b/nnn/.config/nnn/plugins/dups
@@ -0,0 +1,70 @@
+#!/usr/bin/env sh
+
+# Description: List non-empty duplicate files in the current directory (based on size followed by MD5)
+#
+# Source: https://www.commandlinefu.com/commands/view/3555/find-duplicate-files-based-on-size-first-then-md5-hash
+#
+# Dependencies: find md5sum sort uniq xargs gsed
+#
+# Note: bash compatible required for mktemp
+#
+# Shell: bash
+# Authors: syssyphus, KlzXS
+
+# If the size of a file has more that $size_digits digits the file will be misplaced
+# 12 digits fit files up to 931GiB
+
+EDITOR="${EDITOR:-vi}"
+TMPDIR="${TMPDIR:-/tmp}"
+
+size_digits=12
+tmpfile=$(mktemp "$TMPDIR/.nnnXXXXXX")
+
+printf "\
+## This is an overview of all duplicate files found.
+## Comment out the files you wish to remove. You will be given an option to cancel.
+## Lines with double comments (##) are ignored.
+## You will have the option to remove the files with force or interactively.\n
+" > "$tmpfile"
+
+# shellcheck disable=SC2016
+find . -size +0 -type f -printf "%${size_digits}s %p\n" | sort -rn | uniq -w"${size_digits}" -D | sed -E '
+s/^ {,12}([0-9]{,12}) (.*)$/printf "%s %s\\n" "$(md5sum "\2")" "d\1"/
+' | tr '\n' '\0' | xargs -0 -n1 sh -c | sort | { uniq -w32 --all-repeated=separate; echo; } | sed -nE '
+h
+s/^(.{32}).* d([0-9]*)$/## md5sum: \1 size: \2 bytes/p
+g
+
+:loop
+N
+/.*\n$/!b loop
+p' | sed -E 's/^.{32} (.*) d[0-9]*$/\1/' >> "$tmpfile"
+
+"$EDITOR" "$tmpfile"
+
+printf "Remove commented files? (yes/no) [default=n]: "
+read -r commented
+
+if [ "$commented" = "y" ]; then
+ sedcmd="/^(##|[^#]).*/d; /^$/d; s/^# *(.*)$/\1/"
+else
+ printf "Press any key to exit"
+ read -r _
+ exit
+fi
+
+printf "Remove with force or interactive? (f/i) [default=i]: "
+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'
+else
+ #shellcheck disable=SC2016
+ sed -E "$sedcmd" "$tmpfile" | tr '\n' '\0' | xargs -0 -r sh -c 'rm -i "$0" "$@" </dev/tty'
+fi
+
+rm "$tmpfile"
+
+printf "Press any key to exit"
+read -r _
diff --git a/nnn/.config/nnn/plugins/finder b/nnn/.config/nnn/plugins/finder
new file mode 100755
index 0000000..649b711
--- /dev/null
+++ b/nnn/.config/nnn/plugins/finder
@@ -0,0 +1,28 @@
+#!/usr/bin/env sh
+
+# Description: Run custom search and list results in smart context
+#
+# Note: To enable multi select in fzf, export the following:
+# - export FZF_DEFAULT_OPTS='--bind ctrl-a:select-all,ctrl-d:deselect-all,ctrl-t:toggle'
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+. "$(dirname "$0")"/.nnn-plugin-helper
+
+printf "Examples:\n"
+printf " find . -name \"pattern*\" -print0\n"
+printf " fd pattern -0\n"
+printf " find -maxdepth 1 -size +100M -print0\n"
+printf " fd -d 2 -S +100M -0\n"
+printf " grep -rlZ pattern\n"
+printf " rg -l0 pattern\n"
+printf " fzf -m | tr %s %s\n\n" "'\n'" "'\0'"
+
+printf "cmd: "
+read -r cmd
+
+if ! [ -z "$cmd" ]; then
+ printf "%s" "+l" > "$NNN_PIPE"
+ eval "$cmd" > "$NNN_PIPE"
+fi
diff --git a/nnn/.config/nnn/plugins/fzcd b/nnn/.config/nnn/plugins/fzcd
new file mode 100755
index 0000000..8cc21ab
--- /dev/null
+++ b/nnn/.config/nnn/plugins/fzcd
@@ -0,0 +1,37 @@
+#!/usr/bin/env sh
+
+# Description: Run fzf and go to the directory of the file selected
+#
+# Shell: POSIX compliant
+# Author: Anna Arad
+
+. "$(dirname "$0")"/.nnn-plugin-helper
+
+if [ "$(cmd_exists fzf)" -eq "0" ]; then
+ sel=$(fzf)
+else
+ exit 1
+fi
+
+if [ -n "$sel" ]; then
+ if ! [ -d "$sel" ]; then
+ sel=$(dirname "$sel")
+ elif [ "$sel" = "." ]; then
+ exit 0
+ fi
+
+ # Check if selected path returned
+ # by fzf command is absolute
+ case $sel in
+ /*) nnn_cd "$sel" ;;
+ *)
+ # Remove "./" prefix if it exists
+ sel="${sel#./}"
+
+ if [ "$PWD" = "/" ]; then
+ nnn_cd "/$sel"
+ else
+ nnn_cd "$PWD/$sel"
+ fi;;
+ esac
+fi
diff --git a/nnn/.config/nnn/plugins/fzhist b/nnn/.config/nnn/plugins/fzhist
new file mode 100755
index 0000000..a3aac3a
--- /dev/null
+++ b/nnn/.config/nnn/plugins/fzhist
@@ -0,0 +1,38 @@
+#!/usr/bin/env sh
+
+# Description: Fuzzy find a command from history, edit in $EDITOR and run as a command
+# Currently supports only bash and fish history
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+if which fzf >/dev/null 2>&1; then
+ fuzzy=fzf
+else
+ exit 1
+fi
+
+shellname="$(basename "$SHELL")"
+
+if [ "$shellname" = "bash" ]; then
+ hist_file="$HOME/.bash_history"
+ entry="$("$fuzzy" < "$hist_file")"
+elif [ "$shellname" = "fish" ]; then
+ hist_file="$HOME/.config/fish/fish_history"
+ entry="$(grep "\- cmd: " "$hist_file" | cut -c 8- | "$fuzzy")"
+fi
+
+if ! [ -z "$entry" ]; then
+ tmpfile=$(mktemp)
+ echo "$entry" >> "$tmpfile"
+ $EDITOR "$tmpfile"
+
+ if [ -s "$tmpfile" ]; then
+ $SHELL -c "$(cat "$tmpfile")"
+ fi
+
+ rm "$tmpfile"
+
+ printf "Press any key to exit"
+ read -r _
+fi
diff --git a/nnn/.config/nnn/plugins/fzopen b/nnn/.config/nnn/plugins/fzopen
new file mode 100755
index 0000000..fa44e0f
--- /dev/null
+++ b/nnn/.config/nnn/plugins/fzopen
@@ -0,0 +1,38 @@
+#!/usr/bin/env sh
+
+# Description: Fuzzy find a file in directory subtree
+# Opens in $VISUAL or $EDITOR if text
+# Opens other type of files with xdg-open
+#
+# Dependencies: fd/find, fzf/skim, xdg-open
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+if which fzf >/dev/null 2>&1; then
+ cmd="$FZF_DEFAULT_COMMAND"
+ if which fd >/dev/null 2>&1; then
+ [ -z "$cmd" ] && cmd="fd -t f 2>/dev/null"
+ else
+ [ -z "$cmd" ] && cmd="find . -type f 2>/dev/null"
+ fi
+ entry="$(eval "$cmd" | fzf --delimiter / --nth=-1 --tiebreak=begin --info=hidden)"
+ # To show only the file name
+ # entry=$(find . -type f 2>/dev/null | fzf --delimiter / --with-nth=-1 --tiebreak=begin --info=hidden)
+elif which sk >/dev/null 2>&1; then
+ entry=$(find . -type f 2>/dev/null | sk)
+else
+ exit 1
+fi
+
+case "$(file -biL "$entry")" in
+ *text*)
+ "${VISUAL:-$EDITOR}" "$entry" ;;
+ *)
+ if uname | grep -q "Darwin"; then
+ open "$entry" >/dev/null 2>&1
+ else
+ xdg-open "$entry" >/dev/null 2>&1
+ fi
+ ;;
+esac
diff --git a/nnn/.config/nnn/plugins/fzz b/nnn/.config/nnn/plugins/fzz
new file mode 100755
index 0000000..049cf9d
--- /dev/null
+++ b/nnn/.config/nnn/plugins/fzz
@@ -0,0 +1,26 @@
+#!/usr/bin/env sh
+
+# Description: cd to any dir in the z database using an fzf pane
+#
+# Shell: POSIX compliant
+# Author: Nick Waywood
+
+. "$(dirname "$0")"/.nnn-plugin-helper
+
+if which fzf >/dev/null 2>&1; then
+ fuzzy=fzf
+else
+ exit 1
+fi
+
+datafile="${_Z_DATA:-$HOME/.z}"
+if [ -f "$datafile" ]; then
+ # I read the data from z's file instead of calling the z command so that the data doesn't need to be processed twice
+ sel=$(awk -F "|" '{print $1}' "$datafile" | "$fuzzy" | awk '{$1=$1};1')
+ # NOTE: Uncomment this line and comment out the line above if you want to see the weightings of the dir's in the fzf pane
+ # sel=$(awk -F "|" '{printf "%s %s\n", $2, $1}' "$datafile" | "$fuzzy" | sed 's/^[0-9,.]* *//' | awk '{$1=$1};1')
+else
+ exit 1
+fi
+
+printf "%s" "0c$sel" > "$NNN_PIPE"
diff --git a/nnn/.config/nnn/plugins/getplugs b/nnn/.config/nnn/plugins/getplugs
new file mode 100755
index 0000000..d875074
--- /dev/null
+++ b/nnn/.config/nnn/plugins/getplugs
@@ -0,0 +1,83 @@
+#!/usr/bin/env sh
+
+# Description: Update nnn plugins to installed nnn version
+#
+# Shell: POSIX compliant
+# Authors: Arun Prakash Jana, KlzXS
+
+CONFIG_DIR=${XDG_CONFIG_HOME:-$HOME/.config}/nnn/
+PLUGIN_DIR=${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins
+
+# is_cmd_exists () {
+# which "$1" > /dev/null 2>&1
+# echo $?
+# }
+
+merge () {
+ if which nvim >/dev/null 2>&1; then
+ nvim -d "$1" "$2"
+ else
+ vimdiff +0 "$1" "$2"
+ fi
+}
+
+prompt () {
+ printf "%s\n" "Plugin $1 already exists and is different."
+ printf "Keep (k), merge (m), overwrite (o) [default: k]? "
+ read -r operation
+
+ if [ "$operation" = "m" ]; then
+ op="merge"
+ elif [ "$operation" = "o" ]; then
+ op="cp -vRf"
+ else
+ op="true"
+ fi
+}
+
+# if [ "$(is_cmd_exists sudo)" -eq "0" ]; then
+# sucmd=sudo
+# elif [ "$(is_cmd_exists doas)" -eq "0" ]; then
+# sucmd=doas
+# else
+# sucmd=: # noop
+# fi
+
+if [ "$1" = "master" ] ; then
+ VER="master"
+ ARCHIVE_URL=https://github.com/jarun/nnn/archive/master.tar.gz
+elif which nnn >/dev/null 2>&1; then
+ VER=$(nnn -V)
+ ARCHIVE_URL=https://github.com/jarun/nnn/releases/download/v"$VER"/nnn-v"$VER".tar.gz
+else
+ echo "nnn is not installed"
+ exit 1
+fi
+
+# backup any earlier plugins
+if [ -d "$PLUGIN_DIR" ]; then
+ tar -C "$CONFIG_DIR" -czf "$CONFIG_DIR""plugins-$(date '+%Y%m%d%H%M').tar.gz" plugins/
+fi
+
+mkdir -p "$PLUGIN_DIR"
+cd "$CONFIG_DIR" || exit 1
+curl -Ls "$ARCHIVE_URL" -o nnn-"$VER".tar.gz
+tar -zxf nnn-"$VER".tar.gz
+
+cd nnn-"$VER"/plugins || exit 1
+
+# shellcheck disable=SC2044
+# We do not use obnoxious names for plugins
+for f in $(find . -maxdepth 1 \( ! -iname "." ! -iname "*.md" \)); do
+ if [ -f ../../plugins/"$f" ]; then
+ if [ "$(diff --brief "$f" ../../plugins/"$f")" ]; then
+ prompt "$f"
+ $op "$f" ../../plugins/
+ fi
+ else
+ cp -vRf "$f" ../../plugins/
+ fi
+done
+cd ../.. || exit 1
+
+rm -rf nnn-"$VER"/ nnn-"$VER".tar.gz
diff --git a/nnn/.config/nnn/plugins/gpgd b/nnn/.config/nnn/plugins/gpgd
new file mode 100755
index 0000000..0dde588
--- /dev/null
+++ b/nnn/.config/nnn/plugins/gpgd
@@ -0,0 +1,22 @@
+#!/usr/bin/env sh
+
+# Description: Decrypts selected files using gpg. The contents of the decrypted file are stored in a file with extension .dec
+#
+# Note: If an appropriate private key cannot be found gpg silently prints a message in the background and no files are written.
+#
+# Shell: POSIX compliant
+# Author: KlzXS
+
+selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+
+printf "(s)election/(c)urrent? [default=c] "
+read -r resp
+
+if [ "$resp" = "s" ]; then
+ files=$(tr '\0' '\n' < "$selection")
+else
+ files=$1
+fi
+
+printf "%s" "$files" | xargs -n1 -I{} gpg --decrypt --output "{}.dec" {}
+
diff --git a/nnn/.config/nnn/plugins/gpge b/nnn/.config/nnn/plugins/gpge
new file mode 100755
index 0000000..e69e116
--- /dev/null
+++ b/nnn/.config/nnn/plugins/gpge
@@ -0,0 +1,38 @@
+#!/usr/bin/env sh
+
+# Description: Encrypts selected files using gpg. Can encrypt either asymmetrically (key) or symmetrically (passphrase).
+# If asymmetric encryption is chosen a key can be chosen from the list of capable public keys using fzf.
+#
+# Note: symmetric encryption only works for a single (current) file as per gpg limitations
+#
+# Shell: POSIX compliant
+# Author: KlzXS
+
+selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+
+printf "(s)ymmetric, (a)symmetric? [default=a] "
+read -r symmetry
+
+if [ "$symmetry" = "s" ]; then
+ gpg --symmetric "$1"
+else
+ printf "(s)election/(c)urrent? [default=c] "
+ read -r resp
+
+ if [ "$resp" = "s" ]; then
+ files=$(tr '\0' '\n' < "$selection")
+ else
+ files=$1
+ fi
+
+ keyids=$(gpg --list-public-keys --with-colons | grep -E "pub:(.*:){10}.*[eE].*:" | awk -F ":" '{print $5}')
+
+ #awk needs literal $10
+ #shellcheck disable=SC2016
+ keyuids=$(printf "%s" "$keyids" | xargs -n1 -I{} sh -c 'gpg --list-key --with-colons "{}" | grep "uid" | awk -F ":" '\''{printf "%s %s\n", "{}", $10}'\''')
+
+ recipient=$(printf "%s" "$keyuids" | fzf | awk '{print $1}')
+
+ printf "%s" "$files" | xargs -n1 gpg --encrypt --recipient "$recipient"
+fi
+
diff --git a/nnn/.config/nnn/plugins/gutenread b/nnn/.config/nnn/plugins/gutenread
new file mode 100755
index 0000000..eb845bf
--- /dev/null
+++ b/nnn/.config/nnn/plugins/gutenread
@@ -0,0 +1,49 @@
+#!/usr/bin/env sh
+
+# Description: Browse Project Gutenberg catalogue by popularity, then download
+# and read a book of your choice.
+#
+# Details: Set the variable EBOOK_ID to download in html format and read in w3m.
+# Clear EBOOK_ID to browse available ebooks by popularity and set it to
+# the ID once you find an interesting one.
+# To dowload and read in epub format set READER to an epub reader like
+# epr: https://github.com/wustho/epr
+#
+# More on EBOOK_ID:
+# Wuthering Heights by Emily Brontë is at https://www.gutenberg.org/ebooks/768
+# So EBOOK_ID would be 768
+#
+# Downloaded ebooks are at ${XDG_CACHE_HOME:-$HOME/.cache}/nnn/gutenbooks/
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+EBOOK_ID="${EBOOK_ID}"
+DIR="${XDG_CACHE_HOME:-$HOME/.cache}/nnn/gutenbooks/$EBOOK_ID"
+BROWSE_LINK="http://www.gutenberg.org/ebooks/search/?sort_order=downloads"
+BROWSER="${BROWSER:-w3m}"
+READER="${READER}"
+
+if [ -n "$EBOOK_ID" ]; then
+ if [ ! -e "$DIR" ]; then
+ mkdir -p "$DIR"
+ cd "$DIR" || exit 1
+
+ if [ -z "$READER" ]; then
+ curl -L -O "https://www.gutenberg.org/files/$EBOOK_ID/$EBOOK_ID-h.zip"
+ unzip "$EBOOK_ID"-h.zip
+ else
+ curl -L -o "$EBOOK_ID".epub "http://www.gutenberg.org/ebooks/$EBOOK_ID.epub.noimages"
+ fi
+ fi
+
+ if [ -d "$DIR" ]; then
+ if [ -z "$READER" ]; then
+ "$BROWSER" "$DIR/$EBOOK_ID-h/$EBOOK_ID-h.htm"
+ else
+ "$READER" "$DIR/$EBOOK_ID.epub"
+ fi
+ fi
+else
+ "$BROWSER" "$BROWSE_LINK"
+fi
diff --git a/nnn/.config/nnn/plugins/hexview b/nnn/.config/nnn/plugins/hexview
new file mode 100755
index 0000000..ce17a60
--- /dev/null
+++ b/nnn/.config/nnn/plugins/hexview
@@ -0,0 +1,15 @@
+#!/usr/bin/env sh
+
+# Description: View a file in hex
+# Dependencies: hx (https://github.com/krpors/hx)/xxd and $PAGER
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+if ! [ -z "$1" ]; then
+ if which hx >/dev/null 2>&1; then
+ hx "$1"
+ else
+ xxd "$1" | $PAGER
+ fi
+fi
diff --git a/nnn/.config/nnn/plugins/imgresize b/nnn/.config/nnn/plugins/imgresize
new file mode 100755
index 0000000..d85d4b5
--- /dev/null
+++ b/nnn/.config/nnn/plugins/imgresize
@@ -0,0 +1,30 @@
+#!/usr/bin/env sh
+
+# Description: Resize images in a directory to screen resolution with imgp
+# imgp homepage: https://github.com/jarun/imgp
+#
+# Notes:
+# 1. Set res if you don't want to be prompted for desktop resolution every time
+# 2. MINSIZE is set to 1MB by default, adjust it if you want
+# 3. imgp options used:
+# a - adaptive mode
+# c - convert PNG to JPG
+# k - skip images matching specified hres/vres
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+# set resolution (e.g. 1920x1080)
+res="${RESOLUTION}"
+
+# set minimum image size (in bytes) to resize (default: 1MB)
+MINSIZE="${MINSIZE:-1048576}"
+
+if [ -z "$res" ]; then
+ printf "desktop resolution (hxv): "
+ read -r res
+fi
+
+if ! [ -z "$res" ] && ! [ -z "$MINSIZE" ]; then
+ imgp -ackx "$res" -s "$MINSIZE"
+fi
diff --git a/nnn/.config/nnn/plugins/imgthumb b/nnn/.config/nnn/plugins/imgthumb
new file mode 100755
index 0000000..8882115
--- /dev/null
+++ b/nnn/.config/nnn/plugins/imgthumb
@@ -0,0 +1,17 @@
+#!/usr/bin/env sh
+
+# Description: View thumbnail of an image or a directory of images with lsix
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+if ! [ -z "$1" ]; then
+ if [ -d "$1" ]; then
+ lsix "$1"/*
+ else
+ lsix "$1"
+ fi
+
+ printf "Press any key to exit..."
+ read -r _
+fi
diff --git a/nnn/.config/nnn/plugins/imgur b/nnn/.config/nnn/plugins/imgur
new file mode 100755
index 0000000..e95360c
--- /dev/null
+++ b/nnn/.config/nnn/plugins/imgur
@@ -0,0 +1,595 @@
+#!/usr/bin/env bash
+
+##########################################################################
+# The MIT License
+#
+# Copyright (c) jomo
+#
+# Permission is hereby granted, free of charge,
+# to any person obtaining a copy of this software and
+# associated documentation files (the "Software"), to
+# deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify,
+# merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom
+# the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice
+# shall be included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+##########################################################################
+
+# https://github.com/jomo/imgur-screenshot
+# https://imgur.com/tools
+#
+# Slightly modified for `nnn` integration
+#
+# Shell: bash
+# Description: Upload an image file to imgur
+
+if [ "${1}" = "--debug" ]; then
+ echo "########################################"
+ echo "Enabling debug mode"
+ echo "Please remove credentials before pasting"
+ echo "########################################"
+ echo ""
+ uname -a
+ for arg in ${0} "${@}"; do
+ echo -n "'${arg}' "
+ done
+ echo -e "\n"
+ shift
+ set -x
+fi
+
+current_version="v1.7.4"
+
+function is_mac() {
+ uname | grep -q "Darwin"
+}
+
+### IMGUR-SCREENSHOT DEFAULT CONFIG ####
+
+# You can override the config in ~/.config/imgur-screenshot/settings.conf
+
+imgur_anon_id="ea6c0ef2987808e"
+imgur_icon_path="${HOME}/Pictures/imgur.png"
+
+imgur_acct_key=""
+imgur_secret=""
+login="false"
+album_title=""
+album_id=""
+credentials_file="${HOME}/.config/imgur-screenshot/credentials.conf"
+
+file_name_format="imgur-%Y_%m_%d-%H:%M:%S.png" # when using scrot, must end with .png!
+file_dir="${HOME}/Pictures"
+
+upload_connect_timeout="5"
+upload_timeout="120"
+upload_retries="1"
+
+# shellcheck disable=SC2034
+if is_mac; then
+ screenshot_select_command="screencapture -i %img"
+ screenshot_window_command="screencapture -iWa %img"
+ screenshot_full_command="screencapture %img"
+ open_command="open %url"
+else
+ screenshot_select_command="scrot -s %img"
+ screenshot_window_command="scrot %img"
+ screenshot_full_command="scrot %img"
+ open_command="xdg-open %url"
+fi
+open="true"
+
+mode="select"
+edit_command="gimp %img"
+edit="false"
+exit_on_album_creation_fail="true"
+
+log_file="${HOME}/.imgur-screenshot.log"
+
+auto_delete=""
+copy_url="true"
+keep_file="true"
+check_update="true"
+
+# NOTICE: if you make changes here, also edit the docs at
+# https://github.com/jomo/imgur-screenshot/wiki/Config
+
+# You can override the config in ~/.config/imgur-screenshot/settings.conf
+
+############## END CONFIG ##############
+
+settings_path="${HOME}/.config/imgur-screenshot/settings.conf"
+if [ -f "${settings_path}" ]; then
+ source "${settings_path}"
+fi
+
+# dependency check
+if [ "${1}" = "--check" ]; then
+ (which grep &>/dev/null && echo "OK: found grep") || echo "ERROR: grep not found"
+ if is_mac; then
+ if which growlnotify &>/dev/null; then
+ echo "OK: found growlnotify"
+ elif which terminal-notifier &>/dev/null; then
+ echo "OK: found terminal-notifier"
+ else
+ echo "ERROR: growlnotify nor terminal-notifier found"
+ fi
+ (which screencapture &>/dev/null && echo "OK: found screencapture") || echo "ERROR: screencapture not found"
+ (which pbcopy &>/dev/null && echo "OK: found pbcopy") || echo "ERROR: pbcopy not found"
+ else
+ (which notify-send &>/dev/null && echo "OK: found notify-send") || echo "ERROR: notify-send (from libnotify-bin) not found"
+ (which scrot &>/dev/null && echo "OK: found scrot") || echo "ERROR: scrot not found"
+ (which xclip &>/dev/null && echo "OK: found xclip") || echo "ERROR: xclip not found"
+ fi
+ (which curl &>/dev/null && echo "OK: found curl") || echo "ERROR: curl not found"
+ exit 0
+fi
+
+
+# notify <'ok'|'error'> <title> <text>
+function notify() {
+ if is_mac; then
+ if which growlnotify &>/dev/null; then
+ growlnotify --icon "${imgur_icon_path}" --iconpath "${imgur_icon_path}" --title "${2}" --message "${3}"
+ else
+ terminal-notifier -appIcon "${imgur_icon_path}" -contentImage "${imgur_icon_path}" -title "imgur: ${2}" -message "${3}"
+ fi
+ else
+ if [ "${1}" = "error" ]; then
+ notify-send -a ImgurScreenshot -u critical -c "im.error" -i "${imgur_icon_path}" -t 500 "imgur: ${2}" "${3}"
+ else
+ notify-send -a ImgurScreenshot -u low -c "transfer.complete" -i "${imgur_icon_path}" -t 500 "imgur: ${2}" "${3}"
+ fi
+ fi
+}
+
+function take_screenshot() {
+ echo "Please select area"
+ is_mac || sleep 0.1 # https://bbs.archlinux.org/viewtopic.php?pid=1246173#p1246173
+
+ cmd="screenshot_${mode}_command"
+ cmd=${!cmd//\%img/${1}}
+
+ if ! shot_err="$(${cmd} &>/dev/null)"; then #takes a screenshot with selection
+ echo "Failed to take screenshot '${1}': '${shot_err}'. For more information visit https://github.com/jomo/imgur-screenshot/wiki/Troubleshooting" | tee -a "${log_file}"
+ notify error "Something went wrong :(" "Information has been logged"
+ exit 1
+ fi
+}
+
+function check_for_update() {
+ # exit non-zero on HTTP error, output only the body (no stats) but output errors, follow redirects, output everything to stdout
+ remote_version="$(curl --compressed -fsSL --stderr - "https://api.github.com/repos/jomo/imgur-screenshot/releases" | grep -Em 1 --color 'tag_name":\s*".*"' | cut -d '"' -f 4)"
+ if ! [ -z "$remote_version" ]; then
+ if [ ! "${current_version}" = "${remote_version}" ] && [ ! -z "${current_version}" ] && [ ! -z "${remote_version}" ]; then
+ echo "Update found!"
+ echo "Version ${remote_version} is available (You have ${current_version})"
+ notify ok "Update found" "Version ${remote_version} is available (You have ${current_version}). https://github.com/jomo/imgur-screenshot"
+ echo "Check https://github.com/jomo/imgur-screenshot/releases/${remote_version} for more info."
+ elif [ -z "${current_version}" ] || [ -z "${remote_version}" ]; then
+ echo "Invalid empty version string"
+ echo "Current (local) version: '${current_version}'"
+ echo "Latest (remote) version: '${remote_version}'"
+ else
+ echo "Version ${current_version} is up to date."
+ fi
+ else
+ echo "Failed to check for latest version: ${remote_version}"
+ fi
+}
+
+function check_oauth2_client_secrets() {
+ if [ -z "${imgur_acct_key}" ] || [ -z "${imgur_secret}" ]; then
+ echo "In order to upload to your account, register a new application at:"
+ echo "https://api.imgur.com/oauth2/addclient"
+ echo "Select 'OAuth 2 authorization without a callback URL'"
+ echo "Then, set the imgur_acct_key (Client ID) and imgur_secret in your config."
+ exit 1
+ fi
+}
+
+function load_access_token() {
+ token_expire_time=0
+ # check for saved access_token and its expiration date
+ if [ -f "${credentials_file}" ]; then
+ source "${credentials_file}"
+ fi
+ current_time="$(date +%s)"
+ preemptive_refresh_time="$((10*60))"
+ expired="$((current_time > (token_expire_time - preemptive_refresh_time)))"
+ if [ ! -z "${refresh_token}" ]; then
+ # token already set
+ if [ "${expired}" -eq "0" ]; then
+ # token expired
+ refresh_access_token "${credentials_file}"
+ fi
+ else
+ acquire_access_token "${credentials_file}"
+ fi
+}
+
+function acquire_access_token() {
+ check_oauth2_client_secrets
+ # prompt for a PIN
+ authorize_url="https://api.imgur.com/oauth2/authorize?client_id=${imgur_acct_key}&response_type=pin"
+ echo "Go to"
+ echo "${authorize_url}"
+ echo "and grant access to this application."
+ read -rp "Enter the PIN: " imgur_pin
+
+ if [ -z "${imgur_pin}" ]; then
+ echo "PIN not entered, exiting"
+ exit 1
+ fi
+
+ # exchange the PIN for access token and refresh token
+ response="$(curl --compressed -fsSL --stderr - \
+ -F "client_id=${imgur_acct_key}" \
+ -F "client_secret=${imgur_secret}" \
+ -F "grant_type=pin" \
+ -F "pin=${imgur_pin}" \
+ https://api.imgur.com/oauth2/token)"
+ save_access_token "${response}" "${1}"
+}
+
+function refresh_access_token() {
+ check_oauth2_client_secrets
+ token_url="https://api.imgur.com/oauth2/token"
+ # exchange the refresh token for access_token and refresh_token
+ if ! response="$(curl --compressed -fsSL --stderr - \
+ -F "client_id=${imgur_acct_key}" \
+ -F "client_secret=${imgur_secret}" \
+ -F "grant_type=refresh_token" \
+ -F "refresh_token=${refresh_token}" \
+ "${token_url}"
+ )"; then
+ # curl failed
+ handle_upload_error "${response}" "${token_url}"
+ exit 1
+ fi
+ save_access_token "${response}" "${1}"
+}
+
+function save_access_token() {
+ if ! grep -q "access_token" <<<"${1}"; then
+ # server did not send access_token
+ echo "Error: Something is wrong with your credentials:"
+ echo "${1}"
+ exit 1
+ fi
+
+ access_token="$(grep -Eo 'access_token":".*"' <<<"${1}" | cut -d '"' -f 3)"
+ refresh_token="$(grep -Eo 'refresh_token":".*"' <<<"${1}" | cut -d '"' -f 3)"
+ expires_in="$(grep -Eo 'expires_in":[0-9]*' <<<"${1}" | cut -d ':' -f 2)"
+ token_expire_time="$(( $(date +%s) + expires_in ))"
+
+ # create dir if not exist
+ mkdir -p "$(dirname "${2}")" 2>/dev/null
+ touch "${2}" && chmod 600 "${2}"
+ cat <<EOF > "${2}"
+access_token="${access_token}"
+refresh_token="${refresh_token}"
+token_expire_time="${token_expire_time}"
+EOF
+}
+
+function fetch_account_info() {
+ response="$(curl --compressed --connect-timeout "${upload_connect_timeout}" -m "${upload_timeout}" --retry "${upload_retries}" -fsSL --stderr - -H "Authorization: Bearer ${access_token}" https://api.imgur.com/3/account/me)"
+ if grep -Eq '"success":\s*true' <<<"${response}"; then
+ username="$(grep -Eo '"url":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
+ echo "Logged in as ${username}."
+ echo "https://${username}.imgur.com"
+ else
+ echo "Failed to fetch info: ${response}"
+ fi
+}
+
+function delete_image() {
+ response="$(curl --compressed -X DELETE -fsSL --stderr - -H "Authorization: Client-ID ${1}" "https://api.imgur.com/3/image/${2}")"
+ if grep -Eq '"success":\s*true' <<<"${response}"; then
+ echo "Image successfully deleted (delete hash: ${2})." >> "${3}"
+ else
+ echo "The Image could not be deleted: ${response}." >> "${3}"
+ fi
+}
+
+function upload_authenticated_image() {
+ echo "Uploading '${1}'..."
+ title="$(echo "${1}" | rev | cut -d "/" -f 1 | cut -d "." -f 2- | rev)"
+ if [ -n "${album_id}" ]; then
+ response="$(curl --compressed --connect-timeout "${upload_connect_timeout}" -m "${upload_timeout}" --retry "${upload_retries}" -fsSL --stderr - -F "title=${title}" -F "image=@\"${1}\"" -F "album=${album_id}" -H "Authorization: Bearer ${access_token}" https://api.imgur.com/3/image)"
+ else
+ response="$(curl --compressed --connect-timeout "${upload_connect_timeout}" -m "${upload_timeout}" --retry "${upload_retries}" -fsSL --stderr - -F "title=${title}" -F "image=@\"${1}\"" -H "Authorization: Bearer ${access_token}" https://api.imgur.com/3/image)"
+ fi
+
+ # JSON parser premium edition (not really)
+ if grep -Eq '"success":\s*true' <<<"${response}"; then
+ img_id="$(grep -Eo '"id":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
+ img_ext="$(grep -Eo '"link":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4 | rev | cut -d "." -f 1 | rev)" # "link" itself has ugly '\/' escaping and no https!
+ del_id="$(grep -Eo '"deletehash":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
+
+ if [ ! -z "${auto_delete}" ]; then
+ export -f delete_image
+ echo "Deleting image in ${auto_delete} seconds."
+ nohup /bin/bash -c "sleep ${auto_delete} && delete_image ${imgur_anon_id} ${del_id} ${log_file}" &
+ fi
+
+ handle_upload_success "https://i.imgur.com/${img_id}.${img_ext}" "https://imgur.com/delete/${del_id}" "${1}"
+ else # upload failed
+ err_msg="$(grep -Eo '"error":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
+ test -z "${err_msg}" && err_msg="${response}"
+ handle_upload_error "${err_msg}" "${1}"
+ fi
+}
+
+function upload_anonymous_image() {
+ echo "Uploading '${1}'..."
+ title="$(echo "${1}" | rev | cut -d "/" -f 1 | cut -d "." -f 2- | rev)"
+ if [ -n "${album_id}" ]; then
+ response="$(curl --compressed --connect-timeout "${upload_connect_timeout}" -m "${upload_timeout}" --retry "${upload_retries}" -fsSL --stderr - -H "Authorization: Client-ID ${imgur_anon_id}" -F "title=${title}" -F "image=@\"${1}\"" -F "album=${album_id}" https://api.imgur.com/3/image)"
+ else
+ response="$(curl --compressed --connect-timeout "${upload_connect_timeout}" -m "${upload_timeout}" --retry "${upload_retries}" -fsSL --stderr - -H "Authorization: Client-ID ${imgur_anon_id}" -F "title=${title}" -F "image=@\"${1}\"" https://api.imgur.com/3/image)"
+ fi
+ # JSON parser premium edition (not really)
+ if grep -Eq '"success":\s*true' <<<"${response}"; then
+ img_id="$(grep -Eo '"id":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
+ img_ext="$(grep -Eo '"link":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4 | rev | cut -d "." -f 1 | rev)" # "link" itself has ugly '\/' escaping and no https!
+ del_id="$(grep -Eo '"deletehash":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
+
+ if [ ! -z "${auto_delete}" ]; then
+ export -f delete_image
+ echo "Deleting image in ${auto_delete} seconds."
+ nohup /bin/bash -c "sleep ${auto_delete} && delete_image ${imgur_anon_id} ${del_id} ${log_file}" &
+ fi
+
+ handle_upload_success "https://i.imgur.com/${img_id}.${img_ext}" "https://imgur.com/delete/${del_id}" "${1}"
+ else # upload failed
+ err_msg="$(grep -Eo '"error":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
+ test -z "${err_msg}" && err_msg="${response}"
+ handle_upload_error "${err_msg}" "${1}"
+ fi
+}
+
+function handle_upload_success() {
+ echo ""
+ echo "image link: ${1}"
+ echo "delete link: ${2}"
+
+ if [ "${copy_url}" = "true" ] && [ -z "${album_title}" ]; then
+ if is_mac; then
+ echo -n "${1}" | pbcopy
+ else
+ echo -n "${1}" | xclip -selection clipboard
+ fi
+ echo "URL copied to clipboard"
+ fi
+
+ # print to log file: image link, image location, delete link
+ echo -e "${1}\t${3}\t${2}" >> "${log_file}"
+
+ notify ok "Upload done!" "${1}"
+
+# if [ ! -z "${open_command}" ] && [ "${open}" = "true" ]; then
+# open_cmd=${open_command//\%url/${1}}
+# open_cmd=${open_cmd//\%img/${2}}
+# echo "Opening '${open_cmd}'"
+# eval "${open_cmd}"
+# fi
+}
+
+function handle_upload_error() {
+ error="Upload failed: \"${1}\""
+ echo "${error}"
+ echo -e "Error\t${2}\t${error}" >> "${log_file}"
+ notify error "Upload failed :(" "${1}"
+}
+
+function handle_album_creation_success() {
+ echo ""
+ echo "Album link: ${1}"
+ echo "Delete hash: ${2}"
+ echo ""
+
+ notify ok "Album created!" "${1}"
+
+ if [ "${copy_url}" = "true" ]; then
+ if is_mac; then
+ echo -n "${1}" | pbcopy
+ else
+ echo -n "${1}" | xclip -selection clipboard
+ fi
+ echo "URL copied to clipboard"
+ fi
+
+ # print to log file: album link, album title, delete hash
+ echo -e "${1}\t\"${3}\"\t${2}" >> "${log_file}"
+}
+
+function handle_album_creation_error() {
+ error="Album creation failed: \"${1}\""
+ echo -e "Error\t${2}\t${error}" >> "${log_file}"
+ notify error "Album creation failed :(" "${1}"
+ if [ ${exit_on_album_creation_fail} ]; then
+ exit 1
+ fi
+}
+
+while [ ${#} != 0 ]; do
+ case "${1}" in
+ -h | --help)
+ echo "usage: ${0} [--debug] [-c | --check | -v | -h | -u]"
+ echo " ${0} [--debug] [option]... [file]..."
+ echo ""
+ echo " --debug Enable debugging, must be first option"
+ echo " -h, --help Show this help, exit"
+ echo " -v, --version Show current version, exit"
+ echo " --check Check if all dependencies are installed, exit"
+ echo " -c, --connect Show connected imgur account, exit"
+ echo " -o, --open <true|false> Override 'open' config"
+ echo " -e, --edit <true|false> Override 'edit' config"
+ echo " -i, --edit-command <command> Override 'edit_command' config (include '%img'), sets --edit 'true'"
+ echo " -l, --login <true|false> Override 'login' config"
+ echo " -a, --album <album_title> Create new album and upload there"
+ echo " -A, --album-id <album_id> Override 'album_id' config"
+ echo " -k, --keep-file <true|false> Override 'keep_file' config"
+ echo " -d, --auto-delete <s> Automatically delete image after <s> seconds"
+ echo " -u, --update Check for updates, exit"
+ echo " file Upload file instead of taking a screenshot"
+ exit 0;;
+ -v | --version)
+ echo "${current_version}"
+ exit 0;;
+ -s | --select)
+ mode="select"
+ shift;;
+ -w | --window)
+ mode="window"
+ shift;;
+ -f | --full)
+ mode="full"
+ shift;;
+ -o | --open)
+ # shellcheck disable=SC2034
+ open="${2}"
+ shift 2;;
+ -e | --edit)
+ edit="${2}"
+ shift 2;;
+ -i | --edit-command)
+ edit_command="${2}"
+ edit="true"
+ shift 2;;
+ -l | --login)
+ login="${2}"
+ shift 2;;
+ -c | --connect)
+ load_access_token
+ fetch_account_info
+ exit 0;;
+ -a | --album)
+ album_title="${2}"
+ shift 2;;
+ -A | --album-id)
+ album_id="${2}"
+ shift 2;;
+ -k | --keep-file)
+ keep_file="${2}"
+ shift 2;;
+ -d | --auto-delete)
+ auto_delete="${2}"
+ shift 2;;
+ -u | --update)
+ check_for_update
+ exit 0;;
+ *)
+ upload_files=("${@}")
+ break;;
+ esac
+done
+
+if [ "${login}" = "true" ]; then
+ # load before changing directory
+ load_access_token
+fi
+
+
+if [ -n "${album_title}" ]; then
+ if [ "${login}" = "true" ]; then
+ response="$(curl -fsSL --stderr - \
+ -F "title=${album_title}" \
+ -H "Authorization: Bearer ${access_token}" \
+ https://api.imgur.com/3/album)"
+ else
+ response="$(curl -fsSL --stderr - \
+ -F "title=${album_title}" \
+ -H "Authorization: Client-ID ${imgur_anon_id}" \
+ https://api.imgur.com/3/album)"
+ fi
+ if grep -Eq '"success":\s*true' <<<"${response}"; then # Album creation successful
+ echo "Album '${album_title}' successfully created"
+ album_id="$(grep -Eo '"id":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
+ del_id="$(grep -Eo '"deletehash":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
+ handle_album_creation_success "http://imgur.com/a/${album_id}" "${del_id}" "${album_title}"
+
+ if [ "${login}" = "false" ]; then
+ album_id="${del_id}"
+ fi
+ else # Album creation failed
+ err_msg="$(grep -Eo '"error":\s*"[^"]+"' <<<"${response}" | cut -d "\"" -f 4)"
+ test -z "${err_msg}" && err_msg="${response}"
+ handle_album_creation_error "${err_msg}" "${album_title}"
+ fi
+fi
+
+if [ -z "${upload_files[*]}" ]; then
+ upload_files[0]=""
+fi
+
+for upload_file in "${upload_files[@]}"; do
+
+ if [ -z "${upload_file}" ]; then
+ cd "${file_dir}" || exit 1
+
+ # new filename with date
+ img_file="$(date +"${file_name_format}")"
+ take_screenshot "${img_file}"
+ else
+ # upload file instead of screenshot
+ img_file="${upload_file}"
+ fi
+
+ # get full path
+ #cd "$(dirname "$(realpath "${img_file}")")"
+ #img_file="$(realpath "${img_file}")"
+
+ # check if file exists
+ if ! [ -f "${img_file}" ]; then
+ echo "file '${img_file}' doesn't exist !"
+ read -r _
+ exit 1
+ fi
+
+ # open image in editor if configured
+ if [ "${edit}" = "true" ]; then
+ edit_cmd=${edit_command//\%img/${img_file}}
+ echo "Opening editor '${edit_cmd}'"
+ if ! (eval "${edit_cmd}"); then
+ echo "Error for image '${img_file}': command '${edit_cmd}' failed, not uploading. For more information visit https://github.com/jomo/imgur-screenshot/wiki/Troubleshooting" | tee -a "${log_file}"
+ notify error "Something went wrong :(" "Information has been logged"
+ exit 1
+ fi
+ fi
+
+ if [ "${login}" = "true" ]; then
+ upload_authenticated_image "${img_file}"
+ else
+ upload_anonymous_image "${img_file}"
+ fi
+
+ # delete file if configured
+ if [ "${keep_file}" = "false" ] && [ -z "${1}" ]; then
+ echo "Deleting temp file ${file_dir}/${img_file}"
+ rm -rf "${img_file}"
+ fi
+
+ echo ""
+done
+
+
+if [ "${check_update}" = "true" ]; then
+ check_for_update
+fi
+
+read -r _
diff --git a/nnn/.config/nnn/plugins/imgview b/nnn/.config/nnn/plugins/imgview
new file mode 100755
index 0000000..daa0845
--- /dev/null
+++ b/nnn/.config/nnn/plugins/imgview
@@ -0,0 +1,70 @@
+#!/usr/bin/env sh
+
+# Description: Open images in hovered directory and thumbnails
+# open hovered image in sxiv or viu and browse other images in the directory
+# Dependencies: imv (https://github.com/eXeC64/imv) or,
+# sxiv (https://github.com/muennich/sxiv) or,
+# viu (https://github.com/atanunq/viu), less
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+abspath() {
+ case "$1" in
+ /*) printf "%s\n" "$1";;
+ *) printf "%s\n" "$PWD/$1";;
+ esac
+}
+
+listimages() {
+ find -L "$(dirname "$target")" -maxdepth 1 -type f -iregex \
+ '.*\(jpe?g\|bmp\|webp\|png\|gif\)$' -print0 | sort -z
+}
+
+view_dir() {
+ target="$(abspath "$2")"
+ count="$(listimages | grep -a -m 1 -ZznF "$target" | cut -d: -f1)"
+
+ if [ -n "$count" ]; then
+ if [ "$1" = 'sxiv' ]; then
+ listimages | xargs -0 "$1" -an "$count" --
+ else
+ listimages | xargs -0 "$1" -n "$count" --
+ fi
+ else
+ shift
+ "$1" -- "$@" # fallback
+ fi
+}
+
+if [ -z "$1" ] || ! [ -s "$1" ]; then
+ printf "empty file"
+ read -r _
+ exit 1
+fi
+
+if uname | grep -q "Darwin"; then
+ if [ -f "$1" ]; then
+ open "$1" >/dev/null 2>&1 &
+ fi
+# `imvr` is often callable as `imv` on Linux distros
+# You might need to change the reference below
+elif which imvr >/dev/null 2>&1; then
+ if [ -f "$1" ]; then
+ view_dir imvr "$1" >/dev/null 2>&1 &
+ elif [ -d "$1" ] || [ -h "$1" ]; then
+ imvr "$1" >/dev/null 2>&1 &
+ fi
+elif which sxiv >/dev/null 2>&1; then
+ if [ -f "$1" ]; then
+ view_dir sxiv "$1" >/dev/null 2>&1 &
+ elif [ -d "$1" ] || [ -h "$1" ]; then
+ sxiv -aqt "$1" >/dev/null 2>&1 &
+ fi
+elif which viu >/dev/null 2>&1; then
+ viu -n "$1" | less -R
+else
+ printf "Please install imv/sxiv/viu and check their callable names match the plugin source"
+ read -r _
+ exit 2
+fi
diff --git a/nnn/.config/nnn/plugins/ipinfo b/nnn/.config/nnn/plugins/ipinfo
new file mode 100755
index 0000000..4ff6f41
--- /dev/null
+++ b/nnn/.config/nnn/plugins/ipinfo
@@ -0,0 +1,13 @@
+#!/usr/bin/env sh
+
+# Description: Shows the external IP address and whois information. Useful over VPNs.
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+IP=$(curl -s ifconfig.me)
+
+whois "$IP"
+echo your external IP address is "$IP"
+
+read -r _
diff --git a/nnn/.config/nnn/plugins/kdeconnect b/nnn/.config/nnn/plugins/kdeconnect
new file mode 100755
index 0000000..f1cfd95
--- /dev/null
+++ b/nnn/.config/nnn/plugins/kdeconnect
@@ -0,0 +1,17 @@
+#!/usr/bin/env sh
+
+# Description: Send the selected files to your Android device using kdeconnect-cli. You must have installed and configured kdeconnect both on the Android device and on the PC.
+#
+# Shell: POSIX compliant
+# Author: juacq97
+
+selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+
+id=$(kdeconnect-cli -a --id-only | awk '{print $1}')
+if [ "$(find "$selection")" ]; then
+ kdeconnect-cli -d "$id" --share "$(cat "$selection")"
+# If you want a system notification, uncomment the next 3 lines.
+# notify-send -a "Kdeconnect" "Sending $(cat "$selection")"
+#else
+# notify-send -a "Kdeconnect" "No file selected"
+fi
diff --git a/nnn/.config/nnn/plugins/launch b/nnn/.config/nnn/plugins/launch
new file mode 100755
index 0000000..19855f9
--- /dev/null
+++ b/nnn/.config/nnn/plugins/launch
@@ -0,0 +1,42 @@
+#!/usr/bin/env sh
+
+# Description: Independent POSIX-compliant GUI application launcher.
+# Fuzzy find executables in $PATH and launch an application.
+# stdin, stdout, stderr are suppressed so CLI tools exit silently.
+#
+# To configure launch as an independent app launcher add a keybind
+# to open launch in a terminal e.g.,
+#
+# xfce4-terminal -e "${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins/launch
+#
+# Dependencies: fzf
+#
+# Usage: launch [delay]
+# delay is in seconds, if omitted launch waits for 1 sec
+#
+# Integration with nnn: launch is installed with other plugins, nnn picks it up.
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+# shellcheck disable=SC2086
+
+IFS=':'
+
+get_selection() {
+ if which fzf >/dev/null 2>&1; then
+ { IFS=':'; ls -H $PATH; } | sort | fzf
+ else
+ exit 1
+ fi
+}
+
+if selection=$( get_selection ); then
+ setsid "$selection" 2>/dev/null 1>/dev/null &
+
+ if ! [ -z "$1" ]; then
+ sleep "$1"
+ else
+ sleep 1
+ fi
+fi
diff --git a/nnn/.config/nnn/plugins/mediainf b/nnn/.config/nnn/plugins/mediainf
index 22ae824..15640b4 100755
--- a/nnn/.config/nnn/plugins/mediainf
+++ b/nnn/.config/nnn/plugins/mediainf
@@ -7,7 +7,7 @@
# Shell: POSIX compliant
# Author: Arun Prakash Jana
-if [ -n "$1" ] && [ -f "$1" ]; then
+if ! [ -z "$1" ] && [ -f "$1" ]; then
mediainfo "$1" | $PAGER
# exiftool "$1" | $PAGER
fi
diff --git a/nnn/.config/nnn/plugins/mimelist b/nnn/.config/nnn/plugins/mimelist
index d601cd8..743d305 100755
--- a/nnn/.config/nnn/plugins/mimelist
+++ b/nnn/.config/nnn/plugins/mimelist
@@ -1,15 +1,21 @@
-
#!/usr/bin/env sh
-# Description: Find and list files by mime type in smart context
+# Description: Run fd/find in subtree and list files by mime type in smart context
+# Dependencies: fd/find
#
# Shell: POSIX compliant
# Author: Arun Prakash Jana
. "$(dirname "$0")"/.nnn-plugin-helper
+if [ "$(cmd_exists fd)" -eq "0" ]; then
+ fd=fd
+else
+ fd=find
+fi
+
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"
+$fd | file -if- | grep "$mime" | awk -F: '{printf "%s\0", $1}' > "$NNN_PIPE"
diff --git a/nnn/.config/nnn/plugins/moclyrics b/nnn/.config/nnn/plugins/moclyrics
new file mode 100755
index 0000000..04e899e
--- /dev/null
+++ b/nnn/.config/nnn/plugins/moclyrics
@@ -0,0 +1,39 @@
+#!/usr/bin/env sh
+
+# Description: Fetches the lyrics of the track currently playing in MOC
+# Dependencies: ddgr (https://github.com/jarun/ddgr)
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+# Check if MOC server is running
+cmd=$(pgrep -x mocp 2>/dev/null)
+ret=$cmd
+if [ -z "$ret" ]; then
+ exit
+fi
+
+# Grab the output
+out="$(mocp -i)"
+
+# Check if anything is playing
+state=$(echo "$out" | grep "State:" | cut -d' ' -f2)
+if ! [ "$state" = 'PLAY' ]; then
+ exit
+fi
+
+# Try by Artist and Song Title first
+ARTIST="$(echo "$out" | grep 'Artist:' | cut -d':' -f2 | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//')"
+TITLE="$(echo "$out" | grep 'SongTitle:' | cut -d':' -f2 | sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//')"
+
+if ! [ -z "$ARTIST" ] && ! [ -z "$TITLE" ]; then
+ ddgr -w azlyrics.com --ducky "$ARTIST" "$TITLE"
+else
+ # Try by file name
+ FILENAME="$(basename "$(echo "$out" | grep 'File:' | cut -d':' -f2)")"
+ FILENAME="$(echo "${FILENAME%%.*}" | tr -d -)"
+
+ if ! [ -z "$FILENAME" ]; then
+ ddgr -w azlyrics.com --ducky "$FILENAME"
+ fi
+fi
diff --git a/nnn/.config/nnn/plugins/mocplay b/nnn/.config/nnn/plugins/mocplay
new file mode 100755
index 0000000..39c7c9a
--- /dev/null
+++ b/nnn/.config/nnn/plugins/mocplay
@@ -0,0 +1,84 @@
+#!/usr/bin/env sh
+
+# Description: Appends and optionally plays music in MOC
+#
+# Notes:
+# - if selection is available, plays it, else plays the current file or directory
+# - appends tracks and exits is MOC is running, else clears playlist and adds tracks
+# - to let mocp shuffle tracks, set SHUFFLE=1
+#
+# Shell: POSIX compliant
+# Authors: Arun Prakash Jana, ath3
+
+IFS="$(printf '\n\r')"
+selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+cmd=$(pgrep -x mocp 2>/dev/null)
+ret=$cmd
+
+SHUFFLE="${SHUFFLE:-0}"
+
+mocp_add ()
+{
+ if [ "$SHUFFLE" = 1 ]; then
+ if [ "$resp" = "y" ]; then
+ arr=$(tr '\0' '\n' < "$selection")
+ elif [ -n "$1" ]; then
+ arr="$1"
+ fi
+
+ for entry in $arr
+ do
+ if [ -d "$entry" ]; then
+ arr2=$arr2$(find "$entry" -type f \( ! -iname "*.m3u" ! -iname "*.pls" \))
+ elif echo "$entry" | grep -qv '\.m3u$\|\.pls$' ; then
+ arr2=$(printf "%s\n%s" "$entry" "$arr2")
+ fi
+ done
+
+ mocp -o shuffle
+ echo "$arr2" | xargs -d "\n" mocp -a
+ else
+ if [ "$resp" = "y" ]; then
+ xargs < "$selection" -0 mocp -a
+ else
+ mocp -a "$1"
+ fi
+ fi
+}
+
+if [ ! -s "$selection" ] && [ -z "$1" ]; then
+ exit
+fi
+
+if [ "$2" = "opener" ]; then
+ :
+elif [ -s "$selection" ]; then
+ printf "Work with selection? Enter 'y' to confirm: "
+ read -r resp
+fi
+
+if [ -z "$ret" ]; then
+ # mocp not running
+ mocp -S
+else
+ # mocp running, check if it's playing
+ state=$(mocp -i | grep "State:" | cut -d' ' -f2)
+
+ if [ "$state" = 'PLAY' ]; then
+ # add to playlist and exit
+ mocp_add "$1"
+
+ # uncomment the line below to show mocp interface after appending
+ # mocp
+
+ exit
+ fi
+fi
+
+# clear selection and play
+mocp -c
+mocp_add "$1" "$resp"
+mocp -p
+
+# uncomment the line below to show mocp interface after appending
+# mocp
diff --git a/nnn/.config/nnn/plugins/mp3conv b/nnn/.config/nnn/plugins/mp3conv
new file mode 100755
index 0000000..b582cbc
--- /dev/null
+++ b/nnn/.config/nnn/plugins/mp3conv
@@ -0,0 +1,41 @@
+#!/usr/bin/env sh
+
+# Description: Extract audio from multimedia files and convert to mp3
+#
+# Dependency: ffmpeg compiled with libmp3lame audio codec support
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+outdir=_mp3files
+
+handle_multimedia() {
+ mime="${1}"
+ file="${2}"
+
+ case "${mime}" in
+ audio/* | video/*)
+ ffmpeg -i "${file}" -vn -codec:a libmp3lame -q:a 2 "${outdir}/${file%.*}.mp3"
+ ;;
+ *)
+ ;;
+ esac
+}
+
+printf "Process 'a'll in directory or 'c'urrent? "
+read -r resp
+
+if [ "$resp" = "a" ]; then
+ if ! [ -e "${outdir}" ]; then
+ mkdir "${outdir}"
+ fi
+
+ for f in *; do
+ if [ -f "${f}" ]; then
+ mimestr="$( file --dereference --brief --mime-type -- "${f}" )"
+ handle_multimedia "${mimestr}" "${f}"
+ fi
+ done
+elif [ "$resp" = "c" ] && [ -f "$1" ]; then
+ ffmpeg -i "${1}" -vn -codec:a libmp3lame -q:a 2 "${1%.*}.mp3"
+fi
diff --git a/nnn/.config/nnn/plugins/nbak b/nnn/.config/nnn/plugins/nbak
new file mode 100755
index 0000000..f9cb644
--- /dev/null
+++ b/nnn/.config/nnn/plugins/nbak
@@ -0,0 +1,75 @@
+#!/usr/bin/env sh
+
+# Description: Backup nnn configuration
+# - config dir content
+# - environment config
+# - shell functions and aliases
+#
+# Shell: POSIX compliant
+# Author: Léo Villeveygoux
+
+nnn_aliases="n nnn"
+
+outdir="nnn-$(whoami)@$(hostname)"
+
+outfile="${outdir}.tar.bz2"
+
+shellname="$(basename "$SHELL")"
+
+conffile="config.txt"
+
+configdir="${XDG_CONFIG_HOME:-$HOME/.config}/nnn"
+
+workdir="$PWD"
+
+tempdir="$(mktemp -d)"
+
+mkdir "$tempdir/$outdir"
+
+if [ ! -d "$tempdir" ]; then
+ echo "Can't create work directory." >&2
+ exit 1
+fi
+
+cd "$tempdir/$outdir" || exit 1
+
+# Backing up config dir content
+cp -r "$configdir" . || exit 1
+
+# Environment config
+env | sed "s/'/'\\\\''/" |\
+ awk '/^NNN_/{print "export '\''"$0"'\''"}' > "$conffile"
+
+# Shell functions/aliases
+case "$shellname" in
+ bash)
+ for name in $nnn_aliases ; do
+ if [ "$(bash -ic "type -t $name")" = "function" ] ; then
+ bash -ic "type $name" | tail -n+2 >> "$conffile"
+ elif bash -ic "alias $name" >/dev/null 2>&1 ; then
+ bash -ic "alias $name" >> "$conffile"
+ fi
+ done
+ ;;
+ zsh)
+ for name in $nnn_aliases ; do
+ if zsh -ic "functions $name" ; then
+ zsh -ic "functions $name" >> "$conffile"
+ elif zsh -ic "alias $name" ; then
+ echo alias "$(zsh -ic "alias $name")" >> "$conffile"
+ fi
+ done
+ ;;
+
+ *)
+ echo "Unknown shell, skipping alias/function checking." >&2
+ ;;
+esac
+
+cd .. || exit 1
+
+printf "Saving as '%s' ... " "$workdir/$outfile"
+
+tar caf "$workdir/$outfile" "$outdir" && echo "Done" || echo "Failed"
+
+cd "$workdir" && rm -rf "$tempdir"
diff --git a/nnn/.config/nnn/plugins/nmount b/nnn/.config/nnn/plugins/nmount
new file mode 100755
index 0000000..566119e
--- /dev/null
+++ b/nnn/.config/nnn/plugins/nmount
@@ -0,0 +1,53 @@
+#!/usr/bin/env sh
+
+# Description: Toggle mount status of a device using pmount
+# If the device is not mounted, it will be mounted.
+# If the device is mounted, it will be unmounted and powered down.
+#
+# Runs `lsblk` if 'l' is entered, exits on 'Return`.
+#
+# Note:
+# - The script uses Linux-specific lsblk to list block devices. Alternatives:
+# macOS: "diskutil list"
+# BSD: "geom disk list"
+# - The script uses udisksctl (from udisks2) to pwoer down devices. This is also Linux-specific.
+# Users on non-Linux platforms can comment it and use an alterntive to power-down disks.
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+prompt="device name ['l' lists]: "
+
+lsblk
+
+printf "\nEnsure you aren't still in the mounted device.\n"
+printf "%s" "$prompt"
+read -r dev
+
+while ! [ -z "$dev" ]
+do
+ if [ "$dev" = "l" ]; then
+ lsblk
+ elif [ "$dev" = "q" ]; then
+ exit
+ else
+ if grep -qs "$dev " /proc/mounts; then
+ sync
+ if pumount "$dev"
+ then
+ echo "$dev" unmounted.
+ if udisksctl power-off -b /dev/"$dev"
+ then
+ echo "$dev" ejected.
+ fi
+ fi
+ else
+ pmount "$dev"
+ echo "$dev" mounted to "$(lsblk -n /dev/"$dev" | rev | cut -d' ' -f1 | rev)".
+ fi
+ fi
+
+ echo
+ printf "%s" "$prompt"
+ read -r dev
+done
diff --git a/nnn/.config/nnn/plugins/nuke b/nnn/.config/nnn/plugins/nuke
new file mode 100755
index 0000000..b783633
--- /dev/null
+++ b/nnn/.config/nnn/plugins/nuke
@@ -0,0 +1,516 @@
+#!/usr/bin/env sh
+
+# #############################################################################
+# Description: Sample script to play files in apps by file type or mime
+#
+# Shell: POSIX compliant
+# Usage: nuke filepath
+#
+# Integration with nnn:
+# 1. Export the required config:
+# export NNN_OPENER=/absolute/path/to/nuke
+# # Otherwise, if nuke is in $PATH
+# # export NNN_OPENER=nuke
+# 2. Run nnn with the program option to indicate a CLI opener
+# nnn -c
+# # The -c program option overrides option -e
+# 3. nuke can use nnn plugins (e.g. mocplay is used for audio), $PATH is updated.
+#
+# Details:
+# Inspired by ranger's scope.sh, modified for usage with nnn.
+#
+# Guards against accidentally opening mime types like executables, shared libs etc.
+#
+# Tries to play 'file' (1st argument) in the following order:
+# i. by extension
+# ii. by mime (image, video, audio, pdf)
+# iii. by mime (other file types)
+#
+# Modification tips:
+# 1. Invokes CLI utilities by default. Set GUI to 1 to enable GUI apps.
+# 2. PAGER is "less -R".
+# 3. Start GUI apps in bg to unblock. Redirect stdout and strerr if required.
+# 4. Some CLI utilities are piped to the $PAGER, to wait and quit uniformly.
+# 5. If the output cannot be paged use "read -r _" to wait for user input.
+# 6. On a DE, try 'xdg-open' or 'open' in handle_fallback() as last resort.
+#
+# Feel free to change the utilities to your favourites and add more mimes.
+#
+# Defaults:
+# By extension (only the enabled ones):
+# most archives: list with atool, bsdtar
+# rar: list with unrar
+# 7-zip: list with 7z
+# pdf: zathura (GUI), pdftotext, mutool, exiftool
+# audio: mocplay (nnn plugin using MOC), mpv, media_client (Haiku), mediainfo, exiftool
+# avi|mkv|mp4: smplayer, mpv (GUI), ffmpegthumbnailer, mediainfo, exiftool
+# log: vi
+# torrent: rtorrent, transmission-show
+# odt|ods|odp|sxw: odt2txt
+# md: glow (https://github.com/charmbracelet/glow), lowdown (https://kristaps.bsd.lv/lowdown)
+# htm|html|xhtml: w3m, lynx, elinks
+# json: jq, python (json.tool module)
+# Multimedia by mime:
+# image/*: imv/sxiv (GUI), viu (https://github.com/atanunq/viu), img2txt, exiftool
+# video/*: smplayer, mpv (GUI), ffmpegthumbnailer, mediainfo, exiftool
+# audio/*: mocplay (nnn plugin using MOC), mpv, media_client (Haiku), mediainfo, exiftool
+# application/pdf: zathura (GUI), pdftotext, mutool, exiftool
+# Other mimes:
+# text/troff: man -l
+# text/* | */xml: vi
+# image/vnd.djvu): djvutxt, exiftool
+#
+# ToDo:
+# 1. Adapt, test and enable all mimes
+# 2. Clean-up the unnecessary exit codes
+# #############################################################################
+
+# set to 1 to enable GUI apps
+GUI="${GUI:-0}"
+
+set -euf -o noclobber -o noglob -o nounset
+IFS="$(printf '%b_' '\n')"; IFS="${IFS%_}" # protect trailing \n
+
+PATH=$PATH:"${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins"
+IMAGE_CACHE_PATH="$(dirname "$1")"/.thumbs
+
+FPATH="$1"
+FNAME=$(basename "$1")
+EDITOR="${EDITOR:-vi}"
+PAGER="${PAGER:-less -R}"
+ext="${FNAME##*.}"
+if [ -n "$ext" ]; then
+ ext="$(printf "%s" "${ext}" | tr '[:upper:]' '[:lower:]')"
+fi
+
+is_mac() {
+ uname | grep -q "Darwin"
+}
+
+handle_pdf() {
+ if [ "$GUI" -ne 0 ] && is_mac; then
+ open "${FPATH}" >/dev/null 2>&1 &
+ exit 0
+ elif [ "$GUI" -ne 0 ] && which zathura >/dev/null 2>&1; then
+ zathura "${FPATH}" >/dev/null 2>&1 &
+ exit 0
+ elif which pdftotext >/dev/null 2>&1; then
+ ## Preview as text conversion
+ pdftotext -l 10 -nopgbrk -q -- "${FPATH}" - | eval "$PAGER"
+ exit 0
+ elif which mutool >/dev/null 2>&1; then
+ mutool draw -F txt -i -- "${FPATH}" 1-10 | eval "$PAGER"
+ exit 0
+ elif which exiftool >/dev/null 2>&1; then
+ exiftool "${FPATH}" | eval "$PAGER"
+ exit 0
+ fi
+}
+
+handle_audio() {
+ if which mocp >/dev/null 2>&1 && which mocplay >/dev/null 2>&1; then
+ mocplay "${FPATH}" "opener" >/dev/null 2>&1
+ exit 0
+ elif which mpv >/dev/null 2>&1; then
+ mpv "${FPATH}" >/dev/null 2>&1 &
+ exit 0
+ elif which media_client >/dev/null 2>&1; then
+ media_client play "${FPATH}" >/dev/null 2>&1 &
+ exit 0
+ elif which mediainfo >/dev/null 2>&1; then
+ mediainfo "${FPATH}" | eval "$PAGER"
+ exit 0
+ elif which exiftool >/dev/null 2>&1; then
+ exiftool "${FPATH}"| eval "$PAGER"
+ exit 0
+ fi
+}
+
+handle_video() {
+ if [ "$GUI" -ne 0 ] && is_mac; then
+ open "${FPATH}" >/dev/null 2>&1 &
+ exit 0
+ elif [ "$GUI" -ne 0 ] && which smplayer >/dev/null 2>&1; then
+ smplayer "${FPATH}" >/dev/null 2>&1 &
+ exit 0
+ elif [ "$GUI" -ne 0 ] && which mpv >/dev/null 2>&1; then
+ mpv "${FPATH}" >/dev/null 2>&1 &
+ exit 0
+ elif which ffmpegthumbnailer >/dev/null 2>&1; then
+ # Thumbnail
+ [ -d "${IMAGE_CACHE_PATH}" ] || mkdir "${IMAGE_CACHE_PATH}"
+ ffmpegthumbnailer -i "${FPATH}" -o "${IMAGE_CACHE_PATH}/${FNAME}.jpg" -s 0
+ viu -n "${IMAGE_CACHE_PATH}/${FNAME}.jpg" | eval "$PAGER"
+ exit 0
+ elif which mediainfo >/dev/null 2>&1; then
+ mediainfo "${FPATH}" | eval "$PAGER"
+ exit 0
+ elif which exiftool >/dev/null 2>&1; then
+ exiftool "${FPATH}"| eval "$PAGER"
+ exit 0
+ fi
+}
+
+# handle this extension and exit
+handle_extension() {
+ case "${ext}" in
+ ## Archive
+ 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)
+ if which atool >/dev/null 2>&1; then
+ atool --list -- "${FPATH}" | eval "$PAGER"
+ exit 0
+ elif which bsdtar >/dev/null 2>&1; then
+ bsdtar --list --file "${FPATH}" | eval "$PAGER"
+ exit 0
+ fi
+ exit 1;;
+ rar)
+ if which unrar >/dev/null 2>&1; then
+ ## Avoid password prompt by providing empty password
+ unrar lt -p- -- "${FPATH}" | eval "$PAGER"
+ fi
+ exit 1;;
+ 7z)
+ if which 7z >/dev/null 2>&1; then
+ ## Avoid password prompt by providing empty password
+ 7z l -p -- "${FPATH}" | eval "$PAGER"
+ exit 0
+ fi
+ exit 1;;
+
+ ## PDF
+ pdf)
+ handle_pdf
+ exit 1;;
+
+ ## Audio
+ aac|flac|m4a|mid|midi|mpa|mp2|mp3|ogg|wav|wma)
+ handle_audio
+ exit 1;;
+
+ ## Video
+ avi|mkv|mp4)
+ handle_video
+ exit 1;;
+
+ ## Log files
+ log)
+ "$EDITOR" "${FPATH}"
+ exit 0;;
+
+ ## BitTorrent
+ torrent)
+ if which rtorrent >/dev/null 2>&1; then
+ rtorrent "${FPATH}"
+ exit 0
+ elif which transmission-show >/dev/null 2>&1; then
+ transmission-show -- "${FPATH}"
+ exit 0
+ fi
+ exit 1;;
+
+ ## OpenDocument
+ odt|ods|odp|sxw)
+ if which odt2txt >/dev/null 2>&1; then
+ ## Preview as text conversion
+ odt2txt "${FPATH}" | eval "$PAGER"
+ exit 0
+ fi
+ exit 1;;
+
+ ## Markdown
+ md)
+ if which glow >/dev/null 2>&1; then
+ glow -sdark "${FPATH}" | eval "$PAGER"
+ exit 0
+ elif which lowdown >/dev/null 2>&1; then
+ lowdown -Tterm "${FPATH}" | eval "$PAGER"
+ exit 0
+ fi
+ ;;
+
+ ## HTML
+ htm|html|xhtml)
+ ## Preview as text conversion
+ if which w3m >/dev/null 2>&1; then
+ w3m -dump "${FPATH}" | eval "$PAGER"
+ exit 0
+ elif which lynx >/dev/null 2>&1; then
+ lynx -dump -- "${FPATH}" | eval "$PAGER"
+ exit 0
+ elif which elinks >/dev/null 2>&1; then
+ elinks -dump "${FPATH}" | eval "$PAGER"
+ exit 0
+ fi
+ ;;
+
+ ## JSON
+ json)
+ if which jq >/dev/null 2>&1; then
+ jq --color-output . "${FPATH}" | eval "$PAGER"
+ exit 0
+ elif which python >/dev/null 2>&1; then
+ python -m json.tool -- "${FPATH}" | eval "$PAGER"
+ exit 0
+ fi
+ ;;
+ esac
+}
+
+abspath() {
+ case "$1" in
+ /*) printf "%s\n" "$1";;
+ *) printf "%s\n" "$PWD/$1";;
+ esac
+}
+
+listimages() {
+ find -L "$(dirname "$target")" -maxdepth 1 -type f -iregex \
+ '.*\(jpe?g\|bmp\|webp\|png\|gif\)$' -print0 | sort -z
+}
+
+load_dir() {
+ target="$(abspath "$2")"
+ count="$(listimages | grep -a -m 1 -ZznF "$target" | cut -d: -f1)"
+
+ if [ -n "$count" ]; then
+ listimages | xargs -0 "$1" -n "$count" --
+ else
+ shift
+ "$1" -- "$@" # fallback
+ fi
+}
+
+handle_multimedia() {
+ ## Size of the preview if there are multiple options or it has to be
+ ## rendered from vector graphics. If the conversion program allows
+ ## specifying only one dimension while keeping the aspect ratio, the width
+ ## will be used.
+ # local DEFAULT_SIZE="1920x1080"
+
+ mimetype="${1}"
+ case "${mimetype}" in
+ ## SVG
+ # image/svg+xml|image/svg)
+ # convert -- "${FPATH}" "${IMAGE_CACHE_PATH}" && exit 6
+ # exit 1;;
+
+ ## DjVu
+ # image/vnd.djvu)
+ # ddjvu -format=tiff -quality=90 -page=1 -size="${DEFAULT_SIZE}" \
+ # - "${IMAGE_CACHE_PATH}" < "${FPATH}" \
+ # && exit 6 || exit 1;;
+
+ ## Image
+ image/*)
+ if [ "$GUI" -ne 0 ] && is_mac; then
+ open "${FPATH}" >/dev/null 2>&1 &
+ exit 0
+ elif [ "$GUI" -ne 0 ] && which imvr >/dev/null 2>&1; then
+ load_dir imvr "${FPATH}" >/dev/null 2>&1 &
+ exit 0
+ elif [ "$GUI" -ne 0 ] && which sxiv >/dev/null 2>&1; then
+ load_dir sxiv "${FPATH}" >/dev/null 2>&1 &
+ exit 0
+ elif which viu >/dev/null 2>&1; then
+ viu -n "${FPATH}" | eval "$PAGER"
+ exit 0
+ elif which img2txt >/dev/null 2>&1; then
+ img2txt --gamma=0.6 -- "${FPATH}" | eval "$PAGER"
+ exit 0
+ elif which exiftool >/dev/null 2>&1; then
+ exiftool "${FPATH}" | eval "$PAGER"
+ exit 0
+ fi
+ # local orientation
+ # orientation="$( identify -format '%[EXIF:Orientation]\n' -- "${FPATH}" )"
+ ## If orientation data is present and the image actually
+ ## needs rotating ("1" means no rotation)...
+ # if [[ -n "$orientation" && "$orientation" != 1 ]]; then
+ ## ...auto-rotate the image according to the EXIF data.
+ # convert -- "${FPATH}" -auto-orient "${IMAGE_CACHE_PATH}" && exit 6
+ # fi
+
+ ## `w3mimgdisplay` will be called for all images (unless overridden
+ ## as above), but might fail for unsupported types.
+ exit 7;;
+
+ ## PDF
+ application/pdf)
+ handle_pdf
+ exit 1;;
+
+ ## Audio
+ audio/*)
+ handle_audio
+ exit 1;;
+
+ ## Video
+ video/*)
+ handle_video
+ exit 1;;
+
+ # pdftoppm -f 1 -l 1 \
+ # -scale-to-x "${DEFAULT_SIZE%x*}" \
+ # -scale-to-y -1 \
+ # -singlefile \
+ # -jpeg -tiffcompression jpeg \
+ # -- "${FPATH}" "${IMAGE_CACHE_PATH%.*}" \
+ # && exit 6 || exit 1;;
+
+
+ ## ePub, MOBI, FB2 (using Calibre)
+ # application/epub+zip|application/x-mobipocket-ebook|\
+ # application/x-fictionbook+xml)
+ # # ePub (using https://github.com/marianosimone/epub-thumbnailer)
+ # epub-thumbnailer "${FPATH}" "${IMAGE_CACHE_PATH}" \
+ # "${DEFAULT_SIZE%x*}" && exit 6
+ # ebook-meta --get-cover="${IMAGE_CACHE_PATH}" -- "${FPATH}" \
+ # >/dev/null && exit 6
+ # exit 1;;
+
+ ## Font
+ # application/font*|application/*opentype)
+ # preview_png="/tmp/$(basename "${IMAGE_CACHE_PATH%.*}").png"
+ # if fontimage -o "${preview_png}" \
+ # --pixelsize "120" \
+ # --fontname \
+ # --pixelsize "80" \
+ # --text " ABCDEFGHIJKLMNOPQRSTUVWXYZ " \
+ # --text " abcdefghijklmnopqrstuvwxyz " \
+ # --text " 0123456789.:,;(*!?') ff fl fi ffi ffl " \
+ # --text " The quick brown fox jumps over the lazy dog. " \
+ # "${FPATH}";
+ # then
+ # convert -- "${preview_png}" "${IMAGE_CACHE_PATH}" \
+ # && rm "${preview_png}" \
+ # && exit 6
+ # else
+ # exit 1
+ # fi
+ # ;;
+
+ ## Preview archives using the first image inside.
+ ## (Very useful for comic book collections for example.)
+ # application/zip|application/x-rar|application/x-7z-compressed|\
+ # application/x-xz|application/x-bzip2|application/x-gzip|application/x-tar)
+ # local fn=""; local fe=""
+ # local zip=""; local rar=""; local tar=""; local bsd=""
+ # case "${mimetype}" in
+ # application/zip) zip=1 ;;
+ # application/x-rar) rar=1 ;;
+ # application/x-7z-compressed) ;;
+ # *) tar=1 ;;
+ # esac
+ # { [ "$tar" ] && fn=$(tar --list --file "${FPATH}"); } || \
+ # { fn=$(bsdtar --list --file "${FPATH}") && bsd=1 && tar=""; } || \
+ # { [ "$rar" ] && fn=$(unrar lb -p- -- "${FPATH}"); } || \
+ # { [ "$zip" ] && fn=$(zipinfo -1 -- "${FPATH}"); } || return
+ #
+ # fn=$(echo "$fn" | python -c "import sys; import mimetypes as m; \
+ # [ print(l, end='') for l in sys.stdin if \
+ # (m.guess_type(l[:-1])[0] or '').startswith('image/') ]" |\
+ # sort -V | head -n 1)
+ # [ "$fn" = "" ] && return
+ # [ "$bsd" ] && fn=$(printf '%b' "$fn")
+ #
+ # [ "$tar" ] && tar --extract --to-stdout \
+ # --file "${FPATH}" -- "$fn" > "${IMAGE_CACHE_PATH}" && exit 6
+ # fe=$(echo -n "$fn" | sed 's/[][*?\]/\\\0/g')
+ # [ "$bsd" ] && bsdtar --extract --to-stdout \
+ # --file "${FPATH}" -- "$fe" > "${IMAGE_CACHE_PATH}" && exit 6
+ # [ "$bsd" ] || [ "$tar" ] && rm -- "${IMAGE_CACHE_PATH}"
+ # [ "$rar" ] && unrar p -p- -inul -- "${FPATH}" "$fn" > \
+ # "${IMAGE_CACHE_PATH}" && exit 6
+ # [ "$zip" ] && unzip -pP "" -- "${FPATH}" "$fe" > \
+ # "${IMAGE_CACHE_PATH}" && exit 6
+ # [ "$rar" ] || [ "$zip" ] && rm -- "${IMAGE_CACHE_PATH}"
+ # ;;
+ esac
+}
+
+handle_mime() {
+ mimetype="${1}"
+ case "${mimetype}" in
+ ## Manpages
+ text/troff)
+ man -l "${FPATH}"
+ exit 0;;
+
+ ## Text
+ text/* | */xml)
+ "$EDITOR" "${FPATH}"
+ exit 0;;
+ ## Syntax highlight
+ # if [[ "$( stat --printf='%s' -- "${FPATH}" )" -gt "${HIGHLIGHT_SIZE_MAX}" ]]; then
+ # exit 2
+ # fi
+ # if [[ "$( tput colors )" -ge 256 ]]; then
+ # local pygmentize_format='terminal256'
+ # local highlight_format='xterm256'
+ # else
+ # local pygmentize_format='terminal'
+ # local highlight_format='ansi'
+ # fi
+ # env HIGHLIGHT_OPTIONS="${HIGHLIGHT_OPTIONS}" highlight \
+ # --out-format="${highlight_format}" \
+ # --force -- "${FPATH}" && exit 5
+ # pygmentize -f "${pygmentize_format}" -O "style=${PYGMENTIZE_STYLE}"\
+ # -- "${FPATH}" && exit 5
+ # exit 2;;
+
+ ## DjVu
+ image/vnd.djvu)
+ if which djvutxt >/dev/null 2>&1; then
+ ## Preview as text conversion (requires djvulibre)
+ djvutxt "${FPATH}" | eval "$PAGER"
+ exit 0
+ elif which exiftool >/dev/null 2>&1; then
+ exiftool "${FPATH}" | eval "$PAGER"
+ exit 0
+ fi
+ exit 1;;
+ esac
+}
+
+handle_fallback() {
+ if [ "$GUI" -ne 0 ] && which xdg-open >/dev/null 2>&1; then
+ xdg-open "${FPATH}" >/dev/null 2>&1 &
+ exit 0
+ elif [ "$GUI" -ne 0 ] && which open >/dev/null 2>&1; then
+ open "${FPATH}" >/dev/null 2>&1 &
+ exit 0
+ fi
+
+ echo '----- File details -----' && file --dereference --brief -- "${FPATH}"
+ exit 1
+}
+
+handle_blocked() {
+ case "${MIMETYPE}" in
+ application/x-sharedlib)
+ exit 0;;
+
+ application/x-shared-library-la)
+ exit 0;;
+
+ application/x-executable)
+ exit 0;;
+
+ application/x-shellscript)
+ exit 0;;
+
+ application/octet-stream)
+ exit 0;;
+ esac
+}
+
+MIMETYPE="$( file --dereference --brief --mime-type -- "${FPATH}" )"
+handle_extension
+handle_multimedia "${MIMETYPE}"
+handle_mime "${MIMETYPE}"
+handle_blocked "${MIMETYPE}"
+handle_fallback
+
+exit 1
diff --git a/nnn/.config/nnn/plugins/oldbigfile b/nnn/.config/nnn/plugins/oldbigfile
new file mode 100755
index 0000000..0a21527
--- /dev/null
+++ b/nnn/.config/nnn/plugins/oldbigfile
@@ -0,0 +1,16 @@
+#!/usr/bin/env sh
+
+# Description: List files bigger than input size by ascending access date.
+#
+# Dependencies: find sort
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+printf "Min file size (MB): "
+read -r size
+
+find . -size +"$size"M -type f -printf '%A+ %s %p\n' | sort
+
+echo "Press any key to exit"
+read -r _
diff --git a/nnn/.config/nnn/plugins/organize b/nnn/.config/nnn/plugins/organize
new file mode 100755
index 0000000..3fb34c1
--- /dev/null
+++ b/nnn/.config/nnn/plugins/organize
@@ -0,0 +1,53 @@
+#!/usr/bin/env sh
+
+# Description: Organize files in directories by category
+#
+# Shell: POSIX compliant
+# Author: th3lusive
+
+organize() {
+ case "$(file -biL "$1")" in
+ *video*)
+ [ ! -d "Videos" ] && mkdir "Videos"
+ mv "$1" "Videos/$1"
+ printf "Moved %s to Videos\n" "$1" ;;
+
+ *audio*) [ ! -d "Audio" ] && mkdir "Audio"
+ mv "$1" "Audio/$1"
+ printf "Moved %s to Audio\n" "$1" ;;
+
+ *image*)
+ [ ! -d "Images" ] && mkdir "Images"
+ mv "$1" "Images/$1"
+ printf "Moved %s to Images\n" "$1" ;;
+
+ *pdf*|*document*|*epub*|*djvu*|*cb*)
+ [ ! -d "Documents" ] && mkdir "Documents"
+ mv "$1" "Documents/$1"
+ printf "Moved %s to Documents\n" "$1" ;;
+
+ *text*)
+ [ ! -d "Plaintext" ] && mkdir "Plaintext"
+ 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"
+ printf "Moved %s to Archives\n" "$1" ;;
+
+ *binary*)
+ [ ! -d "Binaries" ] && mkdir "Binaries"
+ mv "$1" "Binaries/$1"
+ printf "Moved %s to Binaries\n" "$1" ;;
+ esac
+}
+
+main() {
+ for file in *
+ do
+ [ -f "$file" ] && organize "$file"
+ done
+}
+
+main "$@"
diff --git a/nnn/.config/nnn/plugins/pdfread b/nnn/.config/nnn/plugins/pdfread
new file mode 100755
index 0000000..4f47992
--- /dev/null
+++ b/nnn/.config/nnn/plugins/pdfread
@@ -0,0 +1,30 @@
+#!/usr/bin/env sh
+
+# Description: Read a text or PDF file in British English
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+if ! [ -z "$1" ]; then
+ tmpf="$(basename "$1")"
+ tmpf="${TMPDIR:-/tmp}"/"${tmpf%.*}"
+
+ if [ "$(head -c 4 "$1")" = "%PDF" ]; then
+ # Convert using pdftotext
+ pdftotext -nopgbrk -layout "$1" - | sed 's/\xe2\x80\x8b//g' > "$tmpf".txt
+
+ pico2wave -w "$tmpf".wav -l en-GB "$(tr '\n' ' ' < "$tmpf".txt)"
+
+ rm "$tmpf".txt
+ else
+ pico2wave -w "$tmpf".wav -l en-GB "$(tr '\n' ' ' < "$1")"
+ fi
+
+ # to jump around and note the time
+ mpv "$tmpf".wav
+
+ # flat read but better quality
+ # play -qV0 "$tmpf".wav treble 2 gain -l 2
+
+ rm "$tmpf".wav
+fi
diff --git a/nnn/.config/nnn/plugins/pdfview b/nnn/.config/nnn/plugins/pdfview
new file mode 100755
index 0000000..2b953b5
--- /dev/null
+++ b/nnn/.config/nnn/plugins/pdfview
@@ -0,0 +1,24 @@
+#!/usr/bin/env sh
+
+# Description: View a PDF file in pager
+#
+# Notes:
+# - $PAGER must be 'less -R' or 'most'
+# - To use mutool, uncomment the relevant lines and comment the pdftotext line
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+if ! [ -z "$1" ]; then
+ if [ "$(head -c 4 "$1")" = "%PDF" ]; then
+ # Convert using pdftotext
+ pdftotext -nopgbrk -layout "$1" - | sed 's/\xe2\x80\x8b//g' | $PAGER
+
+ # Convert using mutool
+ # file=`basename "$1"`
+ # txt=/tmp/"$file".txt
+ # mutool convert -o "$txt" "$1"
+ # eval $PAGER $txt
+ # rm "$txt"
+ fi
+fi
diff --git a/nnn/.config/nnn/plugins/preview-tabbed b/nnn/.config/nnn/plugins/preview-tabbed
new file mode 100755
index 0000000..98a4be8
--- /dev/null
+++ b/nnn/.config/nnn/plugins/preview-tabbed
@@ -0,0 +1,211 @@
+#!/usr/bin/env bash
+
+# Description: tabbed/xembed based file previewer
+#
+# Note: This plugin needs a "NNN_FIFO" to work. See man.
+#
+# Dependencies:
+# - tabbed (https://tools.suckless.org/tabbed): xembed host
+# - xterm (or urxvt or st) : xembed client for text-based preview
+# - mpv (https://mpv.io): xembed client for video/audio
+# - sxiv (https://github.com/muennich/sxiv): xembed client for images
+# - zathura (https://pwmt.org/projects/zathura): xembed client for PDF documents
+# - nnn's nuke plugin for text preview and fallback (should be in plugins directory)
+# nuke is a fallback for 'mpv', 'sxiv', and 'zathura', but it has has its own
+# dependencies, see the script itself
+# - vim (or any editor/pager really)
+# - file
+# - mktemp
+# - xdotool (optional, to keep main window focused)
+#
+# How to use:
+# First, install the dependencies. Then you need to set a NNN_FIFO path
+# and set a key for the plugin, then start `nnn`:
+#
+# $ NNN_FIFO=/tmp/nnn.fifo nnn
+#
+# Then in `nnn`, launch the `preview-tabbed` plugin.
+#
+# If you provide the same NNN_FIFO to all nnn instances, there will be a
+# single common preview window. I you provide different FIFO path, they
+# will be independent.
+#
+# How it works:
+# We use `tabbed` [1] as a xembed [2] host, to have a single window
+# owning each previewer window. So each previewer must be a xembed client.
+# For text previewers, this is not an issue, as there are a lot of
+# xembed-able terminal emulator (we default to `xterm`, but examples are
+# provided for `urxvt` and `st`). For graphic preview this can be trickier,
+# but a few popular viewers are xembed-able, we use:
+# - `mpv`: multimedia player, for video/audio preview
+# - `sxiv`: image viewer
+# - `zathura`: PDF viewer
+# - but we allways fallback to `nuke` plugin
+#
+# [1]: http://tools.suckless.org/tabbed/
+# [2]: https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html
+#
+# Shell: bash (job control is weakly specified in POSIX)
+# Author: Léo Villeveygoux
+
+
+XDOTOOL_TIMEOUT=2
+PAGER=${PAGER:-"vim -R"}
+NUKE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins/nuke"
+
+
+if which xterm >/dev/null 2>&1 ; then
+ TERMINAL="xterm -into"
+elif which urxvt >/dev/null 2>&1 ; then
+ TERMINAL="urxvt -embed"
+elif which st >/dev/null 2>&1 ; then
+ TERMINAL="st -w"
+else
+ echo "No xembed term found" >&2
+fi
+
+
+term_nuke () {
+ # $1 -> $XID, $2 -> $FILE
+ $TERMINAL "$1" -e "$NUKE" "$2" &
+}
+
+start_tabbed () {
+ FIFO="$(mktemp -u)"
+ mkfifo "$FIFO"
+
+ tabbed > "$FIFO" &
+
+ jobs # Get rid of the "Completed" entries
+
+ TABBEDPID="$(jobs -p %%)"
+
+ if [ -z "$TABBEDPID" ] ; then
+ echo "Can't start tabbed"
+ exit 1
+ fi
+
+ read -r XID < "$FIFO"
+
+ rm "$FIFO"
+}
+
+get_viewer_pid () {
+ VIEWERPID="$(jobs -p %%)"
+}
+
+kill_viewer () {
+ if [ -n "$VIEWERPID" ] && jobs -p | grep "$VIEWERPID" ; then
+ kill "$VIEWERPID"
+ fi
+}
+
+sigint_kill () {
+ kill_viewer
+ kill "$TABBEDPID"
+ exit 0
+}
+
+previewer_loop () {
+ unset -v NNN_FIFO
+ # mute from now
+ exec >/dev/null 2>&1
+
+ MAINWINDOW="$(xdotool getactivewindow)"
+
+ start_tabbed
+ trap sigint_kill SIGINT
+
+ xdotool windowactivate "$MAINWINDOW"
+
+ # Bruteforce focus stealing prevention method,
+ # works well in floating window managers like XFCE
+ # but make interaction with the preview window harder
+ # (uncomment to use):
+ #xdotool behave "$XID" focus windowactivate "$MAINWINDOW" &
+
+ while read -r FILE ; do
+
+ jobs # Get rid of the "Completed" entries
+
+ if ! jobs | grep tabbed ; then
+ break
+ fi
+
+ if [ ! -e "$FILE" ] ; then
+ continue
+ fi
+
+ kill_viewer
+
+ MIME="$(file -b --mime-type "$FILE")"
+
+ case "$MIME" in
+ video/*)
+ if which mpv >/dev/null 2>&1 ; then
+ mpv --force-window=immediate --loop-file --wid="$XID" "$FILE" &
+ else
+ term_nuke "$XID" "$FILE"
+ fi
+ ;;
+ audio/*)
+ if which mpv >/dev/null 2>&1 ; then
+ mpv --force-window=immediate --loop-file --wid="$XID" "$FILE" &
+ else
+ term_nuke "$XID" "$FILE"
+ fi
+ ;;
+ image/*)
+ if which sxiv >/dev/null 2>&1 ; then
+ sxiv -e "$XID" "$FILE" &
+ else
+ term_nuke "$XID" "$FILE"
+ fi
+ ;;
+ application/pdf)
+ if which zathura >/dev/null 2>&1 ; then
+ zathura -e "$XID" "$FILE" &
+ else
+ term_nuke "$XID" "$FILE"
+ fi
+ ;;
+ inode/directory)
+ $TERMINAL "$XID" -e nnn "$FILE" &
+ ;;
+ text/*)
+ if [ -x "$NUKE" ] ; then
+ term_nuke "$XID" "$FILE"
+ else
+ # shellcheck disable=SC2086
+ $TERMINAL "$XID" -e $PAGER "$FILE" &
+ fi
+ ;;
+ *)
+ if [ -x "$NUKE" ] ; then
+ term_nuke "$XID" "$FILE"
+ else
+ $TERMINAL "$XID" -e sh -c "file '$FILE' | $PAGER -" &
+ fi
+ ;;
+ esac
+ get_viewer_pid
+
+ # following lines are not needed with the bruteforce xdotool method
+ ACTIVE_XID="$(xdotool getactivewindow)"
+ if [ $((ACTIVE_XID == XID)) -ne 0 ] ; then
+ xdotool windowactivate "$MAINWINDOW"
+ else
+ timeout "$XDOTOOL_TIMEOUT" xdotool behave "$XID" focus windowactivate "$MAINWINDOW" &
+ fi
+ done
+ kill "$TABBEDPID"
+ kill_viewer
+}
+
+if [ ! -r "$NNN_FIFO" ] ; then
+ echo "Can't read \$NNN_FIFO ('$NNN_FIFO')"
+ exit 1
+fi
+
+previewer_loop < "$NNN_FIFO" &
+disown
diff --git a/nnn/.config/nnn/plugins/preview-tui b/nnn/.config/nnn/plugins/preview-tui
new file mode 100755
index 0000000..255c35d
--- /dev/null
+++ b/nnn/.config/nnn/plugins/preview-tui
@@ -0,0 +1,231 @@
+#!/usr/bin/env sh
+
+# Description: Terminal based file previewer
+#
+# Note: This plugin needs a "NNN_FIFO" to work. See man.
+#
+# Dependencies:
+# - Supports 3 independent methods to preview with:
+# - tmux (>=3.0), or
+# - kitty with allow_remote_control on, or
+# - $TERMINAL set to a terminal (it's xterm by default).
+# - less or $PAGER
+# - tree or exa or ls
+# - mediainfo or file
+# - mktemp
+# - unzip
+# - tar
+# - man
+# - optional: bat for code syntax highlighting
+# - optional: kitty terminal or catimg for images
+# - optional: scope.sh file viewer from ranger.
+# To use:
+# 1. drop scope.sh executable in $PATH
+# 2. set/export $USE_SCOPE as 1
+# - optional: pistol file viewer (https://github.com/doronbehar/pistol).
+# To use:
+# 1. install pistol
+# 2. set/export $USE_PISTOL as 1
+#
+# Usage:
+# You need to set a NNN_FIFO path and a key for the plugin with NNN_PLUG,
+# then start `nnn`:
+#
+# $ nnn -a
+#
+# or
+#
+# $ NNN_FIFO=/tmp/nnn.fifo nnn
+#
+# Then in `nnn`, launch the `preview-tui` plugin.
+#
+# If you provide the same NNN_FIFO to all nnn instances, there will be a
+# single common preview window. If you provide different FIFO path (e.g.
+# with -a), they will be independent.
+#
+# The previews will be shown in a tmux split. If that isn't possible, it
+# will try to use a kitty terminal split. And as a final fallback, a
+# different terminal window will be used ($TERMINAL).
+#
+# Tmux and kitty users can configure $SPLIT to either "h" or "v" to set a
+# 'h'orizontal split or a 'v'ertical split (as in, the line that splits the
+# windows will be horizontal or vertical).
+#
+# Kitty users need `allow_remote_control` set to `yes`. To customize the
+# window split, `enabled_layouts` has to be set to `all` or `splits` (the
+# former is the default value). This terminal is also able to show images
+# without extra dependencies.
+#
+# Shell: POSIX compliant
+# Authors: Todd Yamakawa, Léo Villeveygoux, @Recidiviste, Mario Ortiz Manero
+
+SPLIT="$SPLIT" # you can set a permanent split here
+TERMINAL="$TERMINAL" # same goes for the terminal
+USE_SCOPE="${USE_SCOPE:-0}"
+USE_PISTOL="${USE_PISTOL:-0}"
+PAGER="${PAGER:-less -R}"
+[ "$PAGER" = "most" ] && PAGER="less -R"
+
+if [ -e "${TMUX%%,*}" ] && tmux -V | grep -q '[ -][3456789]\.'; then
+ TERMINAL=tmux
+elif [ -n "$KITTY_WINDOW_ID" ] && kitty @ ls >/dev/null 2>&1; then
+ TERMINAL=kitty
+else
+ TERMINAL="${TERMINAL:-xterm}"
+fi
+
+if [ -z "$SPLIT" ] && [ $(($(tput lines) * 2)) -gt "$(tput cols)" ]; then
+ SPLIT='h'
+elif [ "$SPLIT" != 'h' ]; then
+ SPLIT='v'
+fi
+
+exists() {
+ which "$1" >/dev/null 2>&1
+}
+
+fifo_pager() {
+ cmd="$1"
+ shift
+
+ # We use a FIFO to access $PAGER PID in jobs control
+ tmpfifopath="${TMPDIR:-/tmp}/nnn-preview-tui-fifo.$$"
+ mkfifo "$tmpfifopath" || return
+
+ $PAGER < "$tmpfifopath" &
+
+ (
+ exec > "$tmpfifopath"
+ "$cmd" "$@" &
+ )
+
+ rm "$tmpfifopath"
+}
+
+# Binary file: show file info inside the pager
+print_bin_info() {
+ printf -- "-------- \033[1;31mBinary file\033[0m --------\n"
+ if exists mediainfo; then
+ mediainfo "$1" 2>/dev/null
+ else
+ file -b "$1"
+ fi
+}
+
+preview_file () {
+ kill %- %+ 2>/dev/null && wait %- %+ 2>/dev/null
+ clear
+
+ # Trying to use pistol if it's available.
+ if [ "$USE_PISTOL" -ne 0 ] && exists pistol; then
+ fifo_pager pistol "$1"
+ return
+ fi
+
+ # Trying to use scope.sh if it's available.
+ if [ "$USE_SCOPE" -ne 0 ] && exists scope.sh; then
+ fifo_pager scope.sh "$1" "$cols" "$lines" "$(mktemp -d)" \
+ "True" 2>/dev/null
+ return
+ fi
+
+ # Detecting the exact type of the file: the encoding, mime type, and
+ # extension in lowercase.
+ encoding="$(file -Lb --mime-encoding -- "$1")"
+ mimetype="$(file -Lb --mime-type -- "$1")"
+ ext="${1##*.}"
+ if [ -n "$ext" ]; then
+ ext="$(printf "%s" "${ext}" | tr '[:upper:]' '[:lower:]')"
+ fi
+ lines=$(($(tput lines)-1))
+ cols=$(tput cols)
+
+ # Otherwise, falling back to the defaults.
+ if [ -d "$1" ]; then
+ cd "$1" || return
+ if exists tree; then
+ fifo_pager tree -L 3 -F
+ elif exists exa; then
+ fifo_pager exa -G --colour=always 2>/dev/null
+ else
+ fifo_pager ls --color=always
+ fi
+ elif [ "$encoding" = "binary" ]; then
+ if [ "${mimetype%%/*}" = "image" ] ; then
+ if [ "$TERMINAL" = "kitty" ]; then
+ # Kitty terminal users can use the native image preview method.
+ kitty +kitten icat --silent --transfer-mode=stream --stdin=no \
+ "$1" &
+ elif exists catimg; then
+ catimg "$1"
+ elif exists viu; then
+ viu -t "$1"
+ else
+ fifo_pager print_bin_info "$1"
+ fi
+ elif [ "$mimetype" = "application/zip" ] ; then
+ fifo_pager unzip -l "$1"
+ elif [ "$ext" = "gz" ] || [ "$ext" = "bz2" ] ; then
+ fifo_pager tar -tvf "$1"
+ else
+ fifo_pager print_bin_info "$1"
+ fi
+ elif [ "$mimetype" = "text/troff" ] ; then
+ fifo_pager man -Pcat -l "$1"
+ else
+ if exists bat; then
+ fifo_pager bat --terminal-width="$cols" --paging=never --decorations=always --color=always \
+ "$1" 2>/dev/null
+ else
+ $PAGER "$1" &
+ fi
+ fi
+}
+
+if [ "$PREVIEW_MODE" ] ; then
+ if [ ! -r "$NNN_FIFO" ] ; then
+ echo "No FIFO available! (\$NNN_FIFO='$NNN_FIFO')" >&2
+ read -r
+ exit 1
+ fi
+
+ preview_file "$1"
+
+ # use cat instead of 'exec <' to avoid issues with dash shell
+ # shellcheck disable=SC2002
+ cat "$NNN_FIFO" |\
+ while read -r selection ; do
+ preview_file "$selection"
+ done
+
+ # Restoring the previous layout for kitty users. This will only work for
+ # kitty >= 0.18.0.
+ if [ "$TERMINAL" = "kitty" ]; then
+ kitty @ last-used-layout --no-response >/dev/null 2>&1
+ fi
+
+ exit 0
+fi
+
+if [ "$TERMINAL" = "tmux" ]; then
+ # tmux splits are inverted
+ if [ "$SPLIT" = "v" ]; then SPLIT="h"; else SPLIT="v"; fi
+
+ tmux split-window -e "NNN_FIFO=$NNN_FIFO" -e "PREVIEW_MODE=1" -d"$SPLIT" "$0" "$1"
+elif [ "$TERMINAL" = "kitty" ]; then
+ # Setting the layout for the new window. It will be restored after the
+ # script ends.
+ kitty @ goto-layout splits >/dev/null
+
+ # Trying to use kitty's integrated window management as the split window.
+ # All environmental variables that will be used in the new window must
+ # be explicitly passed.
+ kitty @ launch --no-response --title "nnn preview" --keep-focus \
+ --cwd "$PWD" --env "PATH=$PATH" --env "NNN_FIFO=$NNN_FIFO" \
+ --env "PREVIEW_MODE=1" --env "PAGER=$PAGER" \
+ --env "USE_SCOPE=$USE_SCOPE" --env "SPLIT=$SPLIT" \
+ --env "USE_PISTOL=$USE_PISTOL" \
+ --location "${SPLIT}split" "$0" "$1" >/dev/null
+else
+ PREVIEW_MODE=1 $TERMINAL -e "$0" "$1" &
+fi
diff --git a/nnn/.config/nnn/plugins/pskill b/nnn/.config/nnn/plugins/pskill
new file mode 100755
index 0000000..979492a
--- /dev/null
+++ b/nnn/.config/nnn/plugins/pskill
@@ -0,0 +1,35 @@
+#!/usr/bin/env sh
+
+# Description: Fuzzy list and kill a (zombie) process by name
+#
+# Dependencies: fzf, ps
+#
+# Note: To kill a zombie process enter "zombie"
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+printf "Enter process name ['defunct' for zombies]: "
+read -r psname
+
+# shellcheck disable=SC2009
+if ! [ -z "$psname" ]; then
+ if which sudo >/dev/null 2>&1; then
+ sucmd=sudo
+ elif which doas >/dev/null 2>&1; then
+ sucmd=doas
+ else
+ sucmd=: # noop
+ fi
+
+ if which fzf >/dev/null 2>&1; then
+ fuzzy=fzf
+ else
+ exit 1
+ fi
+
+ cmd="$(ps -ax | grep -iw "$psname" | "$fuzzy" | sed -e 's/^[ \t]*//' | cut -d' ' -f1)"
+ if [ -n "$cmd" ]; then
+ $sucmd kill -9 "$cmd"
+ fi
+fi
diff --git a/nnn/.config/nnn/plugins/renamer b/nnn/.config/nnn/plugins/renamer
new file mode 100755
index 0000000..68b6ef0
--- /dev/null
+++ b/nnn/.config/nnn/plugins/renamer
@@ -0,0 +1,41 @@
+#!/usr/bin/env sh
+
+# Description: Batch rename selection or current directory with qmv
+#
+# Notes:
+# - 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.
+# Vidir don't show directories nor hidden files.
+#
+# Shell: POSIX compliant
+# Author: José Neder
+
+selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+
+if which qmv >/dev/null 2>&1; then
+ batchrenamesel="qmv -fdo -da"
+ batchrename="qmv -fdo -a"
+elif which vidir >/dev/null 2>&1; then
+ batchrenamesel="vidir"
+ batchrename="vidir"
+else
+ printf "there is not batchrename program installed."
+ exit
+fi
+
+if [ -s "$selection" ]; then
+ printf "rename selection? "
+ read -r resp
+fi
+
+if [ "$resp" = "y" ]; then
+ # -o flag is necessary for interactive editors
+ xargs -o -0 $batchrenamesel < "$selection"
+elif [ ! "$(LC_ALL=C ls -a)" = ".
+.." ]; then
+ # On older systems that don't have ls -A
+ $batchrename
+fi
+
diff --git a/nnn/.config/nnn/plugins/ringtone b/nnn/.config/nnn/plugins/ringtone
new file mode 100755
index 0000000..c18f255
--- /dev/null
+++ b/nnn/.config/nnn/plugins/ringtone
@@ -0,0 +1,36 @@
+#!/usr/bin/env sh
+
+# Description: Create an mp3 ringtone out of an audio file in any format
+# Needs user to provide start and end where to cut the file
+# Input file audio.ext results in audio_ringtone.mp3
+#
+# Tip: To convert a complete media file, set start as 0 and
+# the runtime of the file as end.
+#
+# Dependencies: date, ffmpeg
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+if [ -n "$1" ]; then
+ printf "start (hh:mm:ss): "
+ read -r start
+ st=$(date -d "$start" +%s) || exit 1
+
+ printf "end (hh:mm:ss): "
+ read -r end
+ et=$(date -d "$end" +%s) || exit 1
+
+ if [ "$st" -ge "$et" ]; then
+ printf "error: start >= end "
+ read -r _
+ exit 1
+ fi
+
+ interval=$(( et - st ))
+
+ outfile=$(basename "$1")
+ outfile="${outfile%.*}"_ringtone.mp3
+
+ ffmpeg -i "$1" -ss "$start" -t "$interval" -vn -sn -acodec libmp3lame -q:a 2 "$outfile"
+fi
diff --git a/nnn/.config/nnn/plugins/rsynccp b/nnn/.config/nnn/plugins/rsynccp
new file mode 100755
index 0000000..5cfa66f
--- /dev/null
+++ b/nnn/.config/nnn/plugins/rsynccp
@@ -0,0 +1,26 @@
+#!/usr/bin/env sh
+
+# Description: Simple script to give copy-paste a progress percentage
+# by utilizing rsync.
+#
+# LIMITATION: this won't work when pasting to MTP device.
+#
+# Dependencies: rsync
+#
+# Shell: POSIX compliant
+# Author: Benawi Adha
+
+sel=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+
+# Choose one of these two schemes by commenting
+
+# more verbose
+xargs -0 -a "$sel" -I % rsync -ah --progress % "$PWD"
+
+# less verbose
+# xargs -0 -a "$sel" -I % rsync -ah --info=progress2 % "$PWD"
+
+# Clear selection
+if [ -p "$NNN_PIPE" ]; then
+ printf "-" > "$NNN_PIPE"
+fi
diff --git a/nnn/.config/nnn/plugins/splitjoin b/nnn/.config/nnn/plugins/splitjoin
new file mode 100755
index 0000000..545eadb
--- /dev/null
+++ b/nnn/.config/nnn/plugins/splitjoin
@@ -0,0 +1,47 @@
+#!/usr/bin/env sh
+
+# Description: Splits the file passed as argument or joins selection
+#
+# Note: Adds numeric suffix to split files
+# Adds '.out suffix to the first file to be joined and saves as output file for join
+#
+# Shell: POSIX compliant
+# Authors: Arun Prakash Jana, ath3
+
+selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+resp=s
+
+if [ -s "$selection" ]; then
+ printf "press 's' (split current file) or 'j' (join selection): "
+ read -r resp
+fi
+
+if [ "$resp" = "j" ]; then
+ if [ -s "$selection" ]; then
+ arr=$(tr '\0' '\n' < "$selection")
+ if [ "$(echo "$arr" | wc -l)" -lt 2 ]; then
+ echo "joining needs at least 2 files"
+ exit
+ fi
+ for entry in $arr
+ do
+ if [ -d "$entry" ]; then
+ echo "cant join directories"
+ exit
+ fi
+ done
+
+ file="$(basename "$(echo "$arr" | sed -n '1p' | sed -e 's/[0-9][0-9]$//')")"
+ sort -z < "$selection" | xargs -0 -I{} cat {} > "${file}.out"
+ fi
+elif [ "$resp" = "s" ]; then
+ if [ -n "$1" ] && [ -f "$1" ]; then
+ # a single file is passed
+ printf "split size in MB: "
+ read -r size
+
+ if [ -n "$size" ]; then
+ split -d -b "$size"M "$1" "$1"
+ fi
+ fi
+fi
diff --git a/nnn/.config/nnn/plugins/suedit b/nnn/.config/nnn/plugins/suedit
new file mode 100755
index 0000000..7598525
--- /dev/null
+++ b/nnn/.config/nnn/plugins/suedit
@@ -0,0 +1,21 @@
+#!/usr/bin/env sh
+
+# Description: Edit file as superuser
+#
+# Shell: POSIX compliant
+# Author: Anna Arad
+
+EDITOR="${EDITOR:-vim}"
+
+is_cmd_exists () {
+ which "$1" > /dev/null 2>&1
+ echo $?
+}
+
+if [ "$(is_cmd_exists sudo)" -eq "0" ]; then
+ sudo "$EDITOR" "$1"
+elif [ "$(is_cmd_exists sudoedit)" -eq "0" ]; then
+ sudoedit "$1"
+elif [ "$(is_cmd_exists doas)" -eq "0" ]; then
+ doas "$EDITOR" "$1"
+fi
diff --git a/nnn/.config/nnn/plugins/toggleex b/nnn/.config/nnn/plugins/toggleex
new file mode 100755
index 0000000..e42d65a
--- /dev/null
+++ b/nnn/.config/nnn/plugins/toggleex
@@ -0,0 +1,21 @@
+#!/usr/bin/env sh
+
+# Description: Toggles executable mode for selection
+#
+# Dependencies: chmod
+#
+# Note: Works _only_ with selection (nnn can toggle the mode for the hovered file)
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+
+if [ -s "$selection" ]; then
+ xargs -0 -I {} sh -c 'if [ -x "{}" ] ; then chmod -x "{}" ; else chmod +x "{}" ; fi' < "$selection"
+
+ # Clear selection
+ if [ -p "$NNN_PIPE" ]; then
+ printf "-" > "$NNN_PIPE"
+ fi
+fi
diff --git a/nnn/.config/nnn/plugins/treeview b/nnn/.config/nnn/plugins/treeview
new file mode 100755
index 0000000..c8f8784
--- /dev/null
+++ b/nnn/.config/nnn/plugins/treeview
@@ -0,0 +1,8 @@
+#!/usr/bin/env sh
+
+# Description: Show tree output in $EDITOR
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+tree -ps | $EDITOR -
diff --git a/nnn/.config/nnn/plugins/uidgid b/nnn/.config/nnn/plugins/uidgid
new file mode 100755
index 0000000..d72f1e0
--- /dev/null
+++ b/nnn/.config/nnn/plugins/uidgid
@@ -0,0 +1,13 @@
+#!/usr/bin/env sh
+
+# Description: list uid and gid of files
+#
+# Note: To list UID and GID of all users in a pretty format, run:
+#
+# cut -d':' -f1,3,4,5 < /etc/passwd | column -ts ":"
+#
+# Shell: POSIX compliant
+# Authors: Arun Prakash Jana, superDuperCyberTechno
+
+# shellcheck disable=SC2012
+ls -lah --group-directories-first | less
diff --git a/nnn/.config/nnn/plugins/umounttree b/nnn/.config/nnn/plugins/umounttree
new file mode 100755
index 0000000..011d74d
--- /dev/null
+++ b/nnn/.config/nnn/plugins/umounttree
@@ -0,0 +1,52 @@
+#!/usr/bin/env sh
+
+# Description: Autodetects a nnn remote mountpoint (mounted with `c`)
+# from any of its subfolders and allows unmounting it
+# from the subdir without navigating to the mountppoint
+# or entering the remote name. Also works when hovering
+# the mountpoint directly like vanilla `u`.
+#
+# Dependencies: fusermount
+#
+# Shell: POSIX compliant
+# Authors: Kabouik & 0xACE
+#
+# TODO:
+# - Avoid lazy unmount by forcing nnn context to leave the subfolder before fusermount.
+# Tried `printf "%s" "0c$m" > "$NNN_PIPE"` but it breaks the nnn interface, see #854.
+
+err=0
+m=$HOME/.config/nnn/mounts
+if [ "$PWD" = "$m" ]; then
+ # Allow running the script on hovered directory if user is in ~/.config/nnn/mounts
+ d="$1"
+else
+ d=$(dirname "$(readlink -f "$1")" | grep -oP "^$m\K.*" | cut -d"/" -f2)
+fi
+
+# Test if user is within $m or a subdir, abort if not
+if [ "$d" = "" ]; then
+ clear && printf "You are not in a remote folder mounted with nnn. Press return to continue. " && read -r _
+else
+ # Test if $m/$d is a mountpoint and try unmounting if it is
+ mountpoint -q -- "$m/$d"
+ if [ "$?" -eq "1" ]; then
+ clear && printf "Parent '%s' is not a mountpoint. Press return to continue. " "$d" && read -r _
+ else
+ cd "$m" && fusermount -uq "$m/$d" || err=1
+ if [ "$err" -eq "0" ]; then
+ rmdir "$m/$d" && clear && printf "Parent '%s' unmounted." "$d"
+ else
+ clear && printf "Failed to unmount. Try lazy unmount? [Yy/Nn] " && read -r
+ fi
+ fi
+fi
+
+# If unmount fails, offer lazy unmount
+if [ "$REPLY" = "y" ] || [ "$REPLY" = "Y" ]; then
+ err=0
+ cd "$m" && fusermount -uqz "$m/$d" || err=1
+ if [ "$err" -eq "0" ]; then
+ rmdir "$m/$d" && clear && printf "Parent '%s' unmounted with lazy unmount. " "$d"
+ fi
+fi
diff --git a/nnn/.config/nnn/plugins/upgrade b/nnn/.config/nnn/plugins/upgrade
new file mode 100755
index 0000000..b2170f7
--- /dev/null
+++ b/nnn/.config/nnn/plugins/upgrade
@@ -0,0 +1,25 @@
+#!/usr/bin/env sh
+
+# Description: Check and update to latest version of nnn manually on Debian 9 Stretch
+#
+# Note: This script installs a package, should be issued with admin privilege
+#
+# Shell: POSIX-compliant
+# Author: Arun Prakash Jana
+
+cur="$(nnn -v)"
+new="$(curl -s "https://github.com/jarun/nnn/releases/latest" | grep -Eo "[0-9]+\.[0-9]+")"
+
+if [ "$cur" = "$new" ]; then
+ echo 'Already at latest version'
+ exit 0
+fi
+
+# get the package
+curl -Ls -O "https://github.com/jarun/nnn/releases/download/v$new/nnn_$new-1_debian9.amd64.deb"
+
+# install it
+sudo dpkg -i nnn_"$new"-1_debian9.amd64.deb
+
+# remove the file
+rm -rf nnn_"$new"-1_debian9.amd64.deb
diff --git a/nnn/.config/nnn/plugins/upload b/nnn/.config/nnn/plugins/upload
new file mode 100755
index 0000000..196e8f7
--- /dev/null
+++ b/nnn/.config/nnn/plugins/upload
@@ -0,0 +1,28 @@
+#!/usr/bin/env sh
+
+# Description: Upload to Firefox Send if ffsend is found, else
+# Paste contents of a text a file http://ix.io
+# Upload a binary file to file.io
+# Dependencies: ffsend (https://github.com/timvisee/ffsend), curl, jq, tr
+# Note: Binary file set to expire after a week
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+if ! [ -z "$1" ] && [ -s "$1" ]; then
+ if which ffsend >/dev/null 2>&1; then
+ ffsend -iq 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
+else
+ printf "empty file!"
+fi
+
+read -r _
diff --git a/nnn/.config/nnn/plugins/vidthumb b/nnn/.config/nnn/plugins/vidthumb
new file mode 100755
index 0000000..248abd7
--- /dev/null
+++ b/nnn/.config/nnn/plugins/vidthumb
@@ -0,0 +1,27 @@
+#!/usr/bin/env sh
+
+# Description: Generate video thumbnails and view them
+#
+# Dependencies:
+# ffmpegthumbnailer: https://github.com/dirkvdb/ffmpegthumbnailer
+# lsix: https://github.com/hackerb9/lsix
+#
+# Shell: POSIX compliant
+# Author: Arun Prakash Jana
+
+mkdir .nthumbs > /dev/null 2>&1
+
+for file in *; do
+ if [ -f "$file" ]; then
+ ffmpegthumbnailer -i "$file" -o .nthumbs/"${file%%.*}".jpg 2> /dev/null
+ fi
+done
+
+# render thumbnails in lsix
+lsix .nthumbs/*
+
+# remove the thumbnails
+rm -rf .nthumbs
+
+printf "Press any key to exit..."
+read -r _
diff --git a/nnn/.config/nnn/plugins/wall b/nnn/.config/nnn/plugins/wall
new file mode 100755
index 0000000..0fc6de7
--- /dev/null
+++ b/nnn/.config/nnn/plugins/wall
@@ -0,0 +1,30 @@
+#!/usr/bin/env sh
+
+# Description: Set the selected image as wallpaper using nitrogen or pywal.
+# Usage: Hover on an image and run the script to set it as wallpaper.
+#
+# Shell: POSIX Compliant
+# Author: juacq97
+
+cmd_exists () {
+ which "$1" > /dev/null 2>&1
+ echo $?
+}
+
+if ! [ -z "$1" ]; then
+ if [ "$(mimetype --output-format %m "$1" | awk -F '/' '{print $1}')" = "image" ]; then
+ if [ "$(cmd_exists nitrogen)" -eq "0" ]; then
+ nitrogen --set-zoom-fill --save "$1"
+ elif [ "$(cmd_exists wal)" -eq "0" ]; then
+ wal -i "$1"
+ else
+ printf "nitrogen ir pywal missing"
+ read -r _
+ fi
+
+ # If you want a system notification, uncomment the next 3 lines.
+ # notify-send -a "nnn" "Wallpaper changed!"
+ # else
+ # notify-send -a "nnn" "No image selected"
+ fi
+fi
diff --git a/nnn/.config/nnn/plugins/x2sel b/nnn/.config/nnn/plugins/x2sel
new file mode 100755
index 0000000..0a0fcd4
--- /dev/null
+++ b/nnn/.config/nnn/plugins/x2sel
@@ -0,0 +1,62 @@
+#!/usr/bin/env sh
+
+# Description: Copy system clipboard newline-separated file list to selection
+# Dependencies:
+# - tr
+# - xclip/xsel (Linux)
+# - pbpaste (macOS)
+# - termux-clipboard-get (Termux)
+# - powershell (WSL)
+# - cygwim's /dev/clipboard (Cygwin)
+# - wl-paste (Wayland)
+# - clipboard (Haiku)
+#
+# Limitation: breaks if a filename has newline in it
+#
+# Shell: POSIX compliant
+# Author: Léo Villeveygoux, after Arun Prakash Jana's .cbcp
+
+IFS="$(printf '%b_' '\n')"; IFS="${IFS%_}" # protect trailing \n
+
+selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
+
+getclip () {
+
+ if which xsel >/dev/null 2>&1; then
+ # Linux
+ xsel -bo
+ elif which xclip >/dev/null 2>&1; then
+ # Linux
+ xclip -sel clip -o
+ elif which pbpaste >/dev/null 2>&1; then
+ # macOS
+ pbpaste
+ elif which termux-clipboard-get >/dev/null 2>&1; then
+ # Termux
+ termux-clipboard-get
+ elif which powershell.exe >/dev/null 2>&1; then
+ # WSL
+ powershell.exe Get-Clipboard
+ elif [ -r /dev/clipboard ] ; then
+ # Cygwin
+ cat /dev/clipboard
+ elif which wl-paste >/dev/null 2>&1; then
+ # Wayland
+ wl-paste
+ elif which clipboard >/dev/null 2>&1; then
+ # Haiku
+ clipboard --print
+ fi
+
+}
+
+CLIPBOARD=$(getclip)
+
+# Check if clipboard actually contains a file list
+for file in $CLIPBOARD ; do
+ if [ ! -e "$file" ] ; then
+ exit 1;
+ fi
+done
+
+printf "%s" "$CLIPBOARD" | tr '\n' '\0' > "$selection"