sistema_progs

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

nuke (18805B)


      1 #!/usr/bin/env sh
      2 
      3 # Description: Sample script to play files in apps by file type or mime
      4 #
      5 # Shell: POSIX compliant
      6 # Usage: nuke filepath
      7 #
      8 # Integration with nnn:
      9 #   1. Export the required config:
     10 #         export NNN_OPENER=/absolute/path/to/nuke
     11 #         # Otherwise, if nuke is in $PATH
     12 #         # export NNN_OPENER=nuke
     13 #   2. Run nnn with the program option to indicate a CLI opener
     14 #         nnn -c
     15 #         # The -c program option overrides option -e
     16 #   3. nuke can use nnn plugins (e.g. mocq is used for audio), $PATH is updated.
     17 #
     18 # Details:
     19 #   Inspired by ranger's scope.sh, modified for usage with nnn.
     20 #
     21 #   Guards against accidentally opening mime types like executables, shared libs etc.
     22 #
     23 #   Tries to play 'file' (1st argument) in the following order:
     24 #     1. by extension
     25 #     2. by mime (image, video, audio, pdf)
     26 #     3. by mime (other file types)
     27 #     4. by mime (prompt and run executables)
     28 #
     29 # Modification tips:
     30 #   1. Invokes CLI utilities by default. Set GUI to 1 to enable GUI apps.
     31 #   2. PAGER is "less -R".
     32 #   3. Start GUI apps in bg to unblock. Redirect stdout and strerr if required.
     33 #   4. Some CLI utilities are piped to the $PAGER, to wait and quit uniformly.
     34 #   5. If the output cannot be paged use "read -r _" to wait for user input.
     35 #   6. On a DE, try 'xdg-open' or 'open' in handle_fallback() as last resort.
     36 #
     37 #   Feel free to change the utilities to your favourites and add more mimes.
     38 #
     39 # Defaults:
     40 #   By extension (only the enabled ones):
     41 #      most archives: list with atool, bsdtar
     42 #      rar: list with unrar
     43 #      7-zip: list with 7z
     44 #      pdf: zathura (GUI), pdftotext, mutool, exiftool
     45 #      audio: mocq (nnn plugin using MOC), mpv, media_client (Haiku), mediainfo, exiftool
     46 #      avi|mkv|mp4: smplayer, mpv (GUI), ffmpegthumbnailer, mediainfo, exiftool
     47 #      log: vi
     48 #      torrent: rtorrent, transmission-show
     49 #      odt|ods|odp|sxw: odt2txt
     50 #      md: glow (https://github.com/charmbracelet/glow), lowdown (https://kristaps.bsd.lv/lowdown)
     51 #      htm|html|xhtml: w3m, lynx, elinks
     52 #      json: jq, python (json.tool module)
     53 #   Multimedia by mime:
     54 #      image/*: imv/sxiv/nsxiv (GUI), viu (https://github.com/atanunq/viu), img2txt, exiftool
     55 #      video/*: smplayer, mpv (GUI), ffmpegthumbnailer, mediainfo, exiftool
     56 #      audio/*: mocq (nnn plugin using MOC), mpv, media_client (Haiku), mediainfo, exiftool
     57 #      application/pdf: zathura (GUI), pdftotext, mutool, exiftool
     58 #   Other mimes:
     59 #      text/troff: man -l
     60 #      text/* | */xml: vi
     61 #      image/vnd.djvu): djvutxt, exiftool
     62 #
     63 # TODO:
     64 #   1. Adapt, test and enable all mimes
     65 #   2. Clean-up the unnecessary exit codes
     66 
     67 # set to 1 to enable GUI apps and/or BIN execution
     68 GUI="${GUI:-0}"
     69 BIN="${BIN:-0}"
     70 
     71 set -euf -o noclobber -o noglob -o nounset
     72 IFS="$(printf '%b_' '\n')"; IFS="${IFS%_}" # protect trailing \n
     73 
     74 PATH=$PATH:"${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins"
     75 IMAGE_CACHE_PATH="$(dirname "$1")"/.thumbs
     76 
     77 FPATH="$1"
     78 FNAME=$(basename "$1")
     79 EDITOR="${VISUAL:-${EDITOR:-vi}}"
     80 PAGER="${PAGER:-less -R}"
     81 ext="${FNAME##*.}"
     82 if [ -n "$ext" ]; then
     83     ext="$(printf "%s" "${ext}" | tr '[:upper:]' '[:lower:]')"
     84 fi
     85 
     86 is_mac() {
     87     uname | grep -q "Darwin"
     88 }
     89 
     90 handle_pdf() {
     91     if [ "$GUI" -ne 0 ]; then
     92         if is_mac; then
     93             nohup open "${FPATH}" >/dev/null 2>&1 &
     94         elif type zathura >/dev/null 2>&1; then
     95             nohup zathura "${FPATH}" >/dev/null 2>&1 &
     96         else
     97             return
     98         fi
     99     elif type pdftotext >/dev/null 2>&1; then
    100         ## Preview as text conversion
    101         pdftotext -l 10 -nopgbrk -q -- "${FPATH}" - | eval "$PAGER"
    102     elif type mutool >/dev/null 2>&1; then
    103         mutool draw -F txt -i -- "${FPATH}" 1-10 | eval "$PAGER"
    104     elif type exiftool >/dev/null 2>&1; then
    105         exiftool "${FPATH}" | eval "$PAGER"
    106     else
    107         return
    108     fi
    109     exit 0
    110 }
    111 
    112 handle_audio() {
    113     if type mocp >/dev/null 2>&1 && type mocq >/dev/null 2>&1; then
    114         mocq "${FPATH}" "opener" >/dev/null 2>&1
    115     elif type mpv >/dev/null 2>&1; then
    116         mpv "${FPATH}" >/dev/null 2>&1 &
    117     elif type media_client >/dev/null 2>&1; then
    118         media_client play "${FPATH}" >/dev/null 2>&1 &
    119     elif type mediainfo >/dev/null 2>&1; then
    120         mediainfo "${FPATH}" | eval "$PAGER"
    121     elif type exiftool >/dev/null 2>&1; then
    122         exiftool "${FPATH}"| eval "$PAGER"
    123     else
    124         return
    125     fi
    126     exit 0
    127 }
    128 
    129 handle_video() {
    130     if [ "$GUI" -ne 0 ]; then
    131         mpv "${FPATH}" > /dev/null 2>&1 &
    132         #if is_mac; then
    133         #    nohup open "${FPATH}" >/dev/null 2>&1 &
    134         #elif type smplayer >/dev/null 2>&1; then
    135         #    nohup smplayer "${FPATH}" >/dev/null 2>&1 &
    136         #elif type mpv >/dev/null 2>&1; then
    137         #    nohup mpv "${FPATH}" >/dev/null 2>&1 &
    138         #else
    139         #    return
    140         fi
    141     elif type ffmpegthumbnailer >/dev/null 2>&1; then
    142         # Thumbnail
    143         [ -d "${IMAGE_CACHE_PATH}" ] || mkdir "${IMAGE_CACHE_PATH}"
    144         ffmpegthumbnailer -i "${FPATH}" -o "${IMAGE_CACHE_PATH}/${FNAME}.jpg" -s 0
    145         viu -n "${IMAGE_CACHE_PATH}/${FNAME}.jpg" | eval "$PAGER"
    146     elif type mediainfo >/dev/null 2>&1; then
    147         mediainfo "${FPATH}" | eval "$PAGER"
    148     elif type exiftool >/dev/null 2>&1; then
    149         exiftool "${FPATH}"| eval "$PAGER"
    150     else
    151         return
    152     fi
    153     exit 0
    154 }
    155 
    156 # handle this extension and exit
    157 handle_extension() {
    158     case "${ext}" in
    159         ## Archive
    160         a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|\
    161         rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z|zip)
    162             if type atool >/dev/null 2>&1; then
    163                 atool --list -- "${FPATH}" | eval "$PAGER"
    164                 exit 0
    165             elif type bsdtar >/dev/null 2>&1; then
    166                 bsdtar --list --file "${FPATH}" | eval "$PAGER"
    167                 exit 0
    168             fi
    169             exit 1;;
    170         rar)
    171             if type unrar >/dev/null 2>&1; then
    172                 ## Avoid password prompt by providing empty password
    173                 unrar lt -p- -- "${FPATH}" | eval "$PAGER"
    174             fi
    175             exit 1;;
    176         7z)
    177             if type 7z >/dev/null 2>&1; then
    178                 ## Avoid password prompt by providing empty password
    179                 7z l -p -- "${FPATH}" | eval "$PAGER"
    180                 exit 0
    181             fi
    182             exit 1;;
    183 
    184         ## PDF
    185         pdf)
    186             handle_pdf
    187             exit 1;;
    188 
    189         ## Audio
    190         aac|flac|m4a|mid|midi|mpa|mp2|mp3|ogg|wav|wma)
    191             handle_audio
    192             exit 1;;
    193 
    194         ## Video
    195         avi|mkv|mp4)
    196             handle_video
    197             exit 1;;
    198 
    199         ## Log files
    200         log)
    201             "$EDITOR" "${FPATH}"
    202             exit 0;;
    203 
    204         ## BitTorrent
    205         torrent)
    206             if type rtorrent >/dev/null 2>&1; then
    207                 rtorrent "${FPATH}"
    208                 exit 0
    209             elif type transmission-show >/dev/null 2>&1; then
    210                 transmission-show -- "${FPATH}"
    211                 exit 0
    212             fi
    213             exit 1;;
    214 
    215         ## OpenDocument
    216         odt|ods|odp|sxw)
    217             if type odt2txt >/dev/null 2>&1; then
    218                 ## Preview as text conversion
    219                 odt2txt "${FPATH}" | eval "$PAGER"
    220                 exit 0
    221             fi
    222             exit 1;;
    223 
    224         ## Markdown
    225         md)
    226             if type glow >/dev/null 2>&1; then
    227                 glow -sdark "${FPATH}" | eval "$PAGER"
    228                 exit 0
    229             elif type lowdown >/dev/null 2>&1; then
    230                 lowdown -Tterm "${FPATH}" | eval "$PAGER"
    231                 exit 0
    232             fi
    233             ;;
    234 
    235         ## HTML
    236         htm|html|xhtml)
    237             ## Preview as text conversion
    238             if type w3m >/dev/null 2>&1; then
    239                 w3m -dump "${FPATH}" | eval "$PAGER"
    240                 exit 0
    241             elif type lynx >/dev/null 2>&1; then
    242                 lynx -dump -- "${FPATH}" | eval "$PAGER"
    243                 exit 0
    244             elif type elinks >/dev/null 2>&1; then
    245                 elinks -dump "${FPATH}" | eval "$PAGER"
    246                 exit 0
    247             fi
    248             ;;
    249 
    250         ## JSON
    251         json)
    252             if type jq >/dev/null 2>&1; then
    253                 jq --color-output . "${FPATH}" | eval "$PAGER"
    254                 exit 0
    255             elif type python >/dev/null 2>&1; then
    256                 python -m json.tool -- "${FPATH}" | eval "$PAGER"
    257                 exit 0
    258             fi
    259             ;;
    260     esac
    261 }
    262 
    263 # sets the variable abs_target, this should be faster than calling printf
    264 abspath() {
    265     case "$1" in
    266         /*) abs_target="$1";;
    267         *)  abs_target="$PWD/$1";;
    268     esac
    269 }
    270 
    271 # storing the result to a tmp file is faster than calling listimages twice
    272 listimages() {
    273     find -L "///${1%/*}" -maxdepth 1 -type f -print0 |
    274         grep -izZE '\.(jpe?g|png|gif|webp|tiff|bmp|ico|svg)$' |
    275         sort -z | tee "$tmp"
    276 }
    277 
    278 load_dir() {
    279     abspath "$2"
    280     tmp="${TMPDIR:-/tmp}/nuke_$$"
    281     trap 'rm -f $tmp' EXIT
    282     count="$(listimages "$abs_target" | grep -a -m 1 -ZznF "$abs_target" | cut -d: -f1)"
    283 
    284     if [ -n "$count" ]; then
    285         if [ "$GUI" -ne 0 ]; then
    286             xargs -0 nohup "$1" -n "$count" -- < "$tmp"
    287         else
    288             xargs -0 "$1" -n "$count" -- < "$tmp"
    289         fi
    290     else
    291         shift
    292         "$1" -- "$@" # fallback
    293     fi
    294 }
    295 
    296 handle_multimedia() {
    297     ## Size of the preview if there are multiple options or it has to be
    298     ## rendered from vector graphics. If the conversion program allows
    299     ## specifying only one dimension while keeping the aspect ratio, the width
    300     ## will be used.
    301     # local DEFAULT_SIZE="1920x1080"
    302 
    303     mimetype="${1}"
    304     case "${mimetype}" in
    305         ## SVG
    306         # image/svg+xml|image/svg)
    307         #     convert -- "${FPATH}" "${IMAGE_CACHE_PATH}" && exit 6
    308         #     exit 1;;
    309 
    310         ## DjVu
    311         # image/vnd.djvu)
    312         #     ddjvu -format=tiff -quality=90 -page=1 -size="${DEFAULT_SIZE}" \
    313         #           - "${IMAGE_CACHE_PATH}" < "${FPATH}" \
    314         #           && exit 6 || exit 1;;
    315 
    316         ## Image
    317         image/*)
    318             if [ "$GUI" -ne 0 ]; then
    319                 if is_mac; then
    320                     nohup open "${FPATH}" >/dev/null 2>&1 &
    321                     exit 0
    322                 elif type imv >/dev/null 2>&1; then
    323                     load_dir imv "${FPATH}" >/dev/null 2>&1 &
    324                     exit 0
    325                 elif type imvr >/dev/null 2>&1; then
    326                     load_dir imvr "${FPATH}" >/dev/null 2>&1 &
    327                     exit 0
    328                 elif type sxiv >/dev/null 2>&1; then
    329                     load_dir sxiv "${FPATH}" >/dev/null 2>&1 &
    330                     exit 0
    331                 elif type nsxiv >/dev/null 2>&1; then
    332                     load_dir nsxiv "${FPATH}" >/dev/null 2>&1 &
    333                     exit 0
    334                 fi
    335             elif type viu >/dev/null 2>&1; then
    336                 viu -n "${FPATH}" | eval "$PAGER"
    337                 exit 0
    338             elif type img2txt >/dev/null 2>&1; then
    339                 img2txt --gamma=0.6 -- "${FPATH}" | eval "$PAGER"
    340                 exit 0
    341             elif type exiftool >/dev/null 2>&1; then
    342                 exiftool "${FPATH}" | eval "$PAGER"
    343                 exit 0
    344             fi
    345             # local orientation
    346             # orientation="$( identify -format '%[EXIF:Orientation]\n' -- "${FPATH}" )"
    347             ## If orientation data is present and the image actually
    348             ## needs rotating ("1" means no rotation)...
    349             # if [[ -n "$orientation" && "$orientation" != 1 ]]; then
    350                 ## ...auto-rotate the image according to the EXIF data.
    351                 # convert -- "${FPATH}" -auto-orient "${IMAGE_CACHE_PATH}" && exit 6
    352             # fi
    353 
    354             ## `w3mimgdisplay` will be called for all images (unless overridden
    355             ## as above), but might fail for unsupported types.
    356             exit 7;;
    357 
    358         ## PDF
    359         application/pdf)
    360             handle_pdf
    361             exit 1;;
    362 
    363         ## Audio
    364         audio/*)
    365             handle_audio
    366             exit 1;;
    367 
    368         ## Video
    369         video/*)
    370             handle_video
    371             exit 1;;
    372 
    373         #     pdftoppm -f 1 -l 1 \
    374         #              -scale-to-x "${DEFAULT_SIZE%x*}" \
    375         #              -scale-to-y -1 \
    376         #              -singlefile \
    377         #              -jpeg -tiffcompression jpeg \
    378         #              -- "${FPATH}" "${IMAGE_CACHE_PATH%.*}" \
    379         #         && exit 6 || exit 1;;
    380 
    381 
    382         ## ePub, MOBI, FB2 (using Calibre)
    383         # application/epub+zip|application/x-mobipocket-ebook|\
    384         # application/x-fictionbook+xml)
    385         #     # ePub (using https://github.com/marianosimone/epub-thumbnailer)
    386         #     epub-thumbnailer "${FPATH}" "${IMAGE_CACHE_PATH}" \
    387         #         "${DEFAULT_SIZE%x*}" && exit 6
    388         #     ebook-meta --get-cover="${IMAGE_CACHE_PATH}" -- "${FPATH}" \
    389         #         >/dev/null && exit 6
    390         #     exit 1;;
    391 
    392         ## Font
    393         # application/font*|application/*opentype)
    394         #     preview_png="/tmp/$(basename "${IMAGE_CACHE_PATH%.*}").png"
    395         #     if fontimage -o "${preview_png}" \
    396         #                  --pixelsize "120" \
    397         #                  --fontname \
    398         #                  --pixelsize "80" \
    399         #                  --text "  ABCDEFGHIJKLMNOPQRSTUVWXYZ  " \
    400         #                  --text "  abcdefghijklmnopqrstuvwxyz  " \
    401         #                  --text "  0123456789.:,;(*!?') ff fl fi ffi ffl  " \
    402         #                  --text "  The quick brown fox jumps over the lazy dog.  " \
    403         #                  "${FPATH}";
    404         #     then
    405         #         convert -- "${preview_png}" "${IMAGE_CACHE_PATH}" \
    406         #             && rm "${preview_png}" \
    407         #             && exit 6
    408         #     else
    409         #         exit 1
    410         #     fi
    411         #     ;;
    412 
    413         ## Preview archives using the first image inside.
    414         ## (Very useful for comic book collections for example.)
    415         # application/zip|application/x-rar|application/x-7z-compressed|\
    416         #     application/x-xz|application/x-bzip2|application/x-gzip|application/x-tar)
    417         #     local fn=""; local fe=""
    418         #     local zip=""; local rar=""; local tar=""; local bsd=""
    419         #     case "${mimetype}" in
    420         #         application/zip) zip=1 ;;
    421         #         application/x-rar) rar=1 ;;
    422         #         application/x-7z-compressed) ;;
    423         #         *) tar=1 ;;
    424         #     esac
    425         #     { [ "$tar" ] && fn=$(tar --list --file "${FPATH}"); } || \
    426         #     { fn=$(bsdtar --list --file "${FPATH}") && bsd=1 && tar=""; } || \
    427         #     { [ "$rar" ] && fn=$(unrar lb -p- -- "${FPATH}"); } || \
    428         #     { [ "$zip" ] && fn=$(zipinfo -1 -- "${FPATH}"); } || return
    429         #
    430         #     fn=$(echo "$fn" | python -c "import sys; import mimetypes as m; \
    431         #             [ print(l, end='') for l in sys.stdin if \
    432         #               (m.guess_type(l[:-1])[0] or '').startswith('image/') ]" |\
    433         #         sort -V | head -n 1)
    434         #     [ "$fn" = "" ] && return
    435         #     [ "$bsd" ] && fn=$(printf '%b' "$fn")
    436         #
    437         #     [ "$tar" ] && tar --extract --to-stdout \
    438         #         --file "${FPATH}" -- "$fn" > "${IMAGE_CACHE_PATH}" && exit 6
    439         #     fe=$(echo -n "$fn" | sed 's/[][*?\]/\\\0/g')
    440         #     [ "$bsd" ] && bsdtar --extract --to-stdout \
    441         #         --file "${FPATH}" -- "$fe" > "${IMAGE_CACHE_PATH}" && exit 6
    442         #     [ "$bsd" ] || [ "$tar" ] && rm -- "${IMAGE_CACHE_PATH}"
    443         #     [ "$rar" ] && unrar p -p- -inul -- "${FPATH}" "$fn" > \
    444         #         "${IMAGE_CACHE_PATH}" && exit 6
    445         #     [ "$zip" ] && unzip -pP "" -- "${FPATH}" "$fe" > \
    446         #         "${IMAGE_CACHE_PATH}" && exit 6
    447         #     [ "$rar" ] || [ "$zip" ] && rm -- "${IMAGE_CACHE_PATH}"
    448         #     ;;
    449     esac
    450 }
    451 
    452 handle_mime() {
    453     mimetype="${1}"
    454     case "${mimetype}" in
    455         ## Manpages
    456         text/troff)
    457             man -l "${FPATH}"
    458             exit 0;;
    459 
    460         ## Text
    461         text/* | */xml)
    462             "$EDITOR" "${FPATH}"
    463             exit 0;;
    464             ## Syntax highlight
    465             # if [[ "$( stat --printf='%s' -- "${FPATH}" )" -gt "${HIGHLIGHT_SIZE_MAX}" ]]; then
    466             #     exit 2
    467             # fi
    468             # if [[ "$( tput colors )" -ge 256 ]]; then
    469             #     local pygmentize_format='terminal256'
    470             #     local highlight_format='xterm256'
    471             # else
    472             #     local pygmentize_format='terminal'
    473             #     local highlight_format='ansi'
    474             # fi
    475             # env HIGHLIGHT_OPTIONS="${HIGHLIGHT_OPTIONS}" highlight \
    476             #     --out-format="${highlight_format}" \
    477             #     --force -- "${FPATH}" && exit 5
    478             # pygmentize -f "${pygmentize_format}" -O "style=${PYGMENTIZE_STYLE}"\
    479             #     -- "${FPATH}" && exit 5
    480             # exit 2;;
    481 
    482         ## DjVu
    483         image/vnd.djvu)
    484             if type djvutxt >/dev/null 2>&1; then
    485                 ## Preview as text conversion (requires djvulibre)
    486                 djvutxt "${FPATH}" | eval "$PAGER"
    487                 exit 0
    488             elif type exiftool >/dev/null 2>&1; then
    489                 exiftool "${FPATH}" | eval "$PAGER"
    490                 exit 0
    491             fi
    492             exit 1;;
    493     esac
    494 }
    495 
    496 handle_fallback() {
    497     if [ "$GUI" -ne 0 ]; then
    498         if type xdg-open >/dev/null 2>&1; then
    499             nohup xdg-open "${FPATH}" >/dev/null 2>&1 &
    500             exit 0
    501         elif type open >/dev/null 2>&1; then
    502             nohup open "${FPATH}" >/dev/null 2>&1 &
    503             exit 0
    504         fi
    505     fi
    506 
    507     echo '----- File details -----' && file --dereference --brief -- "${FPATH}"
    508     exit 1
    509 }
    510 
    511 handle_blocked() {
    512     case "${MIMETYPE}" in
    513         application/x-sharedlib)
    514             exit 0;;
    515 
    516         application/x-shared-library-la)
    517             exit 0;;
    518 
    519         application/x-executable)
    520             exit 0;;
    521 
    522         application/x-shellscript)
    523             exit 0;;
    524 
    525         application/octet-stream)
    526             exit 0;;
    527     esac
    528 }
    529 
    530 handle_bin() {
    531     case "${MIMETYPE}" in
    532         application/x-executable|application/x-shellscript)
    533         clear
    534         echo '-------- Executable File --------' && file --dereference --brief -- "${FPATH}"
    535         printf "Run executable (y/N/'a'rgs)? "
    536         read -r answer
    537         case "$answer" in
    538             [Yy]* ) exec "${FPATH}";;
    539             [Aa]* )
    540                 printf "args: "
    541                 read -r args
    542                 exec "${FPATH}" "$args";;
    543             [Nn]* ) exit;;
    544         esac
    545     esac
    546 }
    547 
    548 MIMETYPE="$( file -bL --mime-type -- "${FPATH}" )"
    549 handle_extension
    550 handle_multimedia "${MIMETYPE}"
    551 handle_mime "${MIMETYPE}"
    552 [ "$BIN" -ne 0 ] && [ -x "${FPATH}" ] && handle_bin
    553 handle_blocked "${MIMETYPE}"
    554 handle_fallback
    555 
    556 exit 1