My build of nnn with minor changes
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

212 lignes
5.8 KiB

  1. #!/usr/bin/env bash
  2. # Description: tabbed/xembed based file previewer
  3. #
  4. # Note: This plugin needs a "NNN_FIFO" to work. See man.
  5. #
  6. # Dependencies:
  7. # - tabbed (https://tools.suckless.org/tabbed): xembed host
  8. # - xterm (or urxvt or st) : xembed client for text-based preview
  9. # - mpv (https://mpv.io): xembed client for video/audio
  10. # - sxiv (https://github.com/muennich/sxiv): xembed client for images
  11. # - zathura (https://pwmt.org/projects/zathura): xembed client for PDF documents
  12. # - nnn's nuke plugin for text preview and fallback (should be in plugins directory)
  13. # nuke is a fallback for 'mpv', 'sxiv', and 'zathura', but it has has its own
  14. # dependencies, see the script itself
  15. # - vim (or any editor/pager really)
  16. # - file
  17. # - mktemp
  18. # - xdotool (optional, to keep main window focused)
  19. #
  20. # How to use:
  21. # First, install the dependencies. Then you need to set a NNN_FIFO path
  22. # and set a key for the plugin, then start `nnn`:
  23. #
  24. # $ NNN_FIFO=/tmp/nnn.fifo nnn
  25. #
  26. # Then in `nnn`, launch the `preview-tabbed` plugin.
  27. #
  28. # If you provide the same NNN_FIFO to all nnn instances, there will be a
  29. # single common preview window. I you provide different FIFO path, they
  30. # will be independent.
  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`: image viewer
  41. # - `zathura`: PDF viewer
  42. # - but we allways fallback to `nuke` plugin
  43. #
  44. # [1]: http://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. XDOTOOL_TIMEOUT=2
  50. PAGER=${PAGER:-"vim -R"}
  51. NUKE="${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins/nuke"
  52. if which xterm >/dev/null 2>&1 ; then
  53. TERMINAL="xterm -into"
  54. elif which urxvt >/dev/null 2>&1 ; then
  55. TERMINAL="urxvt -embed"
  56. elif which st >/dev/null 2>&1 ; then
  57. TERMINAL="st -w"
  58. else
  59. echo "No xembed term found" >&2
  60. fi
  61. term_nuke () {
  62. # $1 -> $XID, $2 -> $FILE
  63. $TERMINAL "$1" -e "$NUKE" "$2" &
  64. }
  65. start_tabbed () {
  66. FIFO="$(mktemp -u)"
  67. mkfifo "$FIFO"
  68. tabbed > "$FIFO" &
  69. jobs # Get rid of the "Completed" entries
  70. TABBEDPID="$(jobs -p %%)"
  71. if [ -z "$TABBEDPID" ] ; then
  72. echo "Can't start tabbed"
  73. exit 1
  74. fi
  75. read -r XID < "$FIFO"
  76. rm "$FIFO"
  77. }
  78. get_viewer_pid () {
  79. VIEWERPID="$(jobs -p %%)"
  80. }
  81. kill_viewer () {
  82. if [ -n "$VIEWERPID" ] && jobs -p | grep "$VIEWERPID" ; then
  83. kill "$VIEWERPID"
  84. fi
  85. }
  86. sigint_kill () {
  87. kill_viewer
  88. kill "$TABBEDPID"
  89. exit 0
  90. }
  91. previewer_loop () {
  92. unset -v NNN_FIFO
  93. # mute from now
  94. exec >/dev/null 2>&1
  95. MAINWINDOW="$(xdotool getactivewindow)"
  96. start_tabbed
  97. trap sigint_kill SIGINT
  98. xdotool windowactivate "$MAINWINDOW"
  99. # Bruteforce focus stealing prevention method,
  100. # works well in floating window managers like XFCE
  101. # but make interaction with the preview window harder
  102. # (uncomment to use):
  103. #xdotool behave "$XID" focus windowactivate "$MAINWINDOW" &
  104. while read -r FILE ; do
  105. jobs # Get rid of the "Completed" entries
  106. if ! jobs | grep tabbed ; then
  107. break
  108. fi
  109. if [ ! -e "$FILE" ] ; then
  110. continue
  111. fi
  112. kill_viewer
  113. MIME="$(file -b --mime-type "$FILE")"
  114. case "$MIME" in
  115. video/*)
  116. if which mpv >/dev/null 2>&1 ; then
  117. mpv --force-window=immediate --loop-file --wid="$XID" "$FILE" &
  118. else
  119. term_nuke "$XID" "$FILE"
  120. fi
  121. ;;
  122. audio/*)
  123. if which mpv >/dev/null 2>&1 ; then
  124. mpv --force-window=immediate --loop-file --wid="$XID" "$FILE" &
  125. else
  126. term_nuke "$XID" "$FILE"
  127. fi
  128. ;;
  129. image/*)
  130. if which sxiv >/dev/null 2>&1 ; then
  131. sxiv -e "$XID" "$FILE" &
  132. else
  133. term_nuke "$XID" "$FILE"
  134. fi
  135. ;;
  136. application/pdf)
  137. if which zathura >/dev/null 2>&1 ; then
  138. zathura -e "$XID" "$FILE" &
  139. else
  140. term_nuke "$XID" "$FILE"
  141. fi
  142. ;;
  143. inode/directory)
  144. $TERMINAL "$XID" -e nnn "$FILE" &
  145. ;;
  146. text/*)
  147. if [ -x "$NUKE" ] ; then
  148. term_nuke "$XID" "$FILE"
  149. else
  150. # shellcheck disable=SC2086
  151. $TERMINAL "$XID" -e $PAGER "$FILE" &
  152. fi
  153. ;;
  154. *)
  155. if [ -x "$NUKE" ] ; then
  156. term_nuke "$XID" "$FILE"
  157. else
  158. $TERMINAL "$XID" -e sh -c "file '$FILE' | $PAGER -" &
  159. fi
  160. ;;
  161. esac
  162. get_viewer_pid
  163. # following lines are not needed with the bruteforce xdotool method
  164. ACTIVE_XID="$(xdotool getactivewindow)"
  165. if [ $((ACTIVE_XID == XID)) -ne 0 ] ; then
  166. xdotool windowactivate "$MAINWINDOW"
  167. else
  168. timeout "$XDOTOOL_TIMEOUT" xdotool behave "$XID" focus windowactivate "$MAINWINDOW" &
  169. fi
  170. done
  171. kill "$TABBEDPID"
  172. kill_viewer
  173. }
  174. if [ ! -r "$NNN_FIFO" ] ; then
  175. echo "Can't read \$NNN_FIFO ('$NNN_FIFO')"
  176. exit 1
  177. fi
  178. previewer_loop < "$NNN_FIFO" &
  179. disown