"Fossies" - the Fresh Open Source Software Archive

Member "nnn-4.4/plugins/preview-tabbed" (23 Nov 2021, 6056 Bytes) of package /linux/misc/nnn-v4.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Bash source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "preview-tabbed": v4.3_vs_v4.4.

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