sistema_progs

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

nuke (18816B)


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