sistema_progs

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

preview-tabbed (6258B)


      1 #!/usr/bin/env bash
      2 
      3 # Description: tabbed/xembed based file previewer
      4 #
      5 # Dependencies:
      6 #   - tabbed (https://tools.suckless.org/tabbed): xembed host
      7 #   - xterm (or urxvt or st) : xembed client for text-based preview
      8 #   - mpv (https://mpv.io): xembed client for video/audio
      9 #   - sxiv (https://github.com/muennich/sxiv) or,
     10 #   - nsxiv (https://codeberg.org/nsxiv/nsxiv) : xembed client for images
     11 #   - zathura (https://pwmt.org/projects/zathura): xembed client for PDF
     12 #   - nnn's nuke plugin for text preview and fallback
     13 #     nuke is a fallback for 'mpv', 'sxiv'/'nsxiv', and 'zathura', but has its
     14 #     own dependencies, see the script for more information
     15 #   - vim (or any editor/pager really)
     16 #   - file
     17 #   - mktemp
     18 #   - xdotool (optional, to keep main window focused)
     19 #
     20 # Usage:
     21 #   - Install the dependencies. Then set a NNN_FIFO
     22 #     and set a key for the plugin, then start `nnn`:
     23 #       $ NNN_FIFO=/tmp/nnn.fifo nnn
     24 #   - Launch the plugin with the designated key from nnn
     25 #
     26 # Notes:
     27 #   1. This plugin needs a "NNN_FIFO" to work. See man.
     28 #   2. If the same NNN_FIFO is used in multiple nnn instances, there will be one
     29 #      common preview window. With different FIFO paths, they will be independent.
     30 #   3. This plugin only works on X, not on Wayland.
     31 #
     32 # How it works:
     33 #   We use `tabbed` [1] as a xembed [2] host, to have a single window
     34 #   owning each previewer window. So each previewer must be a xembed client.
     35 #   For text previewers, this is not an issue, as there are a lot of
     36 #   xembed-able terminal emulator (we default to `xterm`, but examples are
     37 #   provided for `urxvt` and `st`). For graphic preview this can be trickier,
     38 #   but a few popular viewers are xembed-able, we use:
     39 #     - `mpv`: multimedia player, for video/audio preview
     40 #     - `sxiv`/`nsxiv`: image viewer
     41 #     - `zathura`: PDF viewer
     42 #     - but we always fallback to `nuke` plugin
     43 #
     44 # [1]: https://tools.suckless.org/tabbed/
     45 # [2]: https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html
     46 #
     47 # Shell: Bash (job control is weakly specified in POSIX)
     48 # Author: Léo Villeveygoux
     49 
     50 
     51 XDOTOOL_TIMEOUT=2
     52 PAGER=${PAGER:-"vim -R"}
     53 NUKE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins/nuke"
     54 
     55 if [ -n "$WAYLAND_DISPLAY" ] ; then
     56     echo "Wayland is not supported in preview-tabbed, this plugin could freeze your session!" >&2
     57     exit 1
     58 fi
     59 
     60 if type xterm >/dev/null 2>&1 ; then
     61     TERMINAL="xterm -into"
     62 elif type urxvt >/dev/null 2>&1 ; then
     63     TERMINAL="urxvt -embed"
     64 elif type st >/dev/null 2>&1 ; then
     65     TERMINAL="st -w"
     66 else
     67     echo "No xembed term found" >&2
     68 fi
     69 
     70 
     71 term_nuke () {
     72     # $1 -> $XID, $2 -> $FILE
     73     $TERMINAL "$1" -e "$NUKE" "$2" &
     74 }
     75 
     76 start_tabbed () {
     77     FIFO="$(mktemp -u)"
     78     mkfifo "$FIFO"
     79 
     80     tabbed > "$FIFO" &
     81 
     82     jobs # Get rid of the "Completed" entries
     83 
     84     TABBEDPID="$(jobs -p %%)"
     85 
     86     if [ -z "$TABBEDPID" ] ; then
     87         echo "Can't start tabbed"
     88         exit 1
     89     fi
     90 
     91     read -r XID < "$FIFO"
     92 
     93     rm "$FIFO"
     94 }
     95 
     96 get_viewer_pid () {
     97         VIEWERPID="$(jobs -p %%)"
     98 }
     99 
    100 kill_viewer () {
    101         if [ -n "$VIEWERPID" ] && jobs -p | grep "$VIEWERPID" ; then
    102             kill "$VIEWERPID"
    103         fi
    104 }
    105 
    106 sigint_kill () {
    107 	kill_viewer
    108 	kill "$TABBEDPID"
    109 	exit 0
    110 }
    111 
    112 previewer_loop () {
    113     unset -v NNN_FIFO
    114     # mute from now
    115     exec >/dev/null 2>&1
    116 
    117     MAINWINDOW="$(xdotool getactivewindow)"
    118 
    119     start_tabbed
    120     trap sigint_kill SIGINT
    121 
    122     xdotool windowactivate "$MAINWINDOW"
    123 
    124     # Bruteforce focus stealing prevention method,
    125     # works well in floating window managers like XFCE
    126     # but make interaction with the preview window harder
    127     # (uncomment to use):
    128     #xdotool behave "$XID" focus windowactivate "$MAINWINDOW" &
    129 
    130     while read -r FILE ; do
    131 
    132         jobs # Get rid of the "Completed" entries
    133 
    134         if ! jobs | grep tabbed ; then
    135             break
    136         fi
    137 
    138         if [ ! -e "$FILE" ] ; then
    139             continue
    140         fi
    141 
    142         kill_viewer
    143 
    144         MIME="$(file -bL --mime-type "$FILE")"
    145 
    146         case "$MIME" in
    147             video/*)
    148                 if type mpv >/dev/null 2>&1 ; then
    149                     mpv --force-window=immediate --loop-file --wid="$XID" "$FILE" &
    150                 else
    151                     term_nuke "$XID" "$FILE"
    152                 fi
    153                 ;;
    154             audio/*)
    155                 if type mpv >/dev/null 2>&1 ; then
    156                     mpv --force-window=immediate --loop-file --wid="$XID" "$FILE" &
    157                 else
    158                     term_nuke "$XID" "$FILE"
    159                 fi
    160                 ;;
    161             image/*)
    162                 if type sxiv >/dev/null 2>&1 ; then
    163                     sxiv -ae "$XID" "$FILE" &
    164                 elif type nsxiv >/dev/null 2>&1 ; then
    165                     nsxiv -ae "$XID" "$FILE" &
    166                 else
    167                     term_nuke "$XID" "$FILE"
    168                 fi
    169                 ;;
    170             application/pdf)
    171                 if type zathura >/dev/null 2>&1 ; then
    172                     zathura -e "$XID" "$FILE" &
    173                 else
    174                     term_nuke "$XID" "$FILE"
    175                 fi
    176                 ;;
    177             inode/directory)
    178                 $TERMINAL "$XID" -e nnn "$FILE" &
    179                 ;;
    180             text/*)
    181                 if [ -x "$NUKE" ] ; then
    182                     term_nuke "$XID" "$FILE"
    183                 else
    184                     # shellcheck disable=SC2086
    185                     $TERMINAL "$XID" -e $PAGER "$FILE" &
    186                 fi
    187                 ;;
    188             *)
    189                 if [ -x "$NUKE" ] ; then
    190                     term_nuke "$XID" "$FILE"
    191                 else
    192                     $TERMINAL "$XID" -e sh -c "file '$FILE' | $PAGER -" &
    193                 fi
    194                 ;;
    195         esac
    196         get_viewer_pid
    197 
    198         # following lines are not needed with the bruteforce xdotool method
    199         ACTIVE_XID="$(xdotool getactivewindow)"
    200         if [ $((ACTIVE_XID == XID)) -ne 0 ] ; then
    201             xdotool windowactivate "$MAINWINDOW"
    202         else
    203             timeout "$XDOTOOL_TIMEOUT" xdotool behave "$XID" focus windowactivate "$MAINWINDOW" &
    204         fi
    205     done
    206     kill "$TABBEDPID"
    207     kill_viewer
    208 }
    209 
    210 if [ ! -r "$NNN_FIFO" ] ; then
    211     echo "Can't read \$NNN_FIFO ('$NNN_FIFO')"
    212     exit 1
    213 fi
    214 
    215 previewer_loop < "$NNN_FIFO" &
    216 disown