My build of nnn with minor changes
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

212 wiersze
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