sistema_progs

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

nuke (18755B)


      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         if is_mac; then
    132             nohup open "${FPATH}" >/dev/null 2>&1 &
    133         elif type smplayer >/dev/null 2>&1; then
    134             nohup smplayer "${FPATH}" >/dev/null 2>&1 &
    135         elif type mpv >/dev/null 2>&1; then
    136             nohup mpv "${FPATH}" >/dev/null 2>&1 &
    137         else
    138             return
    139         fi
    140     elif type ffmpegthumbnailer >/dev/null 2>&1; then
    141         # Thumbnail
    142         [ -d "${IMAGE_CACHE_PATH}" ] || mkdir "${IMAGE_CACHE_PATH}"
    143         ffmpegthumbnailer -i "${FPATH}" -o "${IMAGE_CACHE_PATH}/${FNAME}.jpg" -s 0
    144         viu -n "${IMAGE_CACHE_PATH}/${FNAME}.jpg" | eval "$PAGER"
    145     elif type mediainfo >/dev/null 2>&1; then
    146         mediainfo "${FPATH}" | eval "$PAGER"
    147     elif type exiftool >/dev/null 2>&1; then
    148         exiftool "${FPATH}"| eval "$PAGER"
    149     else
    150         return
    151     fi
    152     exit 0
    153 }
    154 
    155 # handle this extension and exit
    156 handle_extension() {
    157     case "${ext}" in
    158         ## Archive
    159         a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|\
    160         rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z|zip)
    161             if type atool >/dev/null 2>&1; then
    162                 atool --list -- "${FPATH}" | eval "$PAGER"
    163                 exit 0
    164             elif type bsdtar >/dev/null 2>&1; then
    165                 bsdtar --list --file "${FPATH}" | eval "$PAGER"
    166                 exit 0
    167             fi
    168             exit 1;;
    169         rar)
    170             if type unrar >/dev/null 2>&1; then
    171                 ## Avoid password prompt by providing empty password
    172                 unrar lt -p- -- "${FPATH}" | eval "$PAGER"
    173             fi
    174             exit 1;;
    175         7z)
    176             if type 7z >/dev/null 2>&1; then
    177                 ## Avoid password prompt by providing empty password
    178                 7z l -p -- "${FPATH}" | eval "$PAGER"
    179                 exit 0
    180             fi
    181             exit 1;;
    182 
    183         ## PDF
    184         pdf)
    185             handle_pdf
    186             exit 1;;
    187 
    188         ## Audio
    189         aac|flac|m4a|mid|midi|mpa|mp2|mp3|ogg|wav|wma)
    190             handle_audio
    191             exit 1;;
    192 
    193         ## Video
    194         avi|mkv|mp4)
    195             handle_video
    196             exit 1;;
    197 
    198         ## Log files
    199         log)
    200             "$EDITOR" "${FPATH}"
    201             exit 0;;
    202 
    203         ## BitTorrent
    204         torrent)
    205             if type rtorrent >/dev/null 2>&1; then
    206                 rtorrent "${FPATH}"
    207                 exit 0
    208             elif type transmission-show >/dev/null 2>&1; then
    209                 transmission-show -- "${FPATH}"
    210                 exit 0
    211             fi
    212             exit 1;;
    213 
    214         ## OpenDocument
    215         odt|ods|odp|sxw)
    216             if type odt2txt >/dev/null 2>&1; then
    217                 ## Preview as text conversion
    218                 odt2txt "${FPATH}" | eval "$PAGER"
    219                 exit 0
    220             fi
    221             exit 1;;
    222 
    223         ## Markdown
    224         md)
    225             if type glow >/dev/null 2>&1; then
    226                 glow -sdark "${FPATH}" | eval "$PAGER"
    227                 exit 0
    228             elif type lowdown >/dev/null 2>&1; then
    229                 lowdown -Tterm "${FPATH}" | eval "$PAGER"
    230                 exit 0
    231             fi
    232             ;;
    233 
    234         ## HTML
    235         htm|html|xhtml)
    236             ## Preview as text conversion
    237             if type w3m >/dev/null 2>&1; then
    238                 w3m -dump "${FPATH}" | eval "$PAGER"
    239                 exit 0
    240             elif type lynx >/dev/null 2>&1; then
    241                 lynx -dump -- "${FPATH}" | eval "$PAGER"
    242                 exit 0
    243             elif type elinks >/dev/null 2>&1; then
    244                 elinks -dump "${FPATH}" | eval "$PAGER"
    245                 exit 0
    246             fi
    247             ;;
    248 
    249         ## JSON
    250         json)
    251             if type jq >/dev/null 2>&1; then
    252                 jq --color-output . "${FPATH}" | eval "$PAGER"
    253                 exit 0
    254             elif type python >/dev/null 2>&1; then
    255                 python -m json.tool -- "${FPATH}" | eval "$PAGER"
    256                 exit 0
    257             fi
    258             ;;
    259     esac
    260 }
    261 
    262 # sets the variable abs_target, this should be faster than calling printf
    263 abspath() {
    264     case "$1" in
    265         /*) abs_target="$1";;
    266         *)  abs_target="$PWD/$1";;
    267     esac
    268 }
    269 
    270 # storing the result to a tmp file is faster than calling listimages twice
    271 listimages() {
    272     find -L "///${1%/*}" -maxdepth 1 -type f -print0 |
    273         grep -izZE '\.(jpe?g|png|gif|webp|tiff|bmp|ico|svg)$' |
    274         sort -z | tee "$tmp"
    275 }
    276 
    277 load_dir() {
    278     abspath "$2"
    279     tmp="${TMPDIR:-/tmp}/nuke_$$"
    280     trap 'rm -f $tmp' EXIT
    281     count="$(listimages "$abs_target" | grep -a -m 1 -ZznF "$abs_target" | cut -d: -f1)"
    282 
    283     if [ -n "$count" ]; then
    284         if [ "$GUI" -ne 0 ]; then
    285             xargs -0 nohup "$1" -n "$count" -- < "$tmp"
    286         else
    287             xargs -0 "$1" -n "$count" -- < "$tmp"
    288         fi
    289     else
    290         shift
    291         "$1" -- "$@" # fallback
    292     fi
    293 }
    294 
    295 handle_multimedia() {
    296     ## Size of the preview if there are multiple options or it has to be
    297     ## rendered from vector graphics. If the conversion program allows
    298     ## specifying only one dimension while keeping the aspect ratio, the width
    299     ## will be used.
    300     # local DEFAULT_SIZE="1920x1080"
    301 
    302     mimetype="${1}"
    303     case "${mimetype}" in
    304         ## SVG
    305         # image/svg+xml|image/svg)
    306         #     convert -- "${FPATH}" "${IMAGE_CACHE_PATH}" && exit 6
    307         #     exit 1;;
    308 
    309         ## DjVu
    310         # image/vnd.djvu)
    311         #     ddjvu -format=tiff -quality=90 -page=1 -size="${DEFAULT_SIZE}" \
    312         #           - "${IMAGE_CACHE_PATH}" < "${FPATH}" \
    313         #           && exit 6 || exit 1;;
    314 
    315         ## Image
    316         image/*)
    317             if [ "$GUI" -ne 0 ]; then
    318                 if is_mac; then
    319                     nohup open "${FPATH}" >/dev/null 2>&1 &
    320                     exit 0
    321                 elif type imv >/dev/null 2>&1; then
    322                     load_dir imv "${FPATH}" >/dev/null 2>&1 &
    323                     exit 0
    324                 elif type imvr >/dev/null 2>&1; then
    325                     load_dir imvr "${FPATH}" >/dev/null 2>&1 &
    326                     exit 0
    327                 elif type sxiv >/dev/null 2>&1; then
    328                     load_dir sxiv "${FPATH}" >/dev/null 2>&1 &
    329                     exit 0
    330                 elif type nsxiv >/dev/null 2>&1; then
    331                     load_dir nsxiv "${FPATH}" >/dev/null 2>&1 &
    332                     exit 0
    333                 fi
    334             elif type viu >/dev/null 2>&1; then
    335                 viu -n "${FPATH}" | eval "$PAGER"
    336                 exit 0
    337             elif type img2txt >/dev/null 2>&1; then
    338                 img2txt --gamma=0.6 -- "${FPATH}" | eval "$PAGER"
    339                 exit 0
    340             elif type exiftool >/dev/null 2>&1; then
    341                 exiftool "${FPATH}" | eval "$PAGER"
    342                 exit 0
    343             fi
    344             # local orientation
    345             # orientation="$( identify -format '%[EXIF:Orientation]\n' -- "${FPATH}" )"
    346             ## If orientation data is present and the image actually
    347             ## needs rotating ("1" means no rotation)...
    348             # if [[ -n "$orientation" && "$orientation" != 1 ]]; then
    349                 ## ...auto-rotate the image according to the EXIF data.
    350                 # convert -- "${FPATH}" -auto-orient "${IMAGE_CACHE_PATH}" && exit 6
    351             # fi
    352 
    353             ## `w3mimgdisplay` will be called for all images (unless overridden
    354             ## as above), but might fail for unsupported types.
    355             exit 7;;
    356 
    357         ## PDF
    358         application/pdf)
    359             handle_pdf
    360             exit 1;;
    361 
    362         ## Audio
    363         audio/*)
    364             handle_audio
    365             exit 1;;
    366 
    367         ## Video
    368         video/*)
    369             handle_video
    370             exit 1;;
    371 
    372         #     pdftoppm -f 1 -l 1 \
    373         #              -scale-to-x "${DEFAULT_SIZE%x*}" \
    374         #              -scale-to-y -1 \
    375         #              -singlefile \
    376         #              -jpeg -tiffcompression jpeg \
    377         #              -- "${FPATH}" "${IMAGE_CACHE_PATH%.*}" \
    378         #         && exit 6 || exit 1;;
    379 
    380 
    381         ## ePub, MOBI, FB2 (using Calibre)
    382         # application/epub+zip|application/x-mobipocket-ebook|\
    383         # application/x-fictionbook+xml)
    384         #     # ePub (using https://github.com/marianosimone/epub-thumbnailer)
    385         #     epub-thumbnailer "${FPATH}" "${IMAGE_CACHE_PATH}" \
    386         #         "${DEFAULT_SIZE%x*}" && exit 6
    387         #     ebook-meta --get-cover="${IMAGE_CACHE_PATH}" -- "${FPATH}" \
    388         #         >/dev/null && exit 6
    389         #     exit 1;;
    390 
    391         ## Font
    392         # application/font*|application/*opentype)
    393         #     preview_png="/tmp/$(basename "${IMAGE_CACHE_PATH%.*}").png"
    394         #     if fontimage -o "${preview_png}" \
    395         #                  --pixelsize "120" \
    396         #                  --fontname \
    397         #                  --pixelsize "80" \
    398         #                  --text "  ABCDEFGHIJKLMNOPQRSTUVWXYZ  " \
    399         #                  --text "  abcdefghijklmnopqrstuvwxyz  " \
    400         #                  --text "  0123456789.:,;(*!?') ff fl fi ffi ffl  " \
    401         #                  --text "  The quick brown fox jumps over the lazy dog.  " \
    402         #                  "${FPATH}";
    403         #     then
    404         #         convert -- "${preview_png}" "${IMAGE_CACHE_PATH}" \
    405         #             && rm "${preview_png}" \
    406         #             && exit 6
    407         #     else
    408         #         exit 1
    409         #     fi
    410         #     ;;
    411 
    412         ## Preview archives using the first image inside.
    413         ## (Very useful for comic book collections for example.)
    414         # application/zip|application/x-rar|application/x-7z-compressed|\
    415         #     application/x-xz|application/x-bzip2|application/x-gzip|application/x-tar)
    416         #     local fn=""; local fe=""
    417         #     local zip=""; local rar=""; local tar=""; local bsd=""
    418         #     case "${mimetype}" in
    419         #         application/zip) zip=1 ;;
    420         #         application/x-rar) rar=1 ;;
    421         #         application/x-7z-compressed) ;;
    422         #         *) tar=1 ;;
    423         #     esac
    424         #     { [ "$tar" ] && fn=$(tar --list --file "${FPATH}"); } || \
    425         #     { fn=$(bsdtar --list --file "${FPATH}") && bsd=1 && tar=""; } || \
    426         #     { [ "$rar" ] && fn=$(unrar lb -p- -- "${FPATH}"); } || \
    427         #     { [ "$zip" ] && fn=$(zipinfo -1 -- "${FPATH}"); } || return
    428         #
    429         #     fn=$(echo "$fn" | python -c "import sys; import mimetypes as m; \
    430         #             [ print(l, end='') for l in sys.stdin if \
    431         #               (m.guess_type(l[:-1])[0] or '').startswith('image/') ]" |\
    432         #         sort -V | head -n 1)
    433         #     [ "$fn" = "" ] && return
    434         #     [ "$bsd" ] && fn=$(printf '%b' "$fn")
    435         #
    436         #     [ "$tar" ] && tar --extract --to-stdout \
    437         #         --file "${FPATH}" -- "$fn" > "${IMAGE_CACHE_PATH}" && exit 6
    438         #     fe=$(echo -n "$fn" | sed 's/[][*?\]/\\\0/g')
    439         #     [ "$bsd" ] && bsdtar --extract --to-stdout \
    440         #         --file "${FPATH}" -- "$fe" > "${IMAGE_CACHE_PATH}" && exit 6
    441         #     [ "$bsd" ] || [ "$tar" ] && rm -- "${IMAGE_CACHE_PATH}"
    442         #     [ "$rar" ] && unrar p -p- -inul -- "${FPATH}" "$fn" > \
    443         #         "${IMAGE_CACHE_PATH}" && exit 6
    444         #     [ "$zip" ] && unzip -pP "" -- "${FPATH}" "$fe" > \
    445         #         "${IMAGE_CACHE_PATH}" && exit 6
    446         #     [ "$rar" ] || [ "$zip" ] && rm -- "${IMAGE_CACHE_PATH}"
    447         #     ;;
    448     esac
    449 }
    450 
    451 handle_mime() {
    452     mimetype="${1}"
    453     case "${mimetype}" in
    454         ## Manpages
    455         text/troff)
    456             man -l "${FPATH}"
    457             exit 0;;
    458 
    459         ## Text
    460         text/* | */xml)
    461             "$EDITOR" "${FPATH}"
    462             exit 0;;
    463             ## Syntax highlight
    464             # if [[ "$( stat --printf='%s' -- "${FPATH}" )" -gt "${HIGHLIGHT_SIZE_MAX}" ]]; then
    465             #     exit 2
    466             # fi
    467             # if [[ "$( tput colors )" -ge 256 ]]; then
    468             #     local pygmentize_format='terminal256'
    469             #     local highlight_format='xterm256'
    470             # else
    471             #     local pygmentize_format='terminal'
    472             #     local highlight_format='ansi'
    473             # fi
    474             # env HIGHLIGHT_OPTIONS="${HIGHLIGHT_OPTIONS}" highlight \
    475             #     --out-format="${highlight_format}" \
    476             #     --force -- "${FPATH}" && exit 5
    477             # pygmentize -f "${pygmentize_format}" -O "style=${PYGMENTIZE_STYLE}"\
    478             #     -- "${FPATH}" && exit 5
    479             # exit 2;;
    480 
    481         ## DjVu
    482         image/vnd.djvu)
    483             if type djvutxt >/dev/null 2>&1; then
    484                 ## Preview as text conversion (requires djvulibre)
    485                 djvutxt "${FPATH}" | eval "$PAGER"
    486                 exit 0
    487             elif type exiftool >/dev/null 2>&1; then
    488                 exiftool "${FPATH}" | eval "$PAGER"
    489                 exit 0
    490             fi
    491             exit 1;;
    492     esac
    493 }
    494 
    495 handle_fallback() {
    496     if [ "$GUI" -ne 0 ]; then
    497         if type xdg-open >/dev/null 2>&1; then
    498             nohup xdg-open "${FPATH}" >/dev/null 2>&1 &
    499             exit 0
    500         elif type open >/dev/null 2>&1; then
    501             nohup open "${FPATH}" >/dev/null 2>&1 &
    502             exit 0
    503         fi
    504     fi
    505 
    506     echo '----- File details -----' && file --dereference --brief -- "${FPATH}"
    507     exit 1
    508 }
    509 
    510 handle_blocked() {
    511     case "${MIMETYPE}" in
    512         application/x-sharedlib)
    513             exit 0;;
    514 
    515         application/x-shared-library-la)
    516             exit 0;;
    517 
    518         application/x-executable)
    519             exit 0;;
    520 
    521         application/x-shellscript)
    522             exit 0;;
    523 
    524         application/octet-stream)
    525             exit 0;;
    526     esac
    527 }
    528 
    529 handle_bin() {
    530     case "${MIMETYPE}" in
    531         application/x-executable|application/x-shellscript)
    532         clear
    533         echo '-------- Executable File --------' && file --dereference --brief -- "${FPATH}"
    534         printf "Run executable (y/N/'a'rgs)? "
    535         read -r answer
    536         case "$answer" in
    537             [Yy]* ) exec "${FPATH}";;
    538             [Aa]* )
    539                 printf "args: "
    540                 read -r args
    541                 exec "${FPATH}" "$args";;
    542             [Nn]* ) exit;;
    543         esac
    544     esac
    545 }
    546 
    547 MIMETYPE="$( file -bL --mime-type -- "${FPATH}" )"
    548 handle_extension
    549 handle_multimedia "${MIMETYPE}"
    550 handle_mime "${MIMETYPE}"
    551 [ "$BIN" -ne 0 ] && [ -x "${FPATH}" ] && handle_bin
    552 handle_blocked "${MIMETYPE}"
    553 handle_fallback
    554 
    555 exit 1