sistema_progs

Programas para customizar o meu entorno de traballo nos meus equipos persoais
Log | Files | Refs

commit 03827eae54c06c1805d044481a90e4f2a3603042
parent c54128aed1ba8f4241d8d8937b2c6a2a80039512
Author: xoel <x.otero@udc.es>
Date:   Mon,  2 Oct 2023 06:35:08 +0200

dot files

Diffstat:
Aconfig/nnn/plugins-202203130245.tar.gz | 0
Aconfig/nnn/plugins/.cbcp | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/.iconlookup | 428+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/.nmv | 171+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/.nnn-plugin-helper | 38++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/.ntfy | 22++++++++++++++++++++++
Aconfig/nnn/plugins/autojump | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/boom | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/bulknew | 32++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/cdpath | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/chksum | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/cmusq | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/diffs | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/dragdrop | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/dups | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/finder | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/fixname | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/fzcd | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/fzhist | 40++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/fzopen | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/fzplug | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/getplugs | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/gpgd | 28++++++++++++++++++++++++++++
Aconfig/nnn/plugins/gpge | 44++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/gutenread | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/imgresize | 31+++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/imgur | 595+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/imgview | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/ipinfo | 13+++++++++++++
Aconfig/nnn/plugins/kdeconnect | 24++++++++++++++++++++++++
Aconfig/nnn/plugins/launch | 42++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/mimelist | 14++++++++++++++
Aconfig/nnn/plugins/moclyrics | 40++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/mocq | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/mp3conv | 41+++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/mtpmount | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/nbak | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/nmount | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/nuke | 558+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/oldbigfile | 16++++++++++++++++
Aconfig/nnn/plugins/organize | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/pdfread | 30++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/preview-tabbed | 211+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/preview-tui | 455+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/pskill | 35+++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/renamer | 45+++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/ringtone | 36++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/rsynccp | 26++++++++++++++++++++++++++
Aconfig/nnn/plugins/splitjoin | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/suedit | 16++++++++++++++++
Aconfig/nnn/plugins/togglex | 21+++++++++++++++++++++
Aconfig/nnn/plugins/umounttree | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/upload | 30++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/wallpaper | 26++++++++++++++++++++++++++
Aconfig/nnn/plugins/x2sel | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nnn/plugins/xdgdefault | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Aconfig/nvim/init.vim | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aportatil/bash_profile | 17+++++++++++++++++
Aportatil/bashrc | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aportatil/xinitrc | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
60 files changed, 5127 insertions(+), 0 deletions(-)

diff --git a/config/nnn/plugins-202203130245.tar.gz b/config/nnn/plugins-202203130245.tar.gz Binary files differ. diff --git a/config/nnn/plugins/.cbcp b/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 type xsel >/dev/null 2>&1; then + # Linux + tr '\0' '\n' < "$selection" | xsel -bi +elif type xclip >/dev/null 2>&1; then + # Linux + tr '\0' '\n' < "$selection" | xclip -sel clip +elif type pbcopy >/dev/null 2>&1; then + # macOS + tr '\0' '\n' < "$selection" | pbcopy +elif type termux-clipboard-set >/dev/null 2>&1; then + # Termux + tr '\0' '\n' < "$selection" | termux-clipboard-set +elif type clip.exe >/dev/null 2>&1; then + # WSL + tr '\0' '\n' < "$selection" | clip.exe +elif type clip >/dev/null 2>&1; then + # Cygwin + tr '\0' '\n' < "$selection" | clip +elif type wl-copy >/dev/null 2>&1; then + # Wayland + tr '\0' '\n' < "$selection" | wl-copy +elif type clipboard >/dev/null 2>&1; then + # Haiku + tr '\0' '\n' < "$selection" | clipboard --stdin +fi diff --git a/config/nnn/plugins/.iconlookup b/config/nnn/plugins/.iconlookup @@ -0,0 +1,428 @@ +#!/usr/bin/env sh + +# Description: Print icons in front of list of directories/files + +# Dependencies: awk + +# Usage +# 1. Set colors and/or icons to your liking +# 2. Pipe any directory listing to iconlookup and it will output prepended icons +# 3. preview-tui uses the script to prepend icon to directory listings +# 4. Aditionally you can consider adding it to your PATH and/or FZF_DEFAULT_COMMAND to +# make it work with various fzf plugins (make sure you also add --ansi to your FZF_DEFAULT_OPTS) + +# Shell: POSIX compliant + +# Author: Luuk van Baal (https://github.com/luukvbaal/iconlookup) + +icon_lookup() { +awk 'BEGIN { +# Set your ANSI colorscheme below (https://en.wikipedia.org/wiki/ANSI_escape_code#Colors). +# Default uses standard nnn icon colors, 8 and 24-bit nord themes are commented out. + colordepth=8 #colordepth=8 #colordepth=24 + color_dirtxt=39 #color_dirtxt=111 #color_dirtxt="129;161;193" + color_filetxt=15 #color_filetxt=111 #color_filetxt="129;161;193" + color_default=39 #color_default=111 #color_default="129;161;193" + color_video=93 #color_video=110 #color_video="136;192;208" + color_audio=220 #color_audio=150 #color_audio="163;190;140" + color_image=82 #color_image=150 #color_image="163;190;140" + color_docs=202 #color_docs=173 #color_docs="208;135;112" + color_archive=209 #color_archive=179 #color_archive="235;203;139" + color_c=81 #color_c=150 #color_c="163;190;140" + color_java=32 #color_java=139 #color_java="180;142;173" + color_js=47 #color_js=109 #color_js="143;188;187" + color_react=39 #color_react=111 #color_react="129;161;193" + color_css=199 #color_css=110 #color_css="136;192;208" + color_python=227 #color_python=68 #color_python="94;129;172" + color_lua=19 #color_lua=167 #color_lua="191;97;106" + color_document=15 #color_document=173 #color_document="208;135;112" + color_fsharp=31 #color_fsharp=179 #color_fsharp="180;142;173" + color_ruby=160 #color_ruby=150 #color_ruby="163;190;140" + color_scala=196 #color_scala=139 #color_scala="143;188;187" + color_shell=47 #color_shell=109 #color_shell="143;188;187" + color_vim=28 #color_vim=109 #color_vim="143;188;187" + +# icons[][1] contains icon and icons[][2] contains color + icons["directory"][1] = ""; icons["directory"][2] = color_default + icons["file"][1] = ""; icons["file"][2] = color_default + icons["exec"][1] = ""; icons["exec"][2] = color_default + icons["manual"][1] = ""; icons["manual"][2] = color_docs + icons["pipe"][1] = "ﳣ"; icons["pipe"][2] = color_default + icons["socket"][1] = "ﳧ"; icons["socket"][2] = color_default + icons["door"][1] = "➡"; icons["door"][2] = color_default + +# top level and common icons + icons[".git"][1] = ""; icons[".git"][2] = color_default + icons["desktop"][1] = "ﲾ"; icons["desktop"][2] = color_default + icons["briefcase"][1] = ""; icons["briefcase"][2] = color_default + icons["document"][1] = ""; icons["document"][2] = color_default + icons["downloads"][1] = ""; icons["downloads"][2] = color_default + icons["music"][1] = ""; icons["music"][2] = color_default + icons["musicfile"][1] = ""; icons["musicfile"][2] = color_audio + icons["pictures"][1] = ""; icons["pictures"][2] = color_default + icons["picturefile"][1] = ""; icons["picturefile"][2] = color_image + icons["public"][1] = ""; icons["public"][2] = color_default + icons["templates"][1] = "陼"; icons["templates"][2] = color_default + icons["videos"][1] = ""; icons["videos"][2] = color_default + icons["videofile"][1] = "ﳜ"; icons["videofile"][2] = color_video + icons["changelog"][1] = ""; icons["changelog"][2] = color_docs + icons["configure"][1] = ""; icons["configure"][2] = color_default + icons["license"][1] = ""; icons["license"][2] = color_docs + icons["makefile"][1] = ""; icons["makefile"][2] = color_default + icons["archive"][1] = ""; icons["archive"][2] = color_archive + icons["script"][1] = ""; icons["script"][2] = color_shell + icons["cplusplus"][1] = ""; icons["cplusplus"][2] = color_c + icons["java"][1] = ""; icons["java"][2] = color_java + icons["clojure"][1] = ""; icons["clojure"][2] = color_default + icons["js"][1] = ""; icons["js"][2] = color_js + icons["linux"][1] = ""; icons["linux"][2] = color_default + icons["fsharp"][1] = ""; icons["fsharp"][2] = color_fsharp + icons["ruby"][1] = ""; icons["ruby"][2] = color_ruby + icons["c"][1] = ""; icons["c"][2] = color_c + icons["chess"][1] = ""; icons["chess"][2] = color_default + icons["haskell"][1] = ""; icons["haskell"][2] = color_vim + icons["html"][1] = ""; icons["html"][2] = color_default + icons["react"][1] = ""; icons["react"][2] = color_react + icons["python"][1] = ""; icons["python"][2] = color_python + icons["database"][1] = ""; icons["database"][2] = color_default + icons["worddoc"][1] = ""; icons["worddoc"][2] = color_document + icons["playlist"][1] = "蘿"; icons["playlist"][2] = color_audio + icons["opticaldisk"][1] = ""; icons["opticaldisk"][2] = color_archive + +# numbers + icons["1"][1] = icons["manual"][1]; icons["1"][2] = icons["manual"][2] + icons["7z"][1] = icons["archive"][1]; icons["7z"][2] = icons["archive"][2] + +# a + icons["a"][1] = icons["manual"][1]; icons["a"][2] = icons["manual"][2] + icons["apk"][1] = icons["archive"][1]; icons["apk"][2] = icons["archive"][2] + icons["asm"][1] = icons["file"][1]; icons["asm"][2] = icons["file"][2] + icons["aup"][1] = icons["musicfile"][1]; icons["aup"][2] = icons["musicfile"][2] + icons["avi"][1] = icons["videofile"][1]; icons["avi"][2] = icons["videofile"][2] + +# b + icons["bat"][1] = icons["script"][1]; icons["bat"][2] = icons["script"][2] + icons["bin"][1] = ""; icons["bin"][2] = color_default + icons["bmp"][1] = icons["picturefile"][1]; icons["bmp"][2] = icons["picturefile"][2] + icons["bz2"][1] = icons["archive"][1]; icons["bz2"][2] = icons["archive"][2] + +# c + icons["cplusplus"][1] = icons["cplusplus"][1]; icons["cplusplus"][2] = icons["cplusplus"][2] + icons["cabal"][1] = icons["haskell"][1]; icons["cab"][2] = icons["haskell"][2] + icons["cab"][1] = icons["archive"][1]; icons["cab"][2] = icons["archive"][2] + icons["cbr"][1] = icons["archive"][1]; icons["cbr"][2] = icons["archive"][2] + icons["cbz"][1] = icons["archive"][1]; icons["cbz"][2] = icons["archive"][2] + icons["cc"][1] = icons["cplusplus"][1]; icons["cc"][2] = icons["cplusplus"][2] + icons["class"][1] = icons["java"][1]; icons["class"][2] = icons["java"][2] + icons["clj"][1] = icons["clojure"][1]; icons["clj"][2] = icons["clojure"][2] + icons["cljc"][1] = icons["clojure"][1]; icons["cljc"][2] = icons["clojure"][2] + icons["cljs"][1] = icons["clojure"][1]; icons["cljs"][2] = icons["clojure"][2] + icons["cmake"][1] = icons["makefile"][1]; icons["cmake"][2] = icons["makefile"][2] + icons["coffee"][1] = ""; icons["coffee"][2] = color_default + icons["conf"][1] = icons["configure"][1]; icons["conf"][2] = icons["configure"][2] + icons["cpio"][1] = icons["archive"][1]; icons["cpio"][2] = icons["archive"][2] + icons["cpp"][1] = icons["cplusplus"][1]; icons["cpp"][2] = icons["cplusplus"][2] + icons["css"][1] = ""; icons["css"][2] = color_css + icons["cue"][1] = icons["playlist"][1]; icons["cue"][2] = icons["playlist"][2] + icons["cvs"][1] = icons["configure"][1]; icons["cvs"][2] = icons["configure"][2] + icons["cxx"][1] = icons["cplusplus"][1]; icons["cxx"][2] = icons["cplusplus"][2] + +# d + icons["db"][1] = icons["database"][1]; icons["db"][2] = icons["database"][2] + icons["deb"][1] = ""; icons["deb"][2] = color_archive + icons["diff"][1] = ""; icons["diff"][2] = color_default + icons["dll"][1] = icons["script"][1]; icons["dll"][2] = icons["script"][2] + icons["doc"][1] = icons["worddoc"][1]; icons["doc"][2] = icons["worddoc"][2] + icons["docx"][1] = icons["worddoc"][1]; icons["docx"][2] = icons["worddoc"][2] + +# e + icons["ejs"][1] = icons["js"][1]; icons["ejs"][2] = icons["js"][2] + icons["elf"][1] = icons["linux"][1]; icons["elf"][2] = icons["linux"][2] + icons["epub"][1] = icons["manual"][1]; icons["epub"][2] = icons["manual"][2] + icons["exe"][1] = icons["exec"][1]; icons["exe"][2] = icons["exec"][2] + +# f + icons["fsharp"][1] = icons["fsharp"][1]; icons["fsharp"][2] = icons["fsharp"][2] + icons["flac"][1] = icons["musicfile"][1]; icons["flac"][2] = icons["musicfile"][2] + icons["fen"][1] = icons["chess"][1]; icons["fen"][2] = icons["chess"][2] + icons["flv"][1] = icons["videofile"][1]; icons["flv"][2] = icons["videofile"][2] + icons["fs"][1] = icons["fsharp"][1]; icons["fs"][2] = icons["fsharp"][2] + icons["fsi"][1] = icons["fsharp"][1]; icons["fsi"][2] = icons["fsharp"][2] + icons["fsscript"][1] = icons["fsharp"][1]; icons["fsscript"][2] = icons["fsharp"][2] + icons["fsx"][1] = icons["fsharp"][1]; icons["fsx"][2] = icons["fsharp"][2] + +# g + icons["gem"][1] = icons["ruby"][1]; icons["gem"][2] = icons["ruby"][2] + icons["gif"][1] = icons["picturefile"][1]; icons["gif"][2] = icons["picturefile"][2] + icons["go"][1] = "ﳑ"; icons["go"][2] = color_default + icons["gz"][1] = icons["archive"][1]; icons["gz"][2] = icons["archive"][2] + icons["gzip"][1] = icons["archive"][1]; icons["gzip"][2] = icons["archive"][2] + +# h + icons["h"][1] = icons["c"][1]; icons["h"][2] = icons["c"][2] + icons["hh"][1] = icons["cplusplus"][1]; icons["hh"][2] = icons["cplusplus"][2] + icons["hpp"][1] = icons["cplusplus"][1]; icons["hpp"][2] = icons["cplusplus"][2] + icons["hs"][1] = icons["haskell"][1]; icons["hs"][2] = icons["haskell"][2] + icons["htaccess"][1] = icons["configure"][1]; icons["htaccess"][2] = icons["configure"][2] + icons["htpasswd"][1] = icons["configure"][1]; icons["htpasswd"][2] = icons["configure"][2] + icons["htm"][1] = icons["html"][1]; icons["htm"][2] = icons["html"][2] + icons["hxx"][1] = icons["cplusplus"][1]; icons["hxx"][2] = icons["cplusplus"][2] + +# i + icons["ico"][1] = icons["picturefile"][1]; icons["ico"][2] = icons["picturefile"][2] + icons["img"][1] = icons["opticaldisk"][1]; icons["img"][2] = icons["opticaldisk"][2] + icons["ini"][1] = icons["configure"][1]; icons["ini"][2] = icons["configure"][2] + icons["iso"][1] = icons["opticaldisk"][1]; icons["iso"][2] = icons["opticaldisk"][2] + +# j + icons["jar"][1] = icons["java"][1]; icons["jar"][2] = icons["java"][2] + icons["java"][1] = icons["java"][1]; icons["java"][2] = icons["java"][2] + icons["jl"][1] = icons["configure"][1]; icons["jl"][2] = icons["configure"][2] + icons["jpeg"][1] = icons["picturefile"][1]; icons["jpeg"][2] = icons["picturefile"][2] + icons["jpg"][1] = icons["picturefile"][1]; icons["jpg"][2] = icons["picturefile"][2] + icons["json"][1] = "ﬥ"; icons["json"][2] = color_js + icons["jsx"][1] = icons["react"][1]; icons["jsx"][2] = icons["react"][2] + +# k + +# l + icons["lha"][1] = icons["archive"][1]; icons["lha"][2] = icons["archive"][2] + icons["lhs"][1] = icons["haskell"][1]; icons["lhs"][2] = icons["haskell"][2] + icons["ilog"][1] = icons["document"][1]; icons["ilog"][2] = icons["document"][2] + icons["lua"][1] = ""; icons["lua"][2] = color_lua + icons["lzh"][1] = icons["archive"][1]; icons["lzh"][2] = icons["archive"][2] + icons["lzma"][1] = icons["archive"][1]; icons["lzma"][2] = icons["archive"][2] + +# m + icons["m"][1] = "ﴜ"; icons["mat"][2] = color_c + icons["m4a"][1] = icons["musicfile"][1]; icons["m4a"][2] = icons["musicfile"][2] + icons["m4v"][1] = icons["videofile"][1]; icons["m4v"][2] = icons["videofile"][2] + icons["mat"][1] = ""; icons["mat"][2] = color_c + icons["markdown"][1] = ""; icons["markdown"][2] = color_docs + icons["md"][1] = ""; icons["md"][2] = color_docs + icons["mk"][1] = icons["makefile"][1]; icons["mk"][2] = icons["makefile"][2] + icons["mkv"][1] = icons["videofile"][1]; icons["mkv"][2] = icons["videofile"][2] + icons["mov"][1] = icons["videofile"][1]; icons["mov"][2] = icons["videofile"][2] + icons["mp3"][1] = icons["musicfile"][1]; icons["mp3"][2] = icons["musicfile"][2] + icons["mp4"][1] = icons["videofile"][1]; icons["mp4"][2] = icons["videofile"][2] + icons["mpeg"][1] = icons["videofile"][1]; icons["mpeg"][2] = icons["videofile"][2] + icons["mpg"][1] = icons["videofile"][1]; icons["mpg"][2] = icons["videofile"][2] + icons["msi"][1] = ""; icons["msi"][2] = color_default + +# n + icons["nix"][1] = ""; icons["nix"][2] = color_fsharp + +# o + icons["o"][1] = icons["manual"][1]; icons["o"][2] = icons["manual"][2] + icons["ogg"][1] = icons["musicfile"][1]; icons["ogg"][2] = icons["musicfile"][2] + icons["odownload"][1] = icons["download"][1]; icons["odownload"][2] = icons["download"][2] + icons["out"][1] = icons["linux"][1]; icons["out"][2] = icons["linux"][2] + +# p + icons["part"][1] = icons["download"][1]; icons["part"][2] = icons["download"][2] + icons["patch"][1] = icons["diff"][1]; icons["patch"][2] = icons["diff"][2] + icons["pdf"][1] = ""; icons["pdf"][2] = color_docs + icons["pgn"][1] = icons["chess"][1]; icons["pgn"][2] = icons["chess"][2] + icons["php"][1] = ""; icons["php"][2] = color_default + icons["png"][1] = icons["picturefile"][1]; icons["png"][2] = icons["picturefile"][2] + icons["ppt"][1] = ""; icons["ppt"][2] = color_default + icons["pptx"][1] = ""; icons["pptx"][2] = color_default + icons["psb"][1] = ""; icons["psb"][2] = color_default + icons["psd"][1] = ""; icons["psd"][2] = color_default + icons["py"][1] = icons["python"][1]; icons["py"][2] = icons["python"][2] + icons["pyc"][1] = icons["python"][1]; icons["pyc"][2] = icons["python"][2] + icons["pyd"][1] = icons["python"][1]; icons["pyd"][2] = icons["python"][2] + icons["pyo"][1] = icons["python"][1]; icons["pyo"][2] = icons["python"][2] + +# q + +# r + icons["rar"][1] = icons["archive"][1]; icons["rar"][2] = icons["archive"][2] + icons["rc"][1] = icons["configure"][1]; icons["rc"][2] = icons["configure"][2] + icons["rom"][1] = ""; icons["rom"][2] = color_default + icons["rpm"][1] = icons["archive"][1]; icons["rpm"][2] = icons["archive"][2] + icons["rss"][1] = "參"; icons["rss"][2] = color_default + icons["rtf"][1] = ""; icons["rtf"][2] = color_default + +# s + icons["sass"][1] = ""; icons["sass"][2] = color_css + icons["scss"][1] = ""; icons["scss"][2] = color_css + icons["so"][1] = icons["manual"][1]; icons["so"][2] = icons["manual"][2] + icons["scala"][1] = ""; icons["scala"][2] = color_scala + icons["sh"][1] = icons["script"][1]; icons["sh"][2] = icons["script"][2] + icons["slim"][1] = icons["script"][1]; icons["slim"][2] = icons["script"][2] + icons["sln"][1] = ""; icons["sln"][2] = color_default + icons["sql"][1] = icons["database"][1]; icons["sql"][2] = icons["database"][2] + icons["srt"][1] = ""; icons["srt"][2] = color_default + icons["isub"][1] = ""; icons["isub"][2] = color_default + icons["svg"][1] = icons["picturefile"][1]; icons["svg"][2] = icons["picturefile"][2] + +# t + icons["tar"][1] = icons["archive"][1]; icons["tar"][2] = icons["archive"][2] + icons["tex"][1] = ""; icons["tex"][2] = color_default + icons["tgz"][1] = icons["archive"][1]; icons["tgz"][2] = icons["archive"][2] + icons["ts"][1] = ""; icons["ts"][2] = color_js + icons["tsx"][1] = icons["react"][1]; icons["tsx"][2] = icons["react"][2] + icons["txt"][1] = icons["document"][1]; icons["txt"][2] = icons["document"][2] + icons["txz"][1] = icons["archive"][1]; icons["txz"][2] = icons["archive"][2] + +# u + +# v + icons["vid"][1] = icons["videofile"][1]; icons["vid"][2] = icons["videofile"][2] + icons["vim"][1] = ""; icons["vim"][2] = color_vim + icons["vimrc"][1] = ""; icons["vimrc"][2] = color_vim + icons["vtt"][1] = ""; icons["vtt"][2] = color_default +# w + icons["wav"][1] = icons["musicfile"][1]; icons["wav"][2] = icons["musicfile"][2] + icons["webm"][1] = icons["videofile"][1]; icons["webm"][2] = icons["videofile"][2] + icons["wma"][1] = icons["videofile"][1]; icons["wma"][2] = icons["videofile"][2] + icons["wmv"][1] = icons["videofile"][1]; icons["wmv"][2] = icons["videofile"][2] + +# x + icons["xbps"][1] = icons["archive"][1]; icons["xbps"][2] = color_archive + icons["xcf"][1] = icons["picturefile"][1]; icons["xcf"][2] = color_image + icons["xhtml"][1] = icons["html"][1]; icons["xhtml"][2] = icons["html"][2] + icons["xls"][1] = ""; icons["xls"][2] = color_default + icons["xlsx"][1] = ""; icons["xlsx"][2] = color_default + icons["xml"][1] = icons["html"][1]; icons["xml"][2] = icons["html"][2] + icons["xz"][1] = icons["archive"][1]; icons["xz"][2] = icons["archive"][2] + +# y + icons["yaml"][1] = icons["configure"][1]; icons["yaml"][2] = icons["configure"][2] + icons["yml"][1] = icons["configure"][1]; icons["yml"][2] = icons["configure"][2] +# z + icons["zip"][1] = icons["archive"][1]; icons["zip"][2] = icons["archive"][2] + icons["zsh"][1] = icons["script"][1]; icons["zsh"][2] = icons["script"][2] + icons["zst"][1] = icons["archive"][1]; icons["zst"][2] = icons["archive"][2] + + FS = "." + limit = ENVIRON["limit"] + switch (colordepth) { + case "4": + escape="\033[" + break; + case "8": + escape="\033[38;5;" + break; + case "24": + escape="\033[38;2;" + break; + } + bstr = ENVIRON["beforestr"] +} +{ + # dont print cwd . and leading ./ from tree -f + if ($0 ~/^\.$/) + next + ent = ($0 ~/^\.\//) ? substr($0, 3, length($0) - 2) : $0 + ext = $NF + + # Print icons, set color and bold directories by using ansi escape codes + if (ext in icons) + printcolor(icons[ext][1], icons[ext][2], color_filetxt, ent, "10") + else + switch (substr(ent, length(ent), 1)) { + case "/": + printcolor(icons["directory"][1], color_default, color_dirtxt, ent, "1") + break; + case "*": + printcolor(icons["exe"][1], color_default, color_filetxt, ent, "10") + break; + case "|": + printcolor(icons["pipe"][1], color_default, color_filetxt, ent, "10") + break; + case "=": + printcolor(icons["socket"][1], color_default, color_filetxt, ent, "10") + break; + case ">": + printcolor(icons["door"][1], color_default, color_filetxt, ent, "10") + break; + default: + printcolor(icons["file"][1], color_default, color_filetxt, ent, "10") + } +} +function printcolor(i, c, d, n, b) { + if (limit != "" && length(n) + 2 > limit) + n = substr(n, 1, limit - 2) + printf "\033[0m" + printf "%s%s%s;%sm%s %s%sm%s\n", bstr, escape, c, b, i, escape, d, n +}' +printf '\033[0m' +} + +print_begin() { + printf '%s\n' "$1" | sed 's/\\n/\n/g' +} + +print_end() { + printf '%s\n' "$1" | sed 's/\\n/\n/g' +} + +print_help() { + printf 'Icon Lookup\n +Usage: + iconlookup [options] + iconlookup [-bBe] [string] + iconlookup -l [number] + iconlookup (-h | --help) + + Prepend icons to list of files based on extension or appended indicator by ls/tree "-F" flag ("/" for directory, "*" for executable etc.) + +Options: + -h --help -? Show this screen. + -b --before Prepend str before icon. + -B --begin Prepend str before output. + -e --end Append str after output. + -l --limit Limit line length to [number] characters.' +} + +while :; do + case $1 in + -h|-\?|--help) + print_help + exit ;; + -B|--begin) + if [ -n "$2" ]; then + print_begin "$2" + fi + shift ;; + -e|--end) + if [ -n "$2" ]; then + end=1 + endstr="$2" + fi + shift ;; + -b|--before) + if [ -n "$2" ]; then + export beforestr="$2" + fi + shift ;; + -l|--limit) + if [ -n "$2" ]; then + export limit="$2" + shift + else + printf 'ERROR: "--limit" requires a non-empty option argument.\n' + exit + fi ;; + --) + shift + break ;; + -?*) + printf 'WARNING: Unknown option ignored: %s\n' "$1" ;; + *) break ;; + esac + shift +done + +if [ ! -t 0 ]; then + [ -n "$beforestr" ] && limit="$((limit - ${#beforestr}))" + icon_lookup +else + printf 'ERROR: no data provided...\nExpecting a directory listing in stdin\n' +fi + +if [ -n "$end" ]; then + print_end "$endstr" +fi diff --git a/config/nnn/plugins/.nmv b/config/nnn/plugins/.nmv @@ -0,0 +1,171 @@ +#!/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 +# To use NNN_LIST your shell must support readlink(1) +# +# 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}" +RECURSIVE="${RECURSIVE:-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 + findcmd="find . ! -name ." + + if [ "$RECURSIVE" -eq 0 ]; then + findcmd="$findcmd -prune" + fi + + if [ "$INCLUDE_HIDDEN" -eq 0 ]; then + findcmd="$findcmd ! -name \".*\"" + fi + + if [ -z "$NNN_LIST" ]; then + findcmd="$findcmd -print" + else + findcmd="$findcmd -printf "'"'"$NNN_LIST/%P\n"'"' + fi + + arr=$(eval "$findcmd" | sort) +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 + if [ -n "$NNN_LIST" ]; then + line=$(readlink "$line" || printf "%s" "$line") + fi + + 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 -i "$src" "$name"; then + printf "%s: failed to rename %s to %s: %s\n" "$0" "$name" "$tmp" "$!" > /dev/stderr + exit_status=1 + else + if [ -d "$name" ]; then + for key in "${!items[@]}"; do + 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/config/nnn/plugins/.nnn-plugin-helper b/config/nnn/plugins/.nnn-plugin-helper @@ -0,0 +1,38 @@ +#!/usr/bin/env sh + +# Description: Helper script for plugins +# +# Shell: POSIX compliant +# Author: Anna Arad + +selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection} +export selection + +## Set CUR_CTX to 1 to open directory in current context +CUR_CTX=0 +export CUR_CTX + +## Ask nnn to switch to directory $1 in context $2. +## If $2 is not provided, the function asks explicitly. +nnn_cd () { + dir="$1" + + if [ -z "$NNN_PIPE" ]; then + echo "No pipe file found" 1>&2 + return + fi + + if [ -n "$2" ]; then + context=$2 + elif [ $CUR_CTX -ne 1 ]; then + printf "Choose context 1-4 (blank for current): " + read -r context + fi + + printf "%s" "${context:-0}c$dir" > "$NNN_PIPE" +} + +cmd_exists () { + type "$1" > /dev/null 2>&1 + echo $? +} diff --git a/config/nnn/plugins/.ntfy b/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 type notify-send >/dev/null 2>&1; then + notify-send nnn "Done!" +elif [ "$OS" = "Darwin" ]; then + osascript -e 'display notification "Done!" with title "nnn"' +elif type ntfy >/dev/null 2>&1; then + ntfy -t nnn send "Done!" +elif [ "$OS" = "Haiku" ]; then + notify --title "nnn" "Done!" +fi diff --git a/config/nnn/plugins/autojump b/config/nnn/plugins/autojump @@ -0,0 +1,61 @@ +#!/usr/bin/env sh + +# Description: Navigate to directory using jump/autojump/zoxide/z +# +# Dependencies: +# - jump - https://github.com/gsamokovarov/jump +# - OR autojump - https://github.com/wting/autojump +# - OR zoxide - https://github.com/ajeetdsouza/zoxide +# - OR z - https://github.com/rupa/z (z requires fzf) +# - OR z (fish) - https://github.com/jethrokuan/z (z requires fzf) +# +# Note: The dependencies STORE NAVIGATION PATTERNS +# +# Shell: POSIX compliant +# Authors: Marty Buchaus, Dave Snider, Tim Adler, Nick Waywood + +if [ ! -p "$NNN_PIPE" ]; then + printf 'ERROR: NNN_PIPE is not set!' + read -r _ + exit 2 +fi + +if type jump >/dev/null 2>&1; then + printf "jump to : " + IFS= read -r line + # shellcheck disable=SC2086 + odir="$(jump cd ${line})" + printf "%s" "0c$odir" > "$NNN_PIPE" +elif type autojump >/dev/null 2>&1; then + printf "jump to : " + read -r dir + odir="$(autojump "$dir")" + printf "%s" "0c$odir" > "$NNN_PIPE" +elif type zoxide >/dev/null 2>&1; then + if type fzf >/dev/null 2>&1; then + odir="$(zoxide query -i --)" + printf "%s" "0c$odir" > "$NNN_PIPE" + else + printf "jump to : " + read -r dir + odir="$(zoxide query -- "$dir")" + printf "%s" "0c$odir" > "$NNN_PIPE" + fi +else + # rupa/z uses $_Z_DATA, jethrokuan/z (=port of z for fish) uses $Z_DATA + datafile="${_Z_DATA:-${Z_DATA:-$HOME/.z}}" + if type fzf >/dev/null 2>&1 && [ -f "$datafile" ]; then + # Read the data from z's file instead of calling + # z so the data doesn't need to be processed twice + sel=$(awk -F "|" '{print $1}' "$datafile" | fzf | 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" | fzf | sed 's/^[0-9,.]* *//' | awk '{$1=$1};1') + + printf "%s" "0c$sel" > "$NNN_PIPE" + else + printf "No supported autojump script [jump/autojump/zoxide/z (needs fzf)] found" + read -r _ + fi +fi diff --git a/config/nnn/plugins/boom b/config/nnn/plugins/boom @@ -0,0 +1,50 @@ +#!/usr/bin/env sh + +# Description: Play random music (MP3, FLAC, M4A, WEBM, WMA) from current dir. +# +# Dependencies: mocp (or custom) +# +# Note: You may want to set GUIPLAYER. +# +# Shell: POSIX compliant +# Author: Arun Prakash Jana + +GUIPLAYER="${GUIPLAYER}" +NUMTRACKS="${NUMTRACKS:-100}" + +if [ -n "$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 type 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/config/nnn/plugins/bulknew b/config/nnn/plugins/bulknew @@ -0,0 +1,32 @@ +#!/usr/bin/env sh + +# Description: Allows for creation of multiple files/dirs simultaneously +# Creates a tmp file to write each entry in 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/config/nnn/plugins/cdpath b/config/nnn/plugins/cdpath @@ -0,0 +1,55 @@ +#!/usr/bin/env sh + +# Description: 'cd' to the directory from CDPATH +# +# Details: If the CDPATH environmet variable is not set, the default value of +# ${XDG_CONFIG_HOME:-$HOME/.config}/nnn/bookmarks will be used. +# You can create this directory and fill it with symbolic links to your +# favorite directories. It's a good idea to add it to CDPATH so that it +# could also be used from the command line outside of nnn. +# The fzf search is done on the directory basename (the first column). +# +# This plugin is an extended version of the bookmarks plugin. +# If you set your CDPATH to ${XDG_CACHE_HOME:-$HOME/.cache}/nnn/bookmarks +# or to the value of BOOKMARKS_DIR, you can use it as a bookmarks replacement. +# +# Shell: POSIX compliant +# Author: Yuri Kloubakov + +. "$(dirname "$0")"/.nnn-plugin-helper + +# Get a list of (symbolic links to) directories for every element of CDPATH +get_dirs() { + IFS=':' + for path in $CDPATH; do + for entry in "$path"/*; do + if [ -d "$entry" ]; then + name=$(basename "$entry" | grep -o '^.\{1,24\}') + if [ -h "$entry" ]; then + slink=$(ls -dl -- "$entry") + entry=${slink#*" $entry -> "} + fi + printf "%-24s :%s\n" "${name}" "$entry" + fi + done + done +} + +abort() { + echo "$1" + read -r _ + exit 1 +} + +if [ -z "$CDPATH" ]; then + CDPATH="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/bookmarks" + [ -d "$CDPATH" ] || abort "CDPATH is not set and there is no \"$CDPATH\" directory" +fi + +dir_list=$(get_dirs) +[ -n "$dir_list" ] || abort "There are no directories to choose from. Check your \"$CDPATH\"." + +dir=$(echo "$dir_list" | fzf --nth=1 --delimiter=':' | awk -F: 'END { print $2 }') +if [ -n "$dir" ]; then + nnn_cd "$dir" 0 +fi diff --git a/config/nnn/plugins/chksum b/config/nnn/plugins/chksum @@ -0,0 +1,72 @@ +#!/usr/bin/env sh + +# Description: Create and verify checksums +# +# Details: +# - selection: it will generate one file with the checksums and filenames +# (and with paths if they are in another directory) +# output checksum filename format: checksum_timestamp.checksum_type +# - 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 +# - directory: recursively calculates checksum for all the files in the dir +# 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" + + # 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 + 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/config/nnn/plugins/cmusq b/config/nnn/plugins/cmusq @@ -0,0 +1,80 @@ +#!/usr/bin/env sh + +# Description: Add selection or hovered file/directory to cmus queue +# +# Dependencies: cmus, pgrep, xdotool (optional) +# +# Notes: +# 1. If adding selection, files/dirs are added in the same order they were selected in nnn +# 2. A new window will be opened if cmus is not running already, playback will start immediately +# 3. If cmus is already running, files will be appended to the queue with no forced playback +# +# TODO: +# 1. Add cava and cmus-lyrics as optional dependencies +# 2. Start cava and/or cmus-lyrics in tmux or kitty panes next to cmus +# +# Shell: POSIX compliant +# Author: Kabouik + +# (Optional) Set preferred terminal emulator for cmus if not set in your env, +# or leave commented out to use OS default +#TERMINAL="kitty" + +if ! type cmus >/dev/null; then + printf "cmus missing" + read -r _ + exit 1 +fi + +selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection} + +start_cmus() { + type xdotool >/dev/null && nnnwindow="$(xdotool getactivewindow)" + case "$TERMINAL" in + kitty | gnome-terminal | st) + nohup "$TERMINAL" -- cmus & ;; + havoc) + nohup "$TERMINAL" cmus & ;; + "") + nohup x-terminal-emulator -e cmus & ;; + *) + nohup "$TERMINAL" -e cmus & ;; + esac + # Give the new terminal some time to open + until cmus-remote -C; do sleep 0.1; done + [ -n "$nnnwindow" ] && xdotool windowactivate "$nnnwindow" +} >/dev/null 2>&1 + +fill_queue() { + if [ "$REPLY" = "s" ]; then + xargs < "$selection" -0 cmus-remote -q + elif [ -n "$1" ]; then + cmus-remote -q "$1" + fi +} + +# If active selection,then ask what to do +if [ -s "$selection" ]; then + printf "Queue [s]election or [c]urrently hovered? [default=c]: " + read -r REPLY +fi + +# If cmus is not running, start and play queue +if ! pgrep cmus >/dev/null; then + printf "cmus is not running, starting it in a new %s window.\n" "$TERMINAL" + start_cmus + fill_queue "$1" + cmus-remote -p + printf "Files added to cmus queue.\n" +else # Append to existing queue if cmus is already running + fill_queue "$1" + printf "Files appended to current cmus queue.\n" +fi + +# Change view +cmus-remote -C "view 4" + +# Clear selection +if [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" +fi diff --git a/config/nnn/plugins/diffs b/config/nnn/plugins/diffs @@ -0,0 +1,62 @@ +#!/usr/bin/env sh + +# Description: Show diff of 2 directories or multiple files in vimdiff +# +# Notes: +# 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 type 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 [ -n "$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 + +# Clear selection +if [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" +fi diff --git a/config/nnn/plugins/dragdrop b/config/nnn/plugins/dragdrop @@ -0,0 +1,75 @@ +#!/usr/bin/env sh + +# Description: Open a Drag and drop window, to drop files onto other programs. +# Also provides drag and drop window for files. +# +# Dependencies: dragon - https://github.com/mwh/dragon +# +# 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 +# +# Shell: POSIX compliant +# Author: 0xACE + +selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection} +resp=f +all= +if type dragon-drag-and-drop >/dev/null 2>&1; then + dnd="dragon-drag-and-drop" +else + dnd="dragon" +fi + +add_file () +{ + printf '%s\0' "$@" >> "$selection" +} + +use_all () +{ + printf "mark --all (a) [default=none]: " + read -r resp + if [ "$resp" = "a" ]; then + all="--all" + else + all="" + fi +} + +if [ -s "$selection" ]; then + printf "Drop file (r). Drag selection (s), Drag current directory (d) or drag current file (f) [default=f]: " + read -r resp +else + printf "Drop file (r). Drag current directory (d) or drag current file (f) [default=f]: " + read -r resp + if [ "$resp" = "s" ]; then + resp=f + fi +fi + +if [ "$resp" = "s" ]; then + use_all + sed -z 's|'"$PWD/"'||g' < "$selection" | xargs -0 "$dnd" "$all" & +elif [ "$resp" = "d" ]; then + use_all + "$dnd" "$all" "$PWD/"* & +elif [ "$resp" = "r" ]; then + true > "$selection" + "$dnd" --print-path --target | while read -r f + do + if printf "%s" "$f" | grep '^\(https\?\|ftps\?\|s\?ftp\):\/\/' ; then + curl -LJO "$f" + add_file "$PWD/$(basename "$f")" + elif [ -e "$f" ]; then + add_file "$f" + fi + done & +else + if [ -n "$1" ] && [ -e "$1" ]; then + "$dnd" "$1" & + fi +fi + diff --git a/config/nnn/plugins/dups b/config/nnn/plugins/dups @@ -0,0 +1,70 @@ +#!/usr/bin/env sh + +# Description: List non-empty duplicates in the current dir (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 +# +# Notes: +# 1. If the file size exceeds $size_digits digits the file will be misplaced +# 12 digits fit files up to 931GiB +# 2. Bash compatible required for mktemp +# +# Shell: Bash +# Authors: syssyphus, KlzXS + +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/config/nnn/plugins/finder b/config/nnn/plugins/finder @@ -0,0 +1,89 @@ +#!/usr/bin/env bash + +# Description: Run custom search and list results in smart context +# +# Note: This plugin retains search history +# +# Usage: +# Run plugin and enter e.g. "-size +10M" to list files in current +# directory larger than 10M. By default entered expressions are +# interpreted as arguments to find. Results have to be NUL +# terminated which is done by default for find. Alternatively one +# can prepend a '$' to run a custom search program such as fd or +# ripgrep. Entered expressions will be saved in history file to +# be listed as bookmarks and and can be entered by index and edited. +# +# Shell: Bash +# Author: Arun Prakash Jana, Luuk van Baal +TMPDIR="${TMPDIR:-/tmp}" +NNN_FINDHIST="${NNN_FINDHIST:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/finderbms}" +NNN_FINDHISTLEN="${NNN_FINDHISTLEN:-10000}" + +printexamples() { + printf -- "-maxdepth 1 -name pattern +-maxdepth 1 -size +100M +\$fd -0 pattern +\$fd -0 -d 2 -S +100M +\$grep -rlZ pattern +\$rg -l0 pattern +\$fzf -m | tr '\\\n' '\\\0'\n" +} + +printexprs() { + for ((i = "$1"; i < ${#fexprs[@]}; i++)); do + printf '%s\t%s\n' "$((i + 1))" "${fexprs[$i]}" + done +} + +mapexpr() { + if [ "$fexpr" -eq "$fexpr" ] 2>/dev/null; then + fexpr=${fexprs[$((fexpr - 1))]} + read -r -e -p "Search expression: " -i "$fexpr" fexpr + else + return 1 + fi +} + +readexpr() { + case "$fexpr" in + h) clear + printf "Examples:\n" + mapfile -t fexprs < <(printexamples) + printexprs 0 + read -r -p "Search expression or index: " fexpr + mapexpr + [ -n "$fexpr" ] && readexpr ;; + \$*) cmd="${fexpr:1}" ;; + *) mapexpr && readexpr + cmd="find $fexpr -print0" ;; + esac +} + +clear +[ -f "$NNN_FINDHIST" ] || printexamples > "$NNN_FINDHIST" + +mapfile -t fexprs < <(sort "$NNN_FINDHIST" | uniq -c | sort -nr | head -n5 |\ + awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}') +printf "Most used search expressions:\n" +printexprs 0 + +mapfile -t -O"$i" fexprs < <(tac "$NNN_FINDHIST" | awk '!a[$0]++' | head -n5) +printf "Most recently used search expressions:\n" +printexprs "$i" +read -r -p "Search expression or index (h for help): " fexpr + +mapexpr + +if [ -n "$fexpr" ]; then + printf "+l" > "$NNN_PIPE" + while :; do + readexpr + eval "$cmd" > "$NNN_PIPE" && break + read -r -e -p "Search expression: " -i "$fexpr" fexpr + done + if [ -n "$fexpr" ]; then + tail -n"$NNN_FINDHISTLEN" "$NNN_FINDHIST" > "$TMPDIR/finderbms" + printf "%s\n" "$fexpr" >> "$TMPDIR/finderbms" + mv "$TMPDIR/finderbms" "$NNN_FINDHIST" + fi +fi diff --git a/config/nnn/plugins/fixname b/config/nnn/plugins/fixname @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +# Description: Clean filename or dirname (either hovered or selections) +# to be more shell-friendly. This script cleans +# non A-Za-z0-9._- characters. +# and replaces it with underscore (_). +# +# It supports cleaning single/double quote, newline, +# leading, trailing spaces. +# +# eg. +# to be continued (つづく).mp4 -> to_be_continued______.mp4 +# [work] stuff.txt -> _work__stuff.txt +# home's server -> home_s_server +# qwe\trty -> __qwe_rty +# +# And if there are two almost similar filenames +# like: 'asd]f' and 'asd f' both will be renamed to 'asd_f', +# to avoid overwriting, the last file will be prepended by _. +# So they will be: 'asd_f' and '_asd_f' +# +# Dependencies: sed +# +# Shell: Bash +# Author: Benawi Adha + +prompt=true +sel=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection} + +cleanup() { + # printf "%s" "$1" | sed -e 's/[^A-Za-z0-9._-]/_/g' + printf "%s" "$1" | sed 's/[^A-Za-z0-9._-]/_/g' | sed ':a;N;$!ba;s/\n/_/g' +} + +if [ -s "$sel" ]; then + targets=() + while IFS= read -r -d '' i || [ -n "$i" ]; do + targets+=( "$(basename "$i")" ) + done < "$sel" +else + targets=("$1") +fi + +for i in "${targets[@]}"; do + printf "%s -> %s\n" "$i" "$(cleanup "$i")"; +done + +if $prompt; then + echo + printf "Proceed [Yn]? " + read -r input + case "$input" in + y|Y|'') + ;; + *) + echo "Canceled" + exit + ;; + esac +fi + +for i in "${targets[@]}"; do + if [ "$i" != "$(cleanup "$i")" ]; then + tmp='' + if [ -e "$(cleanup "$i")" ]; then + tmp='_' + fi + mv "$i" "$tmp$(cleanup "$i")"; + fi +done + +# Clear selection +if [ -s "$sel" ] && [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" +fi diff --git a/config/nnn/plugins/fzcd b/config/nnn/plugins/fzcd @@ -0,0 +1,88 @@ +#!/usr/bin/env sh + +# Description: Fuzzy search multiple locations read-in from a path-list file +# (or $PWD) and open the selected file's dir in a smart context. +# Dependencies: fzf, find (only for multi-location search) +# +# Details: Paths in list file should be newline-separated absolute paths. +# Paths can be file paths; the script will scan the parent dirs. +# +# The path-list file precedence is: +# - "$1" (the hovered file) if it exists, is plain-text and the +# first line points to an existing file +# - "$LIST" if set below +# - "$2" (the current directory) [mimics plugin fzcd behaviour] +# +# The path-list file can be generated easily: +# - pick the (file)paths in picker mode to path-list file +# - OR, edit selection in nnn and save as path-list file +# +# Shell: POSIX compliant +# Author: Anna Arad, Arun Prakash Jana, KlzXS + +IFS="$(printf '\n\r')" + +. "$(dirname "$0")"/.nnn-plugin-helper + +CTX=+ +LIST="$LIST" + +if ! type fzf >/dev/null 2>&1; then + printf "fzf missing" + read -r _ + exit 1 +fi + +if [ -n "$1" ] && [ "$(file -b --mime-type "$1")" = 'text/plain' ] && [ -e "$(head -1 "$1")" ]; then + LIST="$1" +elif ! [ -s "$LIST" ]; then + sel=$(fzf) + # Show only the file and parent dir + # sel=$(fzf --delimiter / --with-nth=-2,-1 --tiebreak=begin --info=hidden) + + LIST='' +fi + +if [ -n "$LIST" ]; then + if type find >/dev/null 2>&1; then + tmpfile=$(mktemp /tmp/abc-script.XXXXXX) + + while IFS= read -r path; do + if [ -d "$path" ]; then + printf "%s\n" "$path" >> "$tmpfile" + elif [ -f "$path" ]; then + printf "%s\n" "$(dirname "$path")" >> "$tmpfile" + fi + done < "$LIST" + + sel=$(xargs -d '\n' -a "$tmpfile" -I{} find {} -type f -printf "%H//%P\n" | sed '/.*\/\/\(\..*\|.*\/\..*\)/d; s:/\+:/:g' | fzf --delimiter / --tiebreak=begin --info=hidden) + # Alternative for 'fd' + # sel=$(xargs -d '\n' -a "$tmpfile" fd . | fzf --delimiter / --tiebreak=begin --info=hidden) + + rm "$tmpfile" + else + printf "find missing" + read -r _ + exit 1 + fi +fi + +if [ -n "$sel" ]; then + if [ "$sel" = "." ] || { ! [ -d "$sel" ] && ! [ -f "$sel" ]; }; then + exit 0 + fi + + # Check if the selected path returned by fzf command is absolute + case $sel in + /*) nnn_cd "$sel" "$CTX" ;; + *) + # Remove "./" prefix if it exists + sel="${sel#./}" + + if [ "$PWD" = "/" ]; then + nnn_cd "/$sel" "$CTX" + else + nnn_cd "$PWD/$sel" "$CTX" + fi;; + esac +fi diff --git a/config/nnn/plugins/fzhist b/config/nnn/plugins/fzhist @@ -0,0 +1,40 @@ +#!/usr/bin/env sh + +# Description: Fuzzy find a command from history, +# edit in $EDITOR and run as a command +# +# Note: Supports only bash and fish history +# +# Shell: POSIX compliant +# Author: Arun Prakash Jana + +if type 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/.local/share/fish/fish_history" + entry="$(grep "\- cmd: " "$hist_file" | cut -c 8- | "$fuzzy")" +fi + +if [ -n "$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/config/nnn/plugins/fzopen b/config/nnn/plugins/fzopen @@ -0,0 +1,82 @@ +#!/usr/bin/env sh + +# Description: Regular mode: +# Fuzzy find a file in directory subtree. +# Opens in $VISUAL or $EDITOR if text. +# Opens other type of files with xdg-open. +# Work only with a single file selected. +# +# Picker mode: +# If picker mode output file is passed, it +# will be overwritten with any picked files. +# Leaves untouched if no file is picked. +# Works with single/multiple files selected. +# +# Dependencies: fd/find, fzf/skim, xdg-open/open (on macOS) +# +# Shell: POSIX compliant +# Author: Arun Prakash Jana + +NUKE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins/nuke" +USE_NUKE=0 + +. "$(dirname "$0")"/.nnn-plugin-helper + +if type fzf >/dev/null 2>&1; then + cmd="$FZF_DEFAULT_COMMAND" + if type 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 -m)" + # To show only the file name + # entry=$(find . -type f 2>/dev/null | fzf --delimiter / --with-nth=-1 --tiebreak=begin --info=hidden) +elif type sk >/dev/null 2>&1; then + entry=$(find . -type f 2>/dev/null | sk) +else + exit 1 +fi + +# Check for picker mode +if [ "$3" ]; then + if [ "$entry" ]; then + case "$entry" in + /*) fullpath="$entry" ;; + *) fullpath="$PWD/$entry" ;; + esac + if [ "-" = "$3" ]; then + printf "%s\n" "$fullpath" + else + printf "%s\n" "$fullpath" > "$3" + fi + + # Tell `nnn` to clear its internal selection + printf "%s" "0p" > "$NNN_PIPE" + fi + + exit 0 +fi + +if [ "$USE_NUKE" -ne 0 ]; then + "$NUKE" "$entry" + exit 0 +fi + +# Open the file (works for a single file only) +cmd_file="" +cmd_open="" +if uname | grep -q "Darwin"; then + cmd_file="file -bIL" + cmd_open="open" +else + cmd_file="file -biL" + cmd_open="xdg-open" +fi + +case "$($cmd_file "$entry")" in + *text*) + "${VISUAL:-$EDITOR}" "$entry" ;; + *) + $cmd_open "$entry" >/dev/null 2>&1 ;; +esac diff --git a/config/nnn/plugins/fzplug b/config/nnn/plugins/fzplug @@ -0,0 +1,59 @@ +#!/usr/bin/env sh + +# Description: Fuzzy find and execute nnn plugins (and optionally, +# custom scripts located elsewhere). +# Description and details of plugins can be previewed +# from the fzf interface. Use `?` to toggle preview +# pane on and off, ^Up/^Dn to scroll. +# +# Dependencies: find, fzf, cat (or bat, if installed) +# +# Note: For better compatibility with as many nnn plugins as possible, +# fzplug will first execute the chosen script on the file hovered +# in nnn, and upon failure, try to run it with no target (i.e on +# an active selection, if present). +# +# Shell: POSIX compliant +# Author: Kabouik + +# Optional scripts sources + +# Leave blank or fill with the absolute path of a folder containing executable +# scripts other than nnn plugins (e.g., "$HOME/.local/share/nautilus/scripts", +# since there are numerous Nautilus script git repositories). +# Add extra variables if needed, make sure you call them in the find command. + +#CUSTOMDIR1="$HOME/.local/share/nautilus/scripts" +CUSTOMDIR1="" +CUSTOMDIR2="" + +nnnpluginsdir="$HOME/.config/nnn/plugins" + +# Preview with bat if installed +if type bat >/dev/null; then + BAT="bat --terminal-width='$(tput cols)' --decorations=always --color=always --style='${BAT_STYLE:-header,numbers}'" +fi + +plugin=$(find "$nnnpluginsdir" "$CUSTOMDIR1" "$CUSTOMDIR2" \ +-maxdepth 3 -perm -111 -type f 2>/dev/null | fzf --ansi --preview \ + "${BAT:-cat} {}" --preview-window="right:66%:wrap" --delimiter / \ + --with-nth -1 --bind="?:toggle-preview") + +# Try running the script on the hovered file, and abort +# abort if no plugin was selected (ESC or ^C pressed). +err=0 +if ! [ "$plugin" = "" ]; then + "$plugin" "$1" || err=1 +fi + +# If attempt with hovered file fails, try without any target +# (nnn selections should still be passed to the script in that case) +if [ "$err" -eq "1" ]; then + clear && "$plugin" || err=2 +fi + +# Abort and show error if both fail +if [ "$err" -eq "2" ]; then + sep="\n---\n" + printf "$sep""Failed to execute '%s'. See error above or try without fzfplug. Press return to continue. " "$plugin" && read -r _ && clear +fi diff --git a/config/nnn/plugins/getplugs b/config/nnn/plugins/getplugs @@ -0,0 +1,70 @@ +#!/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 + +merge () { + if type 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 [ "$1" = "master" ] ; then + VER="master" + ARCHIVE_URL=https://github.com/jarun/nnn/archive/master.tar.gz +elif type 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/config/nnn/plugins/gpgd b/config/nnn/plugins/gpgd @@ -0,0 +1,28 @@ +#!/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" {} + +# Clear selection +if [ "$resp" = "s" ] && [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" +fi diff --git a/config/nnn/plugins/gpge b/config/nnn/plugins/gpge @@ -0,0 +1,44 @@ +#!/usr/bin/env sh + +# Description: Encrypts selected files using gpg. Can encrypt +# 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" + + # Clear selection + if [ "$resp" = "s" ] && [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" + fi +fi diff --git a/config/nnn/plugins/gutenread b/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 download 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="https://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 "https://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/config/nnn/plugins/imgresize b/config/nnn/plugins/imgresize @@ -0,0 +1,31 @@ +#!/usr/bin/env sh + +# Description: Resize images in a directory to screen resolution with imgp +# +# Dependencipes: imgp - https://github.com/jarun/imgp +# +# Notes: +# 1. Set res to avoid the desktop resolution prompt each 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 [ -n "$res" ] && [ -n "$MINSIZE" ]; then + imgp -ackx "$res" -s "$MINSIZE" +fi diff --git a/config/nnn/plugins/imgur b/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://help.imgur.com/hc/en-us/articles/209592766-Tools-for-Imgur +# +# 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 + (type grep &>/dev/null && echo "OK: found grep") || echo "ERROR: grep not found" + if is_mac; then + if type growlnotify &>/dev/null; then + echo "OK: found growlnotify" + elif type terminal-notifier &>/dev/null; then + echo "OK: found terminal-notifier" + else + echo "ERROR: growlnotify nor terminal-notifier found" + fi + (type screencapture &>/dev/null && echo "OK: found screencapture") || echo "ERROR: screencapture not found" + (type pbcopy &>/dev/null && echo "OK: found pbcopy") || echo "ERROR: pbcopy not found" + else + (type notify-send &>/dev/null && echo "OK: found notify-send") || echo "ERROR: notify-send (from libnotify-bin) not found" + (type scrot &>/dev/null && echo "OK: found scrot") || echo "ERROR: scrot not found" + (type xclip &>/dev/null && echo "OK: found xclip") || echo "ERROR: xclip not found" + fi + (type 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 type 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 [ -n "$remote_version" ]; then + if [ ! "${current_version}" = "${remote_version}" ] && [ -n "${current_version}" ] && [ -n "${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 [ -n "${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 [ -n "${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 [ -n "${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 "https://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/config/nnn/plugins/imgview b/config/nnn/plugins/imgview @@ -0,0 +1,111 @@ +#!/usr/bin/env sh + +# Description: Open hovered or current directory in image viewer. +# Generates media thumbnails with optional dependencies. +# +# Dependencies: +# - imv (https://github.com/eXeC64/imv) or, +# - sxiv (https://github.com/muennich/sxiv) or, +# - nsxiv (https://github.com/nsxiv/nsxiv) or, +# - ucollage (https://github.com/ckardaris/ucollage) or, +# - lsix (https://github.com/hackerb9/lsix), or +# - viu (https://github.com/atanunq/viu), or +# - catimg (https://github.com/posva/catimg), or +# - optional: ffmpeg for audio thumbnails (album art) +# - optional: ffmpegthumbnailer for video thumbnails +# +# Shell: POSIX compliant +# Author: Arun Prakash Jana, Luuk van Baal +# +# Consider setting NNN_PREVIEWDIR to $XDG_CACHE_HOME/nnn/previews +# if you want to keep media thumbnails on disk between reboots. +NNN_PREVIEWDIR="${NNN_PREVIEWDIR:-${TMPDIR:-/tmp}/nnn/previews}" + +exit_prompt() { + [ -n "$1" ] && printf "%s\n" "$1" + printf "%s" "Press any key to exit..." + cfg=$(stty -g); stty raw -echo; head -c 1; stty "$cfg" + clear + exit +} + +make_thumbs() { + mkdir -p "$NNN_PREVIEWDIR$dir" || return + if [ "$1" -eq 3 ]; then + [ -d "$target" ] && exit_prompt "$2 can only display a single image" + mime="$(file -bL --mime-type -- "$target")" + case "$mime" in + audio/*) ffmpeg -i "$target" "$NNN_PREVIEWDIR$target.jpg" -y >/dev/null 2>&1 + ret="$NNN_PREVIEWDIR/$target.jpg" ;; + video/*) ffmpegthumbnailer -i "$target" -o "$NNN_PREVIEWDIR$target.jpg" 2> /dev/null + ret="$NNN_PREVIEWDIR/$target.jpg" ;; + *) ret="$target" ;; + esac + fi + for file in "$dir"/*; do + if [ ! -f "$NNN_PREVIEWDIR$file.jpg" ]; then + case "$(file -bL --mime-type -- "$file")" in + audio/*) [ "$1" -ne 0 ] && ffmpeg -i "$file" "$NNN_PREVIEWDIR$file.jpg" -y >/dev/null 2>&1 ;; + video/*) [ "$1" -ne 1 ] && ffmpegthumbnailer -i "$file" -o "$NNN_PREVIEWDIR$file.jpg" 2> /dev/null ;; + esac + fi + done + for file in "$NNN_PREVIEWDIR$dir"/*; do + filename="$(basename "$file" .jpg)" + [ ! -e "$dir/$filename" ] && rm "$file" 2>/dev/null + done +} + +listimages() { + find -L "$dir" "$NNN_PREVIEWDIR$dir" -maxdepth 1 -type f -print0 2>/dev/null | sort -z +} + +view_files() { + [ -f "$target" ] && count="-n $(listimages | grep -a -m 1 -ZznF "$target" | cut -d: -f1)" + case "$1" in + nsxiv) listimages | xargs -0 nsxiv -a "${count:--t}" -- ;; + sxiv) listimages | xargs -0 sxiv -a "${count:--t}" -- ;; + imv*) listimages | xargs -0 "$1" "${count:-}" -- ;; + esac +} + +target="$(readlink -f "$1")" +[ -d "$target" ] && dir="$target" || dir="${target%/*}" +if uname | grep -q "Darwin"; then + [ -f "$1" ] && open "$1" >/dev/null 2>&1 & +elif type lsix >/dev/null 2>&1; then + if [ -d "$target" ]; then + cd "$target" || exit_prompt + fi + make_thumbs "" + clear + lsix + cd "$NNN_PREVIEWDIR$dir" && lsix + exit_prompt +elif type ucollage >/dev/null 2>&1; then + type ffmpeg >/dev/null 2>&1 && make_thumbs 1 + UCOLLAGE_EXPAND_DIRS=1 ucollage "$dir" "$NNN_PREVIEWDIR$dir" || exit_prompt +elif type sxiv >/dev/null 2>&1; then + type ffmpegthumbnailer >/dev/null 2>&1 && make_thumbs 0 + view_files sxiv >/dev/null 2>&1 & +elif type nsxiv >/dev/null 2>&1; then + type ffmpegthumbnailer >/dev/null 2>&1 && make_thumbs 0 + view_files nsxiv >/dev/null 2>&1 & +elif type imv >/dev/null 2>&1; then + make_thumbs "" + view_files imv >/dev/null 2>&1 & +elif type imvr >/dev/null 2>&1; then + make_thumbs "" + view_files imvr >/dev/null 2>&1 & +elif type viu >/dev/null 2>&1; then + clear + make_thumbs 3 viu + viu -n "$ret" + exit_prompt +elif type catimg >/dev/null 2>&1; then + make_thumbs 3 catimg + catimg "$ret" + exit_prompt +else + exit_prompt "Please install sxiv/nsxiv/imv/viu/catimg/lsix." +fi diff --git a/config/nnn/plugins/ipinfo b/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/config/nnn/plugins/kdeconnect b/config/nnn/plugins/kdeconnect @@ -0,0 +1,24 @@ +#!/usr/bin/env sh + +# Description: Send the selected files to your Android device using kdeconnect-cli. +# kdeconnect must be configured on the Android device and 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 [ -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/config/nnn/plugins/launch b/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 type 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 [ -n "$1" ]; then + sleep "$1" + else + sleep 1 + fi +fi diff --git a/config/nnn/plugins/mimelist b/config/nnn/plugins/mimelist @@ -0,0 +1,14 @@ +#!/usr/bin/env sh + +# Description: Find and list files by mime type in smart context +# +# Shell: POSIX compliant +# Author: Arun Prakash Jana + +. "$(dirname "$0")"/.nnn-plugin-helper + +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" diff --git a/config/nnn/plugins/moclyrics b/config/nnn/plugins/moclyrics @@ -0,0 +1,40 @@ +#!/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 [ -n "$ARTIST" ] && [ -n "$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 [ -n "$FILENAME" ]; then + ddgr -w azlyrics.com --ducky "$FILENAME" + fi +fi diff --git a/config/nnn/plugins/mocq b/config/nnn/plugins/mocq @@ -0,0 +1,89 @@ +#!/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 + +# Clear selection +if [ "$resp" = "y" ] && [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" +fi diff --git a/config/nnn/plugins/mp3conv b/config/nnn/plugins/mp3conv @@ -0,0 +1,41 @@ +#!/usr/bin/env sh + +# Description: Extract audio from multimedia files and convert to mp3 +# +# Dependencies: 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/config/nnn/plugins/mtpmount b/config/nnn/plugins/mtpmount @@ -0,0 +1,76 @@ +#!/usr/bin/env sh + +# Description: Toggle mount of MTP device (eg. Android device) +# 'l' to list mountable devices +# 'n' integer associated to device to mount +# 'q'/'Return' exit +# +# Dependencies: gvfs-mtp +# +# Notes: The MTP device should be mounted at /run/user/$UID/gvfs. +# Put /run/user/$UID/gvfs to bookmark entries (NNN_BMS) for faster access. +# Make sure the device is unlocked when mounting. +# +# When doing copy-paste into MTP device, you will get an error like this: +# cp: preserving times for './gambar1.png': Operation not supported +# That just means the file is copied but timestamp won't be preserved. +# It's like doing `cp -p localfile.txt file-to-SMB.txt`. +# +# Shell: POSIX compliant +# Author: Benawi Adha + +prompt="Device number ('l' to list): " + +IFS=' +' + +lsmtp () { + devs=$(gio mount -li | grep -e 'activation_root' | sed 's/\s*activation_root=//g') + c=1 + printf "Devices list:\n" + for i in $devs; do + printf "%s %s\\n" "$c" "$i" + c=$(( c + 1 )) + done + echo +} + +lsmtp +printf "%s" "$prompt" +read -r input + +while [ -n "$input" ] +do + if [ "$input" = "l" ]; then + lsmtp + elif [ "$input" = "q" ] || [ "$input" -eq 0 ]; then + exit + elif [ "$input" -le "$(printf '%s\n' "${devs}" | grep -c '^')" ]; then + # dev=$(printf "%s\n" "$devs" | cut -d$'\n' -f${input}) + c=1 + for i in $devs; do + dev=$i + if [ "$input" -eq $c ]; then + break + fi + c=$(( c + 1 )) + done + + if (gio mount -l | grep '^Mount([1-9]).*'"$dev" ) 1>/dev/null; then + if gio mount -u "${dev}"; then + printf "%s unmounted\n" "$dev" + fi + else + if gio mount "${dev}"; then + printf "%s mounted to /run/user/\$UID/gvfs\n" "$dev" + fi + fi + echo + else + printf "Invalid input\n" + fi + + printf "%s" "$prompt" + read -r input +done + diff --git a/config/nnn/plugins/nbak b/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/config/nnn/plugins/nmount b/config/nnn/plugins/nmount @@ -0,0 +1,55 @@ +#!/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. +# +# Dependencies: lsblk, pmount +# +# Usage: Runs `lsblk` on 'l', exits on 'Return`. +# +# Notes: +# - 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 power 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 [e.g. sdXn] ('l'ist, 'q'uit): " + +lsblk + +printf "\nEnsure you aren't still in the mounted device.\n" +printf "%s" "$prompt" +read -r dev + +while [ -n "$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/config/nnn/plugins/nuke b/config/nnn/plugins/nuke @@ -0,0 +1,558 @@ +#!/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. mocq 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: +# 1. by extension +# 2. by mime (image, video, audio, pdf) +# 3. by mime (other file types) +# 4. by mime (prompt and run executables) +# +# 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: mocq (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/nsxiv (GUI), viu (https://github.com/atanunq/viu), img2txt, exiftool +# video/*: smplayer, mpv (GUI), ffmpegthumbnailer, mediainfo, exiftool +# audio/*: mocq (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 and/or BIN execution +GUI="${GUI:-0}" +BIN="${BIN:-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="${VISUAL:-${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 ]; then + if is_mac; then + nohup open "${FPATH}" >/dev/null 2>&1 & + elif type zathura >/dev/null 2>&1; then + nohup zathura "${FPATH}" >/dev/null 2>&1 & + else + return + fi + + elif type zathura >/dev/null 2>&1; then + nohup zathura "${FPATH}" >/dev/null 2>&1 & + elif type pdftotext >/dev/null 2>&1; then + ## Preview as text conversion + pdftotext -l 10 -nopgbrk -q -- "${FPATH}" - | eval "$PAGER" + elif type mutool >/dev/null 2>&1; then + mutool draw -F txt -i -- "${FPATH}" 1-10 | eval "$PAGER" + elif type exiftool >/dev/null 2>&1; then + exiftool "${FPATH}" | eval "$PAGER" + else + return + fi + exit 0 +} + +handle_audio() { + if type mocp >/dev/null 2>&1 && type mocq >/dev/null 2>&1; then + mocq "${FPATH}" "opener" >/dev/null 2>&1 + elif type mpv >/dev/null 2>&1; then + mpv "${FPATH}" >/dev/null 2>&1 & + elif type media_client >/dev/null 2>&1; then + media_client play "${FPATH}" >/dev/null 2>&1 & + elif type mediainfo >/dev/null 2>&1; then + mediainfo "${FPATH}" | eval "$PAGER" + elif type exiftool >/dev/null 2>&1; then + exiftool "${FPATH}"| eval "$PAGER" + else + return + fi + exit 0 +} + +handle_video() { + mpv "${FPATH}" >/dev/null 2>&1 & + if [ "$GUI" -ne 0 ]; then + echo "COUSA" + mpv "${FPATH}" >/dev/null 2>&1 & + #if is_mac; then + # nohup open "${FPATH}" >/dev/null 2>&1 & + #elif type smplayer >/dev/null 2>&1; then + # nohup smplayer "${FPATH}" >/dev/null 2>&1 & + #elif type mpv >/dev/null 2>&1; then + # mpv "${FPATH}" >/dev/null 2>&1 & + #else + # return + #fi + elif type 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" + elif type mediainfo >/dev/null 2>&1; then + mediainfo "${FPATH}" | eval "$PAGER" + elif type exiftool >/dev/null 2>&1; then + exiftool "${FPATH}"| eval "$PAGER" + else + return + fi + exit 0 +} + +# 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 type atool >/dev/null 2>&1; then + atool --list -- "${FPATH}" | eval "$PAGER" + exit 0 + elif type bsdtar >/dev/null 2>&1; then + bsdtar --list --file "${FPATH}" | eval "$PAGER" + exit 0 + fi + exit 1;; + rar) + if type unrar >/dev/null 2>&1; then + ## Avoid password prompt by providing empty password + unrar lt -p- -- "${FPATH}" | eval "$PAGER" + fi + exit 1;; + 7z) + if type 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 type rtorrent >/dev/null 2>&1; then + rtorrent "${FPATH}" + exit 0 + elif type transmission-show >/dev/null 2>&1; then + transmission-show -- "${FPATH}" + exit 0 + fi + exit 1;; + + ## OpenDocument + odt|ods|odp|sxw) + if type odt2txt >/dev/null 2>&1; then + ## Preview as text conversion + odt2txt "${FPATH}" | eval "$PAGER" + exit 0 + fi + exit 1;; + + ## Markdown + md) + if type glow >/dev/null 2>&1; then + glow -sdark "${FPATH}" | eval "$PAGER" + exit 0 + elif type lowdown >/dev/null 2>&1; then + lowdown -Tterm "${FPATH}" | eval "$PAGER" + exit 0 + fi + ;; + + ## HTML + htm|html|xhtml) + ## Preview as text conversion + if type w3m >/dev/null 2>&1; then + w3m -dump "${FPATH}" | eval "$PAGER" + exit 0 + elif type lynx >/dev/null 2>&1; then + lynx -dump -- "${FPATH}" | eval "$PAGER" + exit 0 + elif type elinks >/dev/null 2>&1; then + elinks -dump "${FPATH}" | eval "$PAGER" + exit 0 + fi + ;; + + ## JSON + json) + if type jq >/dev/null 2>&1; then + jq --color-output . "${FPATH}" | eval "$PAGER" + exit 0 + elif type python >/dev/null 2>&1; then + python -m json.tool -- "${FPATH}" | eval "$PAGER" + exit 0 + fi + ;; + esac +} + +# sets the variable abs_target, this should be faster than calling printf +abspath() { + case "$1" in + /*) abs_target="$1";; + *) abs_target="$PWD/$1";; + esac +} + +# storing the result to a tmp file is faster than calling listimages twice +listimages() { + find -L "///${1%/*}" -maxdepth 1 -type f -print0 | + grep -izZE '\.(jpe?g|png|gif|webp|tiff|bmp|ico|svg)$' | + sort -z | tee "$tmp" +} + +load_dir() { + abspath "$2" + tmp="${TMPDIR:-/tmp}/nuke_$$" + trap 'rm -f $tmp' EXIT + count="$(listimages "$abs_target" | grep -a -m 1 -ZznF "$abs_target" | cut -d: -f1)" + + if [ -n "$count" ]; then + if [ "$GUI" -ne 0 ]; then + xargs -0 nohup "$1" -n "$count" -- < "$tmp" + else + xargs -0 "$1" -n "$count" -- < "$tmp" + fi + 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 ]; then + if is_mac; then + nohup open "${FPATH}" >/dev/null 2>&1 & + exit 0 + elif type imvr >/dev/null 2>&1; then + load_dir imvr "${FPATH}" >/dev/null 2>&1 & + exit 0 + elif type sxiv >/dev/null 2>&1; then + load_dir sxiv "${FPATH}" >/dev/null 2>&1 & + exit 0 + elif type nsxiv >/dev/null 2>&1; then + load_dir nsxiv "${FPATH}" >/dev/null 2>&1 & + exit 0 + fi + elif type sxiv >/dev/null 2>&1; then + sxiv "${FPATH}" | eval "$PAGER" + exit 0 + elif type img2txt >/dev/null 2>&1; then + img2txt --gamma=0.6 -- "${FPATH}" | eval "$PAGER" + exit 0 + elif type 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 type djvutxt >/dev/null 2>&1; then + ## Preview as text conversion (requires djvulibre) + djvutxt "${FPATH}" | eval "$PAGER" + exit 0 + elif type exiftool >/dev/null 2>&1; then + exiftool "${FPATH}" | eval "$PAGER" + exit 0 + fi + exit 1;; + esac +} + +handle_fallback() { + if [ "$GUI" -ne 0 ]; then + if type xdg-open >/dev/null 2>&1; then + nohup xdg-open "${FPATH}" >/dev/null 2>&1 & + exit 0 + elif type open >/dev/null 2>&1; then + nohup open "${FPATH}" >/dev/null 2>&1 & + exit 0 + fi + 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 +} + +handle_bin() { + case "${MIMETYPE}" in + application/x-executable|application/x-shellscript) + clear + echo '-------- Executable File --------' && file --dereference --brief -- "${FPATH}" + printf "Run executable (y/N/'a'rgs)? " + read -r answer + case "$answer" in + [Yy]* ) exec "${FPATH}";; + [Aa]* ) + printf "args: " + read -r args + exec "${FPATH}" "$args";; + [Nn]* ) exit;; + esac + esac +} + +MIMETYPE="$( file -bL --mime-type -- "${FPATH}" )" +handle_extension +handle_multimedia "${MIMETYPE}" +handle_mime "${MIMETYPE}" +[ "$BIN" -ne 0 ] && [ -x "${FPATH}" ] && handle_bin +handle_blocked "${MIMETYPE}" +handle_fallback + +exit 1 diff --git a/config/nnn/plugins/oldbigfile b/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/config/nnn/plugins/organize b/config/nnn/plugins/organize @@ -0,0 +1,62 @@ +#!/usr/bin/env sh + +# 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*) + [ ! -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 + + # Clear selection + if [ -s "$sel" ] && [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" + fi +} + +main "$@" diff --git a/config/nnn/plugins/pdfread b/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 [ -n "$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/config/nnn/plugins/preview-tabbed b/config/nnn/plugins/preview-tabbed @@ -0,0 +1,211 @@ +#!/usr/bin/env bash + +# Description: tabbed/xembed based file previewer +# +# 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) or, +# - nsxiv (https://github.com/nsxiv/nsxiv) : xembed client for images +# - zathura (https://pwmt.org/projects/zathura): xembed client for PDF +# - nnn's nuke plugin for text preview and fallback +# nuke is a fallback for 'mpv', 'sxiv'/'nsxiv', and 'zathura', but has its +# own dependencies, see the script for more information +# - vim (or any editor/pager really) +# - file +# - mktemp +# - xdotool (optional, to keep main window focused) +# +# Usage: +# - Install the dependencies. Then set a NNN_FIFO +# and set a key for the plugin, then start `nnn`: +# $ NNN_FIFO=/tmp/nnn.fifo nnn +# - Launch the plugin with the designated key from nnn +# +# Notes: +# 1. This plugin needs a "NNN_FIFO" to work. See man. +# 2. If the same NNN_FIFO is used in multiple nnn instances, there will be one +# common preview window. With different FIFO paths, 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`/`nsxiv`: image viewer +# - `zathura`: PDF viewer +# - but we always fallback to `nuke` plugin +# +# [1]: https://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 type xterm >/dev/null 2>&1 ; then + TERMINAL="xterm -into" +elif type urxvt >/dev/null 2>&1 ; then + TERMINAL="urxvt -embed" +elif type 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 -bL --mime-type "$FILE")" + + case "$MIME" in + video/*) + if type mpv >/dev/null 2>&1 ; then + mpv --force-window=immediate --loop-file --wid="$XID" "$FILE" & + else + term_nuke "$XID" "$FILE" + fi + ;; + audio/*) + if type mpv >/dev/null 2>&1 ; then + mpv --force-window=immediate --loop-file --wid="$XID" "$FILE" & + else + term_nuke "$XID" "$FILE" + fi + ;; + image/*) + if type sxiv >/dev/null 2>&1 ; then + sxiv -ae "$XID" "$FILE" & + elif type nsxiv >/dev/null 2>&1 ; then + nsxiv -ae "$XID" "$FILE" & + else + term_nuke "$XID" "$FILE" + fi + ;; + application/pdf) + if type 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" #Aqui estaba term_nuke + else + # shellcheck disable=SC2086 + $TERMINAL "$XID" -e $PAGER "$FILE" & + fi + ;; + *) + if [ -x "$NUKE" ] ; then + term_nuke "$XID" "$FILE" # Aqui tamen estaba term_nuke + 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/config/nnn/plugins/preview-tui b/config/nnn/plugins/preview-tui @@ -0,0 +1,455 @@ +#!/usr/bin/env sh + +# Description: Terminal based file previewer +# +# Note: This plugin needs a "NNN_FIFO" to work. See man. +# +# Dependencies: +# - Supports 4 independent methods to preview with: +# - tmux (>=3.0), or +# - kitty with allow_remote_control and listen_on set in kitty.conf, or +# - QuickLook on WSL (https://github.com/QL-Win/QuickLook) +# - $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: bsdtar or atool for additional archive preview +# - optional: bat for code syntax highlighting +# - optional: ueberzug, kitty terminal, viu or catimg for images +# - optional: convert(ImageMagick) for playing gif preview +# - optional: ffmpegthumbnailer for video thumbnails (https://github.com/dirkvdb/ffmpegthumbnailer) +# - optional: ffmpeg for audio thumbnails +# - optional: libreoffce for opendocument/officedocument preview +# - optional: pdftoppm(poppler) for pdf thumbnails +# - optional: gnome-epub-thumbnailer for epub thumbnails (https://gitlab.gnome.org/GNOME/gnome-epub-thumbnailer) +# - optional: fontpreview for font preview (https://github.com/sdushantha/fontpreview) +# - optional: glow or lowdown for markdown +# - optional: w3m or lynx or elinks for html +# - optional: set/export ICONLOOKUP as 1 to enable file icons in front of directory previews with .iconlookup +# Icons and colors are configureable in .iconlookup +# - optional: scope.sh file viewer from ranger. +# 1. drop scope.sh executable in $PATH +# 2. set/export $USE_SCOPE as 1 +# - optional: pistol file viewer (https://github.com/doronbehar/pistol). +# 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 launch the `preview-tui` plugin in `nnn`. +# +# 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`, and `listen_on` set +# to e.g. "unix:$TMPDIR/kitty". 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. +# +# Iterm2 users are recommended to use viu to view images without getting pixelated. +# +# Shell: POSIX compliant +# Authors: Todd Yamakawa, Léo Villeveygoux, @Recidiviste, Mario Ortiz Manero, Luuk van Baal + +#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}" +ICONLOOKUP="${ICONLOOKUP:-0}" +PAGER="${PAGER:-less -P?n -R}" +TMPDIR="${TMPDIR:-/tmp}" +BAT_STYLE="${BAT_STYLE:-numbers}" +BAT_THEME="${BAT_THEME:-ansi}" +# Consider setting NNN_PREVIEWDIR to $XDG_CACHE_HOME/nnn/previews if you want to keep previews on disk between reboots +NNN_PREVIEWDIR="${NNN_PREVIEWDIR:-$TMPDIR/nnn/previews}" +NNN_PREVIEWWIDTH="${NNN_PREVIEWWIDTH:-1920}" +NNN_PREVIEWHEIGHT="${NNN_PREVIEWHEIGHT:-1080}" +NNN_PARENT="${NNN_FIFO#*.}" +[ "$NNN_PARENT" -eq "$NNN_PARENT" ] 2>/dev/null || NNN_PARENT="" +FIFOPID="$TMPDIR/nnn-preview-tui-fifopid.$NNN_PARENT" +PREVIEWPID="$TMPDIR/nnn-preview-tui-pagerpid.$NNN_PARENT" +CURSEL="$TMPDIR/nnn-preview-tui-selection.$NNN_PARENT" +FIFO_UEBERZUG="$TMPDIR/nnn-preview-tui-ueberzug-fifo.$NNN_PARENT" + +start_preview() { + [ "$PAGER" = "most" ] && PAGER="less -R" + + if [ -e "${TMUX%%,*}" ] && tmux -V | grep -q '[ -][3456789]\.'; then + TERMINAL=tmux + elif [ -n "$KITTY_LISTEN_ON" ]; then + TERMINAL=kitty + elif [ -z "$TERMINAL" ] && [ "$TERM_PROGRAM" = "iTerm.app" ]; then + TERMINAL=iterm + else + TERMINAL="${TERMINAL:-xterm}" + fi + + if [ -z "$SPLIT" ] && [ $(($(tput lines <"$TTY") * 2)) -gt "$(tput cols <"$TTY")" ]; then + SPLIT='h' + elif [ "$SPLIT" != 'h' ]; then + SPLIT='v' + fi + + case "$TERMINAL" in + tmux) # tmux splits are inverted + if [ "$SPLIT" = "v" ]; then DSPLIT="h"; else DSPLIT="v"; fi + tmux split-window -e "NNN_FIFO=$NNN_FIFO" -e "PREVIEW_MODE=1" -e TTY="$TTY" \ + -e "CURSEL=$CURSEL" -e "TMPDIR=$TMPDIR" -e "FIFOPID=$FIFOPID" \ + -e "BAT_STYLE=$BAT_STYLE" -e "BAT_THEME=$BAT_THEME" -e "PREVIEWPID=$PREVIEWPID" \ + -e "PAGER=$PAGER" -e "ICONLOOKUP=$ICONLOOKUP" -e "NNN_PREVIEWWIDTH=$NNN_PREVIEWWIDTH" \ + -e "USE_SCOPE=$USE_SCOPE" -e "SPLIT=$SPLIT" -e "USE_PISTOL=$USE_PISTOL" \ + -e "NNN_PREVIEWDIR=$NNN_PREVIEWDIR" -e "NNN_PREVIEWHEIGHT=$NNN_PREVIEWHEIGHT" \ + -e "FIFO_UEBERZUG=$FIFO_UEBERZUG" -e "QLPATH=$2" -d"$DSPLIT" "$0" "$1" ;; + kitty) # Setting the layout for the new window. It will be restored after the script ends. + kitty @ goto-layout splits + # 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 "TMPDIR=$TMPDIR" \ + --env "USE_SCOPE=$USE_SCOPE" --env "SPLIT=$SPLIT" --env "TERMINAL=$TERMINAL"\ + --env "PREVIEWPID=$PREVIEWPID" --env "FIFO_UEBERZUG=$FIFO_UEBERZUG" \ + --env "ICONLOOKUP=$ICONLOOKUP" --env "NNN_PREVIEWHEIGHT=$NNN_PREVIEWHEIGHT" \ + --env "NNN_PREVIEWWIDTH=$NNN_PREVIEWWIDTH" --env "NNN_PREVIEWDIR=$NNN_PREVIEWDIR" \ + --env "USE_PISTOL=$USE_PISTOL" --env "BAT_STYLE=$BAT_STYLE" \ + --env "BAT_THEME=$BAT_THEME" --env "FIFOPID=$FIFOPID" --env TTY="$TTY" \ + --env "CURSEL=$CURSEL" --location "${SPLIT}split" "$0" "$1" ;; + iterm) + command="$SHELL -c 'cd $PWD; \ + PATH=\\\"$PATH\\\" NNN_FIFO=\\\"$NNN_FIFO\\\" PREVIEW_MODE=1 PAGER=\\\"$PAGER\\\" \ + USE_SCOPE=\\\"$USE_SCOPE\\\" SPLIT=\\\"$SPLIT\\\" TERMINAL=\\\"$TERMINAL\\\" \ + PREVIEWPID=\\\"$PREVIEWPID\\\" CURSEL=\\\"$CURSEL\\\" TMPDIR=\\\"$TMPDIR\\\" \ + ICONLOOKUP=\\\"$ICONLOOKUP\\\" NNN_PREVIEWHEIGHT=\\\"$NNN_PREVIEWHEIGHT\\\" \ + NNN_PREVIEWWIDTH=\\\"$NNN_PREVIEWWIDTH\\\" NNN_PREVIEWDIR=\\\"$NNN_PREVIEWDIR\\\" \ + USE_PISTOL=\\\"$USE_PISTOL\\\" BAT_STYLE=\\\"$BAT_STYLE\\\" TTY=\\\"$TTY\\\" \ + BAT_THEME=\\\"$BAT_THEME\\\" FIFOPID=\\\"$FIFOPID\\\" \\\"$0\\\" \\\"$1\\\"'" + if [ "$SPLIT" = "h" ]; then split="horizontally"; else split="vertically"; fi + osascript <<-EOF + tell application "iTerm" + tell current session of current window + split $split with default profile command "$command" + end tell + end tell +EOF + ;; + *) if [ -n "$2" ]; then + QUICKLOOK=1 QLPATH="$2" PREVIEW_MODE=1 "$0" "$1" & + else + PREVIEWPID="$PREVIEWPID" CURSEL="$CURSEL" PREVIEW_MODE=1 TTY="$TTY" \ + FIFOPID="$FIFOPID" FIFO_UEBERZUG="$FIFO_UEBERZUG" $TERMINAL -e "$0" "$1" & + fi ;; + esac +} >/dev/null 2>&1 + +toggle_preview() { + if exists QuickLook.exe; then + QLPATH="QuickLook.exe" + elif exists Bridge.exe; then + QLPATH="Bridge.exe" + fi + if kill "$(cat "$FIFOPID")"; then + [ -p "$NNN_PPIPE" ] && printf "0" > "$NNN_PPIPE" + kill "$(cat "$PREVIEWPID")" + pkill -f "tail --follow $FIFO_UEBERZUG" + if [ -n "$QLPATH" ] && stat "$1"; then + f="$(wslpath -w "$1")" && "$QLPATH" "$f" & + fi + else + [ -p "$NNN_PPIPE" ] && printf "1" > "$NNN_PPIPE" + start_preview "$1" "$QLPATH" + fi +} >/dev/null 2>&1 + +exists() { + type "$1" >/dev/null +} + +fifo_pager() { + cmd="$1" + shift + + # We use a FIFO to access $PAGER PID in jobs control + tmpfifopath="$TMPDIR/nnn-preview-tui-fifo.$$" + mkfifo "$tmpfifopath" || return + + $PAGER < "$tmpfifopath" & + printf "%s" "$!" > "$PREVIEWPID" + + ( + exec > "$tmpfifopath" + if [ "$cmd" = "pager" ]; then + if exists bat; then + bat --terminal-width="$(tput cols <"$TTY")" --decorations=always --color=always \ + --paging=never --style="$BAT_STYLE" --theme="$BAT_THEME" "$@" & + else + $PAGER "$@" & + fi + else + "$cmd" "$@" & + fi + ) + + rm "$tmpfifopath" +} 2>/dev/null + +# 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" + else + file -b "$1" + fi +} 2>/dev/null + +handle_mime() { + case "$2" in + image/jpeg) image_preview "$cols" "$lines" "$1" ;; + image/gif) generate_preview "$cols" "$lines" "$1" "gif" ;; + image/*) generate_preview "$cols" "$lines" "$1" "image" ;; + video/*) generate_preview "$cols" "$lines" "$1" "video" ;; + audio/*) generate_preview "$cols" "$lines" "$1" "audio" ;; + application/font*|application/*opentype|font/*) generate_preview "$cols" "$lines" "$1" "font" ;; + */*office*|*/*document*) generate_preview "$cols" "$lines" "$1" "office" ;; + application/zip) fifo_pager unzip -l "$1" ;; + text/troff) + if exists man; then + fifo_pager man -Pcat -l "$1" + else + fifo_pager pager "$1" + fi ;; + *) handle_ext "$1" "$3" "$4" ;; + esac +} + +handle_ext() { + case "$2" in + epub) generate_preview "$cols" "$lines" "$1" "epub" ;; + pdf) generate_preview "$cols" "$lines" "$1" "pdf" ;; + gz|bz2) fifo_pager tar -tvf "$1" ;; + md) if exists glow; then + fifo_pager glow -s dark "$1" + elif exists lowdown; then + fifo_pager lowdown -Tterm "$1" + else + fifo_pager pager "$1" + fi ;; + htm|html|xhtml) + if exists w3m; then + fifo_pager w3m "$1" + elif exists lynx; then + fifo_pager lynx "$1" + elif exists elinks; then + fifo_pager elinks "$1" + else + fifo_pager pager "$1" + fi ;; + 7z|a|ace|alz|arc|arj|bz|cab|cpio|deb|jar|lha|lz|lzh|lzma|lzo\ + |rar|rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z) + if exists atool; then + fifo_pager atool -l "$1" + elif exists bsdtar; then + fifo_pager bsdtar -tvf "$1" + fi ;; + *) if [ "$3" = "bin" ]; then + fifo_pager print_bin_info "$1" + else + fifo_pager pager "$1" + fi ;; + esac +} + +preview_file() { + 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" + return + fi + + # Use QuickLook if it's available. + if [ -n "$QUICKLOOK" ]; then + stat "$1" && f="$(wslpath -w "$1")" && "$QLPATH" "$f" & + return + fi + + # Detecting the exact type of the file: the encoding, mime type, and extension in lowercase. + encoding="$(file -bL --mime-encoding -- "$1")" + mimetype="$(file -bL --mime-type -- "$1")" + ext="${1##*.}" + [ -n "$ext" ] && ext="$(printf "%s" "${ext}" | tr '[:upper:]' '[:lower:]')" + lines=$(tput lines <"$TTY") + cols=$(tput cols <"$TTY") + + # Otherwise, falling back to the defaults. + if [ -d "$1" ]; then + cd "$1" || return + if [ "$ICONLOOKUP" -ne 0 ] && [ -f "$(dirname "$0")"/.iconlookup ]; then + [ "$SPLIT" = v ] && BSTR="\n" + # shellcheck disable=SC2012 + ls -F --group-directories-first | head -n "$((lines - 3))" | "$(dirname "$0")"/.iconlookup -l "$cols" -B "$BSTR" -b " " + elif exists tree; then + fifo_pager tree --filelimit "$(find . -maxdepth 1 | wc -l)" -L 3 -C -F --dirsfirst --noreport + elif exists exa; then + exa -G --group-directories-first --colour=always + else + fifo_pager ls -F --group-directories-first --color=always + fi + elif [ "${encoding#*)}" = "binary" ]; then + handle_mime "$1" "$mimetype" "$ext" "bin" + else + handle_mime "$1" "$mimetype" "$ext" + fi +} 2>/dev/null + +generate_preview() { + if [ -n "$QLPATH" ] && stat "$3"; then + f="$(wslpath -w "$3")" && "$QLPATH" "$f" & + elif [ ! -f "$NNN_PREVIEWDIR/$3.jpg" ] || [ -n "$(find -L "$3" -newer "$NNN_PREVIEWDIR/$3.jpg")" ]; then + mkdir -p "$NNN_PREVIEWDIR/${3%/*}" + case $4 in + audio) ffmpeg -i "$3" -filter_complex "scale=iw*min(1\,min($NNN_PREVIEWWIDTH/iw\,ih)):-1" "$NNN_PREVIEWDIR/$3.jpg" -y ;; + epub) gnome-epub-thumbnailer "$3" "$NNN_PREVIEWDIR/$3.jpg" ;; + font) fontpreview -i "$3" -o "$NNN_PREVIEWDIR/$3.jpg" ;; + gif) if [ -p "$FIFO_UEBERZUG" ] && exists convert; then + if [ ! -d "$NNN_PREVIEWDIR/$3" ]; then + mkdir -p "$NNN_PREVIEWDIR/$3" + convert -coalesce -resize "$NNN_PREVIEWWIDTH"x"$NNN_PREVIEWHEIGHT"\> "$3" "$NNN_PREVIEWDIR/$3/${3##*/}.jpg" + fi + while true; do + for frame in $(find "$NNN_PREVIEWDIR/$3"/*.jpg | sort -V); do + image_preview "$1" "$2" "$frame" + sleep 0.1 + done + done & + printf "%s" "$!" > "$PREVIEWPID" + return + else + exec >/dev/tty + image_preview "$1" "$2" "$3" + return + fi ;; + image) if exists convert; then + convert "$3" -flatten -resize "$NNN_PREVIEWWIDTH"x"$NNN_PREVIEWHEIGHT"\> "$NNN_PREVIEWDIR/$3.jpg" + else + image_preview "$1" "$2" "$3" && return + fi ;; + office) libreoffice --convert-to jpg "$3" --outdir "$NNN_PREVIEWDIR/${3%/*}" + filename="$(printf "%s" "${3##*/}" | cut -d. -f1)" + mv "$NNN_PREVIEWDIR/${3%/*}/$filename.jpg" "$NNN_PREVIEWDIR/$3.jpg" ;; + pdf) pdftoppm -jpeg -f 1 -singlefile "$3" "$NNN_PREVIEWDIR/$3" ;; + video) ffmpegthumbnailer -s0 -i "$3" -o "$NNN_PREVIEWDIR/$3.jpg" || rm "$NNN_PREVIEWDIR/$3.jpg" ;; + esac + fi >/dev/null + if [ -f "$NNN_PREVIEWDIR/$3.jpg" ]; then + image_preview "$1" "$2" "$NNN_PREVIEWDIR/$3.jpg" + else + fifo_pager print_bin_info "$3" + fi +} 2>/dev/null + +image_preview() { + clear + if [ "$TERMINAL" = "kitty" ]; then + # Kitty terminal users can use the native image preview method + kitty +kitten icat --silent --place "$1"x"$2"@0x0 --transfer-mode=stream --stdin=no "$3" & + elif exists ueberzug; then + ueberzug_layer "$1" "$2" "$3" && return + elif exists catimg; then + catimg "$3" & + elif exists viu; then + viu -t "$3" & + #elif exists sxiv; then + # sxiv "$3" + else + fifo_pager print_bin_info "$3" && return + fi + printf "%s" "$!" > "$PREVIEWPID" +} 2>/dev/null + +ueberzug_layer() { + printf '{"action": "add", "identifier": "nnn_ueberzug", "x": 0, "y": 0, "width": "%d", "height": "%d", "scaler": "fit_contain", "path": "%s"}\n' "$1" "$2" "$3" > "$FIFO_UEBERZUG" +} + +ueberzug_remove() { + printf '{"action": "remove", "identifier": "nnn_ueberzug"}\n' > "$FIFO_UEBERZUG" +} + +winch_handler() { + clear + kill "$(cat "$PREVIEWPID")" + if [ -p "$FIFO_UEBERZUG" ]; then + pkill -f "tail --follow $FIFO_UEBERZUG" + tail --follow "$FIFO_UEBERZUG" | ueberzug layer --silent --parser json & + fi + preview_file "$(cat "$CURSEL")" +} 2>/dev/null + +preview_fifo() { + while read -r selection; do + if [ -n "$selection" ]; then + kill "$(cat "$PREVIEWPID")" + [ -p "$FIFO_UEBERZUG" ] && ueberzug_remove + [ "$selection" = "close" ] && sleep 0.15 && pkill -P "$$" && exit + preview_file "$selection" + printf "%s" "$selection" > "$CURSEL" + fi + done < "$NNN_FIFO" + sleep 0.1 # make sure potential preview by winch_handler is killed + pkill -P "$$" +} 2>/dev/null + +if [ "$PREVIEW_MODE" ]; then + if [ "$TERMINAL" != "kitty" ] && exists ueberzug; then + mkfifo "$FIFO_UEBERZUG" + tail --follow "$FIFO_UEBERZUG" | ueberzug layer --silent --parser json & + fi + + preview_file "$PWD/$1" + preview_fifo & + printf "%s" "$!" > "$FIFOPID" + printf "%s" "$PWD/$1" > "$CURSEL" + trap 'winch_handler; wait' WINCH + trap 'rm "$PREVIEWPID" "$CURSEL" "$FIFO_UEBERZUG" "$FIFOPID" 2>/dev/null' INT HUP EXIT + wait "$!" 2>/dev/null +else + if [ ! -r "$NNN_FIFO" ]; then + clear + printf "No FIFO available! (\$NNN_FIFO='%s')\nPlease read Usage in preview-tui." "$NNN_FIFO" + cfg=$(stty -g); stty raw -echo; head -c 1; stty "$cfg" + elif [ "$KITTY_WINDOW_ID" ] && [ -z "$TMUX" ] && [ -z "$KITTY_LISTEN_ON" ]; then + clear + printf "\$KITTY_LISTEN_ON not set!\nPlease read Usage in preview-tui." + cfg=$(stty -g); stty raw -echo; head -c 1; stty "$cfg" + else + TTY="$(tty)" + TTY="$TTY" toggle_preview "$1" & + fi +fi diff --git a/config/nnn/plugins/pskill b/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 [ -n "$psname" ]; then + if type sudo >/dev/null 2>&1; then + sucmd=sudo + elif type doas >/dev/null 2>&1; then + sucmd=doas + else + sucmd=: # noop + fi + + if type 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/config/nnn/plugins/renamer b/config/nnn/plugins/renamer @@ -0,0 +1,45 @@ +#!/usr/bin/env sh + +# Description: Batch rename selection or current directory with qmv or vidir +# +# 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 type qmv >/dev/null 2>&1; then + batchrenamesel="qmv -fdo -da" + batchrename="qmv -fdo -a" +elif type 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" + + # 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 + $batchrename +fi diff --git a/config/nnn/plugins/ringtone b/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/config/nnn/plugins/rsynccp b/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/config/nnn/plugins/splitjoin b/config/nnn/plugins/splitjoin @@ -0,0 +1,52 @@ +#!/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" + + # Clear selection + if [ -p "$NNN_PIPE" ]; then + printf "-" > "$NNN_PIPE" + fi + 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/config/nnn/plugins/suedit b/config/nnn/plugins/suedit @@ -0,0 +1,16 @@ +#!/usr/bin/env sh + +# Description: Edit file as superuser +# +# Shell: POSIX compliant +# Author: Anna Arad + +EDITOR="${EDITOR:-vim}" + +if type sudo >/dev/null 2>&1; then + sudo -E "$EDITOR" "$1" +elif type sudoedit >/dev/null 2>&1; then + sudoedit -E "$1" +elif type doas >/dev/null 2>&1; then + doas "$EDITOR" "$1" +fi diff --git a/config/nnn/plugins/togglex b/config/nnn/plugins/togglex @@ -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/config/nnn/plugins/umounttree b/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/config/nnn/plugins/upload b/config/nnn/plugins/upload @@ -0,0 +1,30 @@ +#!/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 [ -n "$1" ] && [ -s "$1" ]; then + if type ffsend >/dev/null 2>&1; then + ffsend -fiq u "$1" + elif [ "$(mimetype --output-format %m "$1" | awk -F '/' '{print $1}')" = "text" ]; then + curl -F "f:1=@$1" ix.io + else + # Upload the file, show the download link and wait till user presses any key + curl -s -F "file=@$1" https://file.io/?expires=1w | jq '.link' | tr -d '"' + + # To write download link to "$1".loc and exit + # curl -s -F "file=@$1" https://file.io/?expires=1w -o `basename "$1"`.loc + fi +else + printf "empty file!" +fi + +read -r _ diff --git a/config/nnn/plugins/wallpaper b/config/nnn/plugins/wallpaper @@ -0,0 +1,26 @@ +#!/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 + +if [ -n "$1" ]; then + if [ "$(file --mime-type "$1" | awk '{print $NF}' | awk -F '/' '{print $1}')" = "image" ]; then + if type nitrogen >/dev/null 2>&1; then + nitrogen --set-zoom-fill --save "$1" + elif type wal >/dev/null 2>&1; then + wal -i "$1" + else + printf "nitrogen or 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/config/nnn/plugins/x2sel b/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) +# +# Note: +# - 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 type xsel >/dev/null 2>&1; then + # Linux + xsel -bo + elif type xclip >/dev/null 2>&1; then + # Linux + xclip -sel clip -o + elif type pbpaste >/dev/null 2>&1; then + # macOS + pbpaste + elif type termux-clipboard-get >/dev/null 2>&1; then + # Termux + termux-clipboard-get + elif type powershell.exe >/dev/null 2>&1; then + # WSL + powershell.exe Get-Clipboard + elif [ -r /dev/clipboard ] ; then + # Cygwin + cat /dev/clipboard + elif type wl-paste >/dev/null 2>&1; then + # Wayland + wl-paste + elif type 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" diff --git a/config/nnn/plugins/xdgdefault b/config/nnn/plugins/xdgdefault @@ -0,0 +1,53 @@ +#!/usr/bin/env sh + +# Description: Sets the xdg-open's default application for the current entry's file +# type. ${XDG_DATA_DIRS} and ${XDG_DATA_HOME} are set to the recommended +# defaults if unset, as specified in XDG Base Directory Specification +# - http://specifications.freedesktop.org/basedir-spec/. +# +# Dependencies: xdg-utils, fzf or dmenu (GUI) +# +# Shell: POSIX compliant +# Author: lwnctd + +# set to 1 to enable GUI apps +GUI="${GUI:-0}" + +if [ "$GUI" -ne 0 ] && command -v dmenu > /dev/null 2>& 1; then + menu="dmenu -i -l 7" +elif command -v fzf > /dev/null 2>& 1; then + menu="fzf -e --tiebreak=begin" +fi + +if [ -z "$1" ] || [ -z "$menu" ] > /dev/null 2>& 1; then + exit 1 +fi + +ftype=$(xdg-mime query filetype "$2/$1") + +if [ -z "$ftype" ]; then + exit 1 +fi + +dirs=${XDG_DATA_DIRS:-/usr/local/share:/usr/share} +dirs=${dirs}:${XDG_DATA_HOME:-$HOME/.local/share}: + +while [ -n "$dirs" ]; do + d=${dirs%%:*} + if [ -n "$d" ] && [ -d "$d"/applications ]; then + set -- "$@" "$d"/applications + fi + dirs=${dirs#*:} +done + +app=$(find "$@" -iname '*.desktop' -exec grep '^Name=' {} + \ + | sort -u -t ':' -k 1,1 \ + | sed -E 's;.+/(.+desktop):Name=(.+);\2:\1;' \ + | sort -t ':' -k 1,1 \ + | column -t -s ':' -o "$(printf '\t')" \ + | $menu \ + | cut -f 2) + +if [ -n "$app" ]; then + xdg-mime default "$app" "$ftype" +fi diff --git a/config/nvim/init.vim b/config/nvim/init.vim @@ -0,0 +1,95 @@ +" >source % (refrescar a configuracion) +syntax on + +:set number +":set rnu +:set numberwidth=1 + +:set mouse=a +:set noerrorbells + +" Tabulacions +:set sw=4 +:set expandtab + +" Indentacions +:set smartindent + +:set nowrap +:set noswapfile +:set nobackup +:set incsearch +:set ignorecase +:set clipboard+=unnamedplus " Senon vai -> instala xclip +:set encoding=utf-8 +:set cursorline +:set termguicolors +:set colorcolumn=120 +:highlight ColoColumn ctermbg=0 guibg=lightgrey + + +" Plugins +call plug#begin('~/.local/share/nvim/plugged') +" Instalar plugins: :PlugInstall +"https://github.com/iamcco/markdown-preview.nvim +Plug 'itchyny/lightline.vim' +Plug 'tpope/vim-surround' " Para engadir/eliminar/cambiar parenteses +Plug 'airblade/vim-gitgutter' " diffs de git +Plug 'tomtom/tcomment_vim' " comentarios +Plug 'orlp/vim-bunlink' " pechar ventanas sen perder as separacions +Plug 'vim-autoformat/vim-autoformat' +Plug 'editorconfig/editorconfig-vim' +Plug 'neoclide/coc.nvim', {'branch': 'release'} +Plug 'iamcco/markdown-preview.nvim', { 'do': 'cd app && yarn install' } +Plug 'rrethy/vim-hexokinase', { 'do': 'make hexokinase' } " css cores +" Temas +Plug 'morhetz/gruvbox' +Plug 'ayu-theme/ayu-vim' +Plug 'joshdick/onedark.vim' + +call plug#end() + +" Establecer tecla lider (espazo) +let mapleader=" " + +let g:gruvbox_contrast_dark="hard" +let g:gruvbox_transparent_bg=1 +colorscheme gruvbox + +" Mapeos de teclas +" gardar +nnoremap <leader>w :w<CR> +" partido vertical,horizontal +nnoremap <leader>vs :vsp<CR> +nnoremap <leader>sp :sp<CR> +" pechar xanela (substituto por bdelete) +nnoremap <leader>q :Bunlink<CR> +" pechar vim +nnoremap <leader>x :q<CR> +" crear nova pestanha +nnoremap <leader>t :tabe<CR> +" Redimensionar particions de xanela +nnoremap <silent> <right> :vertical resize +5<CR> +nnoremap <silent> <left> :vertical resize -5<CR> +nnoremap <silent> <up> :resize +5<CR> +nnoremap <silent> <down> :resize -5<CR> +" Abrir o ficheiro de configuracion +nnoremap <leader>e :e $MYVIMRC<CR> +" Moverse entre particions de xanela +nnoremap <silent><C-Right> <c-w>l +nnoremap <silent><C-Left> <c-w>h +nnoremap <silent><C-Up> <c-w>k +nnoremap <silent><C-Down> <c-w>j + + +" Esto e para compilar a latex automaticamente +function! ZathuraOpenPdf() + let fullPath = expand("%:p") + let pdfFile = substitute(fullPath, ".txt", ".pdf", "") + execute "silent !pdflatex '". fullPath ."' &" + execute "silent !zathura '" . pdfFile . "' &" +endfunction +nnoremap <c-t> :call ZathuraOpenPdf()<CR> + +hi! Normal ctermbg=NONE guibg=NONE +hi! NonText ctermbg=NONE guibg=NONE diff --git a/portatil/bash_profile b/portatil/bash_profile @@ -0,0 +1,17 @@ +# +# ~/.bash_profile +# + +[[ -f ~/.bashrc ]] && . ~/.bashrc + +[[ $(fgconsole 2>/dev/null) == 1 ]] && exec startx -- vt1 + +#synclient TapButton1=1 +#synclient TapButton2=3 +#export PROBA="Ueseeeee_;)" +#sh /etc/profile.d/touchpad_pilluko.sh +export NNN_FIFO=/tmp/nnn.fifo +export HISTSIZE=10000 +# Esto e para que no reverse search podas ir para adiante e atras con +# Ctrl + R (Adiante), Ctrl + S (Atras) +stty -ixon diff --git a/portatil/bashrc b/portatil/bashrc @@ -0,0 +1,70 @@ +# +# ~/.bashrc +# + +# If not running interactively, don't do anything +[[ $- != *i* ]] && return + +alias ls='ls --color=auto' +PS1='[\u@\h \W]\$ ' +# Cousas dos locales +export LANG=en_US.UTF-8 +export LANGUAGE=en_US.UTF-8 +export LC_COLLATE=C +export LC_CTYPE=en_US.UTF-8 +# PROMPT (30: gris, 31:vermello, 32:verde, 33:amarelo, 34: azul, 35: rosa, 36: cian, 37: branco) +export PS1="\[\033[01;31m\][\[\033[01;36m\]chinomin \[\033[01;30m\]\W\[\033[01;31m\]]\[\033[00m\] " +# TERMINAL PRINCIPAL +export TERMINAL=st +# EDITOR PRINCIPAL +export EDITOR=nvim +# Cousas de NNN +export NNN_PLUG='p:preview-tui;t:preview-tabbed;i:imgview;' +export NNN_USE_EDITOR=1 +export NNN_OPENER=/home/chinomin/.config/nnn/plugins/nuke +export NNN_FIFO=/tmp/nnn.fifo +alias pdf=zathura +alias v=nvim +alias ase=aseprite +alias off='poweroff' +alias cp='cp -iv' +alias mv='mv -v' +alias rep='mpv --vo=null --video=no --no-video --term-osd-bar --no-resume-playback --shuffle' +alias redes='nmcli device wifi list' +alias desligar="nmcli connection down $({ nmcli | awk '/^wlp2s0/ {print $4}'; })" +alias dly="youtube-dl --ignore-errors --format bestaudio --extract-audio --audio-format mp3 --audio-quality 160K --output \"%(title)s.%(ext)s\" --yes-playlist" +alias montar="sudo mount -t auto /dev/sda1 /media/usb_pau" +alias vim='nvim' +alias keys="eval '$(ssh-agent -s)'; ssh-add /home/chinomin/proxectos/testkey" +# Facer un script para conectarse a unha rede +# Funcion para acceder a nnn e cambie o pwd +n () +{ + # Block nesting of nnn in subshells + if [ -n $NNNLVL ] && [ "${NNNLVL:-0}" -ge 1 ]; then + echo "nnn xa esta funcionando meu" + return + fi + + export NNN_TMPFILE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.lastd" + + nnn -c -e -Rd "$@" + + if [ -f "$NNN_TMPFILE" ]; then + . "$NNN_TMPFILE" + rm -f "$NNN_TMPFILE" > /dev/null + fi +} + +# Se e a primeira vez na sesion + +if [ "$INICIADA" == "siu" ]; then + neofetch + sudo ntpd -qg + return +fi + +## Blesh (autocompletado) + +[[ $- == *i* ]] && . /usr/share/blesh/ble.sh + diff --git a/portatil/xinitrc b/portatil/xinitrc @@ -0,0 +1,63 @@ +#!/bin/sh + +userresources=$HOME/.Xresources +usermodmap=$HOME/.Xmodmap +sysresources=/etc/X11/xinit/.Xresources +sysmodmap=/etc/X11/xinit/.Xmodmap + +# merge in defaults and keymaps + +if [ -f $sysresources ]; then + + + + + + + + xrdb -merge $sysresources + +fi + +if [ -f $sysmodmap ]; then + xmodmap $sysmodmap +fi + +if [ -f "$userresources" ]; then + + + + + + + + xrdb -merge "$userresources" + +fi + +if [ -f "$usermodmap" ]; then + xmodmap "$usermodmap" +fi + +# start some nice programs + +if [ -d /etc/X11/xinit/xinitrc.d ] ; then + for f in /etc/X11/xinit/xinitrc.d/?*.sh ; do + [ -x "$f" ] && . "$f" + done + unset f +fi + +nitrogen --restore & +picom & +. /opt/gcolors/colors_env.sh +dwmblocks & +export INICIADA="siu" +st & +export INICIADA="nop" +exec dwm +#twm & +#xclock -geometry 50x50-1+1 & +#xterm -geometry 80x50+494+51 & +#xterm -geometry 80x20+494-0 & +#exec xterm -geometry 80x66+0+0 -name login