From 7f5dbd11e370d3c25bc1bf58618ee2804f9de1c2 Mon Sep 17 00:00:00 2001 From: Arun Prakash Jana Date: Sat, 27 Mar 2021 17:07:58 +0530 Subject: [PATCH] Fix #917: enhance plugin framework to clear sel on request With this enhancement, plugins which operate on selection can explicitly request the program to clear the selection. --- plugins/README.md | 119 ++++++++++++++++++++++-------------------- plugins/chksum | 5 ++ plugins/cleanfilename | 7 ++- plugins/diffs | 5 ++ plugins/gpgd | 5 ++ plugins/gpge | 5 ++ plugins/kdeconnect | 7 ++- plugins/mocplay | 5 ++ plugins/organize | 9 ++++ plugins/renamer | 5 ++ plugins/rsynccp | 5 ++ plugins/splitjoin | 5 ++ plugins/togglex | 13 ++--- src/nnn.c | 13 +++-- 14 files changed, 136 insertions(+), 72 deletions(-) diff --git a/plugins/README.md b/plugins/README.md index 1a0ddcf5..77feb384 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -14,64 +14,68 @@ Plugins extend the capabilities of `nnn`. They are _executable_ scripts (or bina ## List of plugins -| Plugin (a-z) | Description | Lang | Dependencies | +| Plugin (a-z) | [Clears selection]1 Description | Lang | Dependencies | | --- | --- | --- | --- | -| [autojump](autojump) | Navigate to dir/path | sh | [jump](https://github.com/gsamokovarov/jump)/autojump/zoxide | -| [bookmarks](bookmarks) | Use named bookmarks managed with symlinks | sh | fzf | -| [boom](boom) | Play random music from dir | sh | [moc](http://moc.daper.net/) | -| [bulknew](bulknew) | Create multiple files/dirs at once | bash | sed, xargs, mktemp | -| [chksum](chksum) | Create and verify checksums | sh | md5sum,
sha256sum | -| [cleanfilename](cleanfilename) | Clean filename to be more shell-friendly | sh | sed | -| [diffs](diffs) | Diff for selection (limited to 2 for directories) | sh | vimdiff, mktemp | -| [dragdrop](dragdrop) | Drag/drop files from/into nnn | sh | [dragon](https://github.com/mwh/dragon) | -| [dups](dups) | List non-empty duplicate files in current dir | bash | find, md5sum,
sort uniq xargs | -| [finder](finder) | Run custom find command and list | sh | - | -| [fzcd](fzcd) | Change to the directory of a fuzzy-selected file/dir | sh | fzf | -| [fzhist](fzhist) | Fuzzy-select a cmd from history, edit in `$EDITOR` and run | sh | fzf, mktemp | -| [fzopen](fzopen) | Fuzzy find a file in dir subtree and edit or open | sh | fzf, xdg-open | -| [fzz](fzz) | Change to any directory in the z database with fzf | sh | fzf, z | -| [getplugs](getplugs) | Update plugins to installed `nnn` version | sh | curl | -| [gpg\*](gpg\*) | Encrypt/decrypt files using GPG | sh | gpg | -| [gutenread](gutenread) | Browse, download, read from Project Gutenberg | sh | curl, unzip, w3m
[epr](https://github.com/wustho/epr) (optional) | -| [hexview](hexview) | View a file in hex in `$PAGER` | sh | [hx](https://github.com/krpors/hx)/xxd | -| [imgresize](imgresize) | Resize images in dir to screen resolution | sh | [imgp](https://github.com/jarun/imgp) | -| [imgthumb](imgthumb) | View thumbnail of an image or dir of images | sh | [lsix](https://github.com/hackerb9/lsix) | -| [imgur](imgur) | Upload an image to imgur (from [imgur-screenshot](https://github.com/jomo/imgur-screenshot)) | bash | - | -| [imgview](imgview) | Browse images, set wallpaper, copy path ([config](https://wiki.archlinux.org/index.php/Sxiv#Assigning_keyboard_shortcuts)), [rename](https://github.com/jarun/nnn/wiki/Basic-use-cases#browse-rename-images)| sh | [imv](https://github.com/eXeC64/imv)/[sxiv](https://github.com/muennich/sxiv)/[viu](https://github.com/atanunq/viu), less| -| [ipinfo](ipinfo) | Fetch external IP address and whois information | sh | curl, whois | -| [kdeconnect](kdeconnect) | Send selected files to an Android device | sh | kdeconnect-cli | -| [launch](launch) | GUI application launcher | sh | fzf | -| [mediainf](mediainf) | Show media information | sh | mediainfo | -| [mimelist](mimelist) | List files by mime in subtree | sh | - | -| [moclyrics](moclyrics) | Show lyrics of the track playing in moc | sh | [ddgr](https://github.com/jarun/ddgr), [moc](http://moc.daper.net/) | -| [mocplay](mocplay) | Append (and/or play) selection/dir/file in moc | sh | [moc](http://moc.daper.net/) | -| [mp3conv](mp3conv) | Extract audio from multimedia as mp3 | sh | ffmpeg | -| [mtpmount](mtpmount) | Toggle mount of MTP device (eg. Android) | sh | gvfs-mtp | -| [nbak](nbak) | Backs up `nnn` config | sh | tar, awk, mktemp | -| [nmount](nmount) | Toggle mount status of a device as normal user | sh | pmount, udisks2 | -| [nuke](nuke) | Sample file opener (CLI-only by default) | sh | _see in-file docs_ | -| [oldbigfile](oldbigfile) | List large files by access time | sh | find, sort | -| [organize](organize) | Auto-organize files in directories by file type | sh | file | -| [pdfread](pdfread) | Read a PDF or text file aloud | sh | pdftotext, mpv,
pico2wave | -| [pdfview](pdfview) | View PDF file in `$PAGER` | sh | pdftotext/
mupdf-tools | -| [picker](picker) | Pick files and list one per line (to pipe) | sh | nnn | -| [preview-tabbed](preview-tabbed) | Tabbed/xembed based file previewer | bash | _see in-file docs_ | -| [preview-tui](preview-tui) | Tmux/kitty/xterm/`$TERMINAL` based file previewer | sh | _see in-file docs_ | -| [preview-tui-ext](preview-tui-ext) | Meant to be an exhaustive version of [preview-tui](preview-tui) | sh | _see in-file docs_ | -| [pskill](pskill) | Fuzzy list by name and kill process or zombie | sh | fzf, ps, sudo/doas | -| [renamer](renamer) | Batch rename selection or files in dir | sh | [qmv](https://www.nongnu.org/renameutils/)/[vidir](https://joeyh.name/code/moreutils/) | -| [ringtone](ringtone) | Create a variable bitrate mp3 ringtone from file | sh | date, ffmpeg | -| [rsynccp](rsynccp) | Gives copy-paste verbose progress percentage | sh | rsync | -| [splitjoin](splitjoin) | Split file or join selection | sh | split, cat | -| [suedit](suedit) | Edit file using superuser permissions | sh | sudoedit/sudo/doas | -| [togglex](togglex) | Toggle executable mode for selection | sh | chmod | -| [treeview](treeview) | Informative tree output in `$EDITOR` | sh | tree | -| [uidgid](uidgid) | List user and group of all files in dir | sh | ls, less | -| [upgrade](upgrade) | Upgrade nnn manually on Debian 9 Stretch | sh | curl | -| [upload](upload) | Upload to Firefox Send or ix.io (text) or file.io (bin) | sh | [ffsend](https://github.com/timvisee/ffsend), curl, jq, tr | -| [vidthumb](vidthumb) | Show video thumbnails in terminal | sh | [ffmpegthumbnailer](https://github.com/dirkvdb/ffmpegthumbnailer),
[lsix](https://github.com/hackerb9/lsix) | -| [wall](wall) | Set wallpaper or change colorscheme | sh | nitrogen/pywal | -| [x2sel](x2sel) | Copy `\n`-separated file list from system clipboard to sel | sh | _see in-file docs_ | +| [autojump](autojump) | [ ] Navigate to dir/path | sh | [jump](https://github.com/gsamokovarov/jump)/autojump/zoxide | +| [bookmarks](bookmarks) | [ ] Use named bookmarks managed with symlinks | sh | fzf | +| [boom](boom) | [ ] Play random music from dir | sh | [moc](http://moc.daper.net/) | +| [bulknew](bulknew) | [ ] Create multiple files/dirs at once | bash | sed, xargs, mktemp | +| [chksum](chksum) | [x] Create and verify checksums | sh | md5sum,
sha256sum | +| [cleanfilename](cleanfilename) | [x] Clean filename to be more shell-friendly | sh | sed | +| [diffs](diffs) | [x] Diff for selection (limited to 2 for directories) | sh | vimdiff, mktemp | +| [dragdrop](dragdrop) | [ ] Drag/drop files from/into nnn | sh | [dragon](https://github.com/mwh/dragon) | +| [dups](dups) | [ ] List non-empty duplicate files in current dir | bash | find, md5sum,
sort uniq xargs | +| [finder](finder) | [ ] Run custom find command and list | sh | - | +| [fzcd](fzcd) | [ ] Change to the directory of a fuzzy-selected file/dir | sh | fzf | +| [fzhist](fzhist) | [ ] Fuzzy-select a cmd from history, edit in `$EDITOR` and run | sh | fzf, mktemp | +| [fzopen](fzopen) | [ ] Fuzzy find a file in dir subtree and edit or open | sh | fzf, xdg-open | +| [fzz](fzz) | [ ] Change to any directory in the z database with fzf | sh | fzf, z | +| [getplugs](getplugs) | [ ] Update plugins to installed `nnn` version | sh | curl | +| [gpg\*](gpg\*) | [x] Encrypt/decrypt files using GPG | sh | gpg | +| [gutenread](gutenread) | [ ] Browse, download, read from Project Gutenberg | sh | curl, unzip, w3m
[epr](https://github.com/wustho/epr) (optional) | +| [hexview](hexview) | [ ] View a file in hex in `$PAGER` | sh | [hx](https://github.com/krpors/hx)/xxd | +| [imgresize](imgresize) | [ ] Resize images in dir to screen resolution | sh | [imgp](https://github.com/jarun/imgp) | +| [imgthumb](imgthumb) | [ ] View thumbnail of an image or dir of images | sh | [lsix](https://github.com/hackerb9/lsix) | +| [imgur](imgur) | [ ] Upload an image to imgur (from [imgur-screenshot](https://github.com/jomo/imgur-screenshot)) | bash | - | +| [imgview](imgview) | [ ] Browse images, set wallpaper, copy path ([config](https://wiki.archlinux.org/index.php/Sxiv#Assigning_keyboard_shortcuts)), [rename](https://github.com/jarun/nnn/wiki/Basic-use-cases#browse-rename-images)| sh | [imv](https://github.com/eXeC64/imv)/[sxiv](https://github.com/muennich/sxiv)/[viu](https://github.com/atanunq/viu), less| +| [ipinfo](ipinfo) | [ ] Fetch external IP address and whois information | sh | curl, whois | +| [kdeconnect](kdeconnect) | [x] Send selected files to an Android device | sh | kdeconnect-cli | +| [launch](launch) | [ ] GUI application launcher | sh | fzf | +| [mediainf](mediainf) | [ ] Show media information | sh | mediainfo | +| [mimelist](mimelist) | [ ] List files by mime in subtree | sh | - | +| [moclyrics](moclyrics) | [ ] Show lyrics of the track playing in moc | sh | [ddgr](https://github.com/jarun/ddgr), [moc](http://moc.daper.net/) | +| [mocplay](mocplay) | [x] Append (and/or play) selection/dir/file in moc | sh | [moc](http://moc.daper.net/) | +| [mp3conv](mp3conv) | [ ] Extract audio from multimedia as mp3 | sh | ffmpeg | +| [mtpmount](mtpmount) | [ ] Toggle mount of MTP device (eg. Android) | sh | gvfs-mtp | +| [nbak](nbak) | [ ] Backs up `nnn` config | sh | tar, awk, mktemp | +| [nmount](nmount) | [ ] Toggle mount status of a device as normal user | sh | pmount, udisks2 | +| [nuke](nuke) | [ ] Sample file opener (CLI-only by default) | sh | _see in-file docs_ | +| [oldbigfile](oldbigfile) | [ ] List large files by access time | sh | find, sort | +| [organize](organize) | [x] Auto-organize files in directories by file type | sh | file | +| [pdfread](pdfread) | [ ] Read a PDF or text file aloud | sh | pdftotext, mpv,
pico2wave | +| [pdfview](pdfview) | [ ] View PDF file in `$PAGER` | sh | pdftotext/
mupdf-tools | +| [picker](picker) | [ ] Pick files and list one per line (to pipe) | sh | nnn | +| [preview-tabbed](preview-tabbed) | [ ] Tabbed/xembed based file previewer | bash | _see in-file docs_ | +| [preview-tui](preview-tui) | [ ] Tmux/kitty/xterm/`$TERMINAL` based file previewer | sh | _see in-file docs_ | +| [preview-tui-ext](preview-tui-ext) | [ ] Meant to be an exhaustive version of [preview-tui](preview-tui) | sh | _see in-file docs_ | +| [pskill](pskill) | [ ] Fuzzy list by name and kill process or zombie | sh | fzf, ps, sudo/doas | +| [renamer](renamer) | [x] Batch rename selection or files in dir | sh | [qmv](https://www.nongnu.org/renameutils/)/[vidir](https://joeyh.name/code/moreutils/) | +| [ringtone](ringtone) | [ ] Create a variable bitrate mp3 ringtone from file | sh | date, ffmpeg | +| [rsynccp](rsynccp) | [x] Gives copy-paste verbose progress percentage | sh | rsync | +| [splitjoin](splitjoin) | [x] Split file or join selection | sh | split, cat | +| [suedit](suedit) | [ ] Edit file using superuser permissions | sh | sudoedit/sudo/doas | +| [togglex](togglex) | [x] Toggle executable mode for selection | sh | chmod | +| [treeview](treeview) | [ ] Informative tree output in `$EDITOR` | sh | tree | +| [uidgid](uidgid) | [ ] List user and group of all files in dir | sh | ls, less | +| [upgrade](upgrade) | [ ] Upgrade nnn manually on Debian 9 Stretch | sh | curl | +| [upload](upload) | [ ] Upload to Firefox Send or ix.io (text) or file.io (bin) | sh | [ffsend](https://github.com/timvisee/ffsend), curl, jq, tr | +| [vidthumb](vidthumb) | [ ] Show video thumbnails in terminal | sh | [ffmpegthumbnailer](https://github.com/dirkvdb/ffmpegthumbnailer),
[lsix](https://github.com/hackerb9/lsix) | +| [wall](wall) | [ ] Set wallpaper or change colorscheme | sh | nitrogen/pywal | +| [x2sel](x2sel) | [ ] Copy `\n`-separated file list from system clipboard to sel | sh | _see in-file docs_ | + +Note: + +1. A plugin has to explicitly request `nnn` to clear the selection e.g. after operating on the selected files. ## Installation @@ -207,6 +211,7 @@ The `ctxcode` indicates the context to change the active directory of. | `1`-`4` | context number | | `0` | current context | | `+` | smart context (next inactive else current) | +| `-` | clear the selection | The `opcode` indicates the operation type. diff --git a/plugins/chksum b/plugins/chksum index 0a386e5a..97f0cf0a 100755 --- a/plugins/chksum +++ b/plugins/chksum @@ -45,6 +45,11 @@ 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" + + # Clear selection + if [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" + fi elif [ -n "$1" ]; then if [ -f "$1" ]; then for chks in md5 sha1 sha224 sha256 sha384 sha512 diff --git a/plugins/cleanfilename b/plugins/cleanfilename index b7f2ba06..d0a09480 100755 --- a/plugins/cleanfilename +++ b/plugins/cleanfilename @@ -21,7 +21,7 @@ cleanup() { printf "%s" "$1" | sed -e 's/[^A-Za-z0-9._-]/_/g' } -if [ -f "$sel" ]; then +if [ -s "$sel" ]; then targets=$(sed -e "s/\\x0/\\n/g;\$a\\" "$sel" | \ while read -r i; do basename "$i"; @@ -57,3 +57,8 @@ for i in $targets; do mv "$i" "$tmp$(cleanup "$i")"; fi done + +# Clear selection +if [ -s "$sel" ] && [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" +fi diff --git a/plugins/diffs b/plugins/diffs index d20cc5da..dea3a4cd 100755 --- a/plugins/diffs +++ b/plugins/diffs @@ -54,3 +54,8 @@ if [ -s "$selection" ]; then echo "needs at least 2 files or directories selected for comparison" fi fi + +# Clear selection +if [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" +fi diff --git a/plugins/gpgd b/plugins/gpgd index ed94bb1d..7f1dba2e 100755 --- a/plugins/gpgd +++ b/plugins/gpgd @@ -19,3 +19,8 @@ else fi printf "%s" "$files" | xargs -n1 -I{} gpg --decrypt --output "{}.dec" {} + +# Clear selection +if [ "$resp" = "s" ] && [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" +fi diff --git a/plugins/gpge b/plugins/gpge index 6a9cb9a9..ba935ab6 100755 --- a/plugins/gpge +++ b/plugins/gpge @@ -34,4 +34,9 @@ else recipient=$(printf "%s" "$keyuids" | fzf | awk '{print $1}') printf "%s" "$files" | xargs -n1 gpg --encrypt --recipient "$recipient" + + # Clear selection + if [ "$resp" = "s" ] && [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" + fi fi diff --git a/plugins/kdeconnect b/plugins/kdeconnect index 60658104..9bef7dfd 100755 --- a/plugins/kdeconnect +++ b/plugins/kdeconnect @@ -8,11 +8,16 @@ selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection} id=$(kdeconnect-cli -a --id-only | awk '{print $1}') -if [ "$(find "$selection")" ]; then +if [ -s "$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" + + # Clear selection + if [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" + fi fi diff --git a/plugins/mocplay b/plugins/mocplay index 39c7c9ad..dbda0d3c 100755 --- a/plugins/mocplay +++ b/plugins/mocplay @@ -82,3 +82,8 @@ mocp -p # uncomment the line below to show mocp interface after appending # mocp + +# Clear selection +if [ "$resp" = "y" ] && [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" +fi diff --git a/plugins/organize b/plugins/organize index 3fb34c1e..fb70aaff 100755 --- a/plugins/organize +++ b/plugins/organize @@ -2,9 +2,13 @@ # Description: Organize files in directories by category # +# Note: This plugin clears the selection as it changes the contents of the current dir +# # Shell: POSIX compliant # Author: th3lusive +sel=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection} + organize() { case "$(file -biL "$1")" in *video*) @@ -48,6 +52,11 @@ main() { do [ -f "$file" ] && organize "$file" done + + # Clear selection + if [ -s "$sel" ] && [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" + fi } main "$@" diff --git a/plugins/renamer b/plugins/renamer index 2d064c55..532434a9 100755 --- a/plugins/renamer +++ b/plugins/renamer @@ -33,6 +33,11 @@ fi if [ "$resp" = "y" ]; then # -o flag is necessary for interactive editors xargs -o -0 $batchrenamesel < "$selection" + + # Clear selection + if [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" + fi elif [ ! "$(LC_ALL=C ls -a)" = ". .." ]; then # On older systems that don't have ls -A diff --git a/plugins/rsynccp b/plugins/rsynccp index 60ee10cd..5cfa66fe 100755 --- a/plugins/rsynccp +++ b/plugins/rsynccp @@ -19,3 +19,8 @@ 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/plugins/splitjoin b/plugins/splitjoin index 545eadb4..5ba081b4 100755 --- a/plugins/splitjoin +++ b/plugins/splitjoin @@ -33,6 +33,11 @@ if [ "$resp" = "j" ]; then file="$(basename "$(echo "$arr" | sed -n '1p' | sed -e 's/[0-9][0-9]$//')")" sort -z < "$selection" | xargs -0 -I{} cat {} > "${file}.out" + + # Clear selection + if [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" + fi fi elif [ "$resp" = "s" ]; then if [ -n "$1" ] && [ -f "$1" ]; then diff --git a/plugins/togglex b/plugins/togglex index d65e00f2..e42d65ac 100755 --- a/plugins/togglex +++ b/plugins/togglex @@ -11,10 +11,11 @@ selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection} -if [ ! -s "$selection" ]; then - printf "0 selected " - read -r _ - exit -fi +if [ -s "$selection" ]; then + xargs -0 -I {} sh -c 'if [ -x "{}" ] ; then chmod -x "{}" ; else chmod +x "{}" ; fi' < "$selection" -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/src/nnn.c b/src/nnn.c index 50f20413..5147651d 100644 --- a/src/nnn.c +++ b/src/nnn.c @@ -4754,15 +4754,15 @@ static void readpipe(int fd, char **path, char **lastname, char **lastdir) char ctx, *nextpath = NULL; ssize_t len = read_nointr(fd, g_buf, 1); - if (len != 1) { - if (selbufpos) - clearselection(); + if (len != 1) return; - } if (g_buf[0] == '+') ctx = (char)(get_free_ctx() + 1); - else if (g_buf[0] < '0') + else if (g_buf[0] == '-') { /* Clear selection on '-' */ + clearselection(); + return; + } else if (g_buf[0] < '0') return; else { ctx = g_buf[0] - '0'; @@ -4789,8 +4789,7 @@ static void readpipe(int fd, char **path, char **lastname, char **lastdir) rmlistpath(); nextpath = load_input(fd, *path); - } else if (selbufpos) - clearselection(); + } if (nextpath) { if (ctx == 0 || ctx == cfg.curctx + 1) { /* Same context */