My build of nnn with minor changes
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

preview-tabbed 5.7 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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. previewer_loop () {
  87. unset -v NNN_FIFO
  88. # mute from now
  89. exec >/dev/null 2>&1
  90. MAINWINDOW="$(xdotool getactivewindow)"
  91. start_tabbed
  92. xdotool windowactivate "$MAINWINDOW"
  93. # Bruteforce focus stealing prevention method,
  94. # works well in floating window managers like XFCE
  95. # but make interaction with the preview window harder
  96. # (uncomment to use):
  97. #xdotool behave "$XID" focus windowactivate "$MAINWINDOW" &
  98. while read -r FILE ; do
  99. jobs # Get rid of the "Completed" entries
  100. if ! jobs | grep tabbed ; then
  101. break
  102. fi
  103. if [ ! -e "$FILE" ] ; then
  104. continue
  105. fi
  106. kill_viewer
  107. MIME="$(file -b --mime-type "$FILE")"
  108. case "$MIME" in
  109. video/*)
  110. if which mpv >/dev/null 2>&1 ; then
  111. mpv --force-window=immediate --loop-file --wid="$XID" "$FILE" &
  112. else
  113. term_nuke "$XID" "$FILE"
  114. fi
  115. ;;
  116. audio/*)
  117. if which mpv >/dev/null 2>&1 ; then
  118. mpv --force-window=immediate --loop-file --wid="$XID" "$FILE" &
  119. else
  120. term_nuke "$XID" "$FILE"
  121. fi
  122. ;;
  123. image/*)
  124. if which sxiv >/dev/null 2>&1 ; then
  125. sxiv -e "$XID" "$FILE" &
  126. else
  127. term_nuke "$XID" "$FILE"
  128. fi
  129. ;;
  130. application/pdf)
  131. if which zathura >/dev/null 2>&1 ; then
  132. zathura -e "$XID" "$FILE" &
  133. else
  134. term_nuke "$XID" "$FILE"
  135. fi
  136. ;;
  137. inode/directory)
  138. $TERMINAL "$XID" -e nnn "$FILE" &
  139. ;;
  140. text/*)
  141. if [ -x "$NUKE" ] ; then
  142. term_nuke "$XID" "$FILE"
  143. else
  144. # shellcheck disable=SC2086
  145. $TERMINAL "$XID" -e $PAGER "$FILE" &
  146. fi
  147. ;;
  148. *)
  149. if [ -x "$NUKE" ] ; then
  150. term_nuke "$XID" "$FILE"
  151. else
  152. $TERMINAL "$XID" -e sh -c "file '$FILE' | $PAGER -" &
  153. fi
  154. ;;
  155. esac
  156. get_viewer_pid
  157. # following lines are not needed with the bruteforce xdotool method
  158. ACTIVE_XID="$(xdotool getactivewindow)"
  159. if [ $((ACTIVE_XID == XID)) -ne 0 ] ; then
  160. xdotool windowactivate "$MAINWINDOW"
  161. else
  162. timeout "$XDOTOOL_TIMEOUT" xdotool behave "$XID" focus windowactivate "$MAINWINDOW" &
  163. fi
  164. done
  165. kill "$TABBEDPID"
  166. kill_viewer
  167. }
  168. if [ ! -r "$NNN_FIFO" ] ; then
  169. echo "Can't read \$NNN_FIFO ('$NNN_FIFO')"
  170. exit 1
  171. fi
  172. previewer_loop < "$NNN_FIFO" &
  173. disown