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.
 
 
 
 
 
 

444 lignes
16 KiB

  1. #!/usr/bin/env sh
  2. # #############################################################################
  3. # Description: Sample script to play files in apps by file type or mime
  4. #
  5. # Shell: POSIX compliant
  6. # Usage: nuke filepath
  7. #
  8. # Integration with nnn:
  9. # 1. Export the required config:
  10. # export NNN_OPENER=/absolute/path/to/nuke
  11. # # Otherwise, if nuke is in $PATH
  12. # # export NNN_OPENER=nuke
  13. # 2. Run nnn with the program option to indicate a CLI opener
  14. # nnn -c
  15. # 3. nuke can use nnn plugins (e.g. mocplay is used for audio), $PATH is updated.
  16. #
  17. # Details:
  18. # Inspired by ranger's scope.sh, modified for usage with nnn.
  19. #
  20. # Guards against accidentally opening mime types like executables, shared libs etc.
  21. #
  22. # Tries to play 'file' (1st argument) in the following order:
  23. # i. by extension
  24. # ii. by mime (image, video, audio, pdf)
  25. # iii. by mime (other file types)
  26. #
  27. # Modification tips:
  28. # 1. Invokes CLI utilities by default. Set GUI to 1 to enable GUI apps.
  29. # 2. PAGER is "less -R".
  30. # 3. Start GUI apps in bg to unblock. Redirect stdout and strerr if required.
  31. # 4. Some CLI utilities are piped to the $PAGER, to wait and quit uniformly.
  32. # 5. If the output cannot be paged use "read -r _" to wait for user input.
  33. # 6. On a DE, try 'xdg-open' in handle_fallback() as last resort.
  34. #
  35. # Feel free to change the utilities to your favourites and add more mimes.
  36. #
  37. # Defaults:
  38. # By extension (only the enbaled ones):
  39. # most archives: list with atool, bsdtar
  40. # rar: list with unrar
  41. # 7-zip: list with 7z
  42. # pdf: zathura (GUI), pdftotext, mutool, exiftool
  43. # m4a: mocplay (nnn plugin using MOC), mpv, mediainfo, exiftool
  44. # torrent: transmission-show
  45. # odt|ods|odp|sxw: odt2txt
  46. # htm|html|xhtml: w3m, lynx, elinks
  47. # json: jq, python (json.tool module)
  48. # Multimedia by mime:
  49. # image/*: sxiv (GUI), viu, img2txt, exiftool
  50. # video/*: smplayer, mpv (GUI), ffmpegthumbnailer, mediainfo, exiftool
  51. # audio/*: mocplay (nnn plugin using MOC), mpv, mediainfo, exiftool
  52. # application/pdf: zathura (GUI), pdftotext, mutool, exiftool
  53. # Other mimes:
  54. # text/* | */xml: vi
  55. # image/vnd.djvu): djvutxt, exiftool
  56. #
  57. # ToDo:
  58. # 1. Adapt, test and enable all mimes
  59. # 2. Clean-up unnecessary the exit codes
  60. # #############################################################################
  61. # set to 1 to enable GUI apps
  62. GUI=0
  63. set -euf -o noclobber -o noglob -o nounset
  64. IFS="$(printf '%b_' '\n')"; IFS="${IFS%_}" # protect trailing \n
  65. PATH=$PATH:"${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins"
  66. IMAGE_CACHE_PATH="$(dirname "$1")"/.thumbs
  67. FPATH="$1"
  68. FNAME=$(basename "$1")
  69. ext="${FNAME##*.}"
  70. if ! [ -z "$ext" ]; then
  71. ext="$(printf "%s" "${ext}" | tr '[:upper:]' '[:lower:]')"
  72. fi
  73. # handle this extension and exit
  74. handle_extension() {
  75. case "${ext}" in
  76. ## Archive
  77. a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|\
  78. rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z|zip)
  79. if which atool >/dev/null 2>&1; then
  80. atool --list -- "${FPATH}" | less -R
  81. exit 0
  82. elif which bsdtar >/dev/null 2>&1; then
  83. bsdtar --list --file "${FPATH}" | less -R
  84. exit 0
  85. fi
  86. exit 1;;
  87. rar)
  88. if which unrar >/dev/null 2>&1; then
  89. ## Avoid password prompt by providing empty password
  90. unrar lt -p- -- "${FPATH}" | less -R
  91. fi
  92. exit 1;;
  93. 7z)
  94. if which 7z >/dev/null 2>&1; then
  95. ## Avoid password prompt by providing empty password
  96. 7z l -p -- "${FPATH}" | less -R
  97. exit 0
  98. fi
  99. exit 1;;
  100. ## PDF
  101. pdf)
  102. if [ $GUI -ne 0 ] && which zathura >/dev/null 2>&1; then
  103. zathura "${FPATH}" >/dev/null 2>&1 &
  104. exit 0
  105. elif which pdftotext >/dev/null 2>&1; then
  106. ## Preview as text conversion
  107. pdftotext -l 10 -nopgbrk -q -- "${FPATH}" - | less -R
  108. exit 0
  109. elif which mutool >/dev/null 2>&1; then
  110. mutool draw -F txt -i -- "${FPATH}" 1-10
  111. exit 0
  112. elif which exiftool >/dev/null 2>&1; then
  113. exiftool "${FPATH}" | less -R
  114. exit 0
  115. fi
  116. exit 1;;
  117. ## Audio
  118. aac|flac|m4a|mid|midi|mpa|mp2|mp3|ogg|wav|wma)
  119. if which mocp >/dev/null 2>&1; then
  120. mocplay "${FPATH}" >/dev/null 2>&1
  121. exit 0
  122. elif which mpv >/dev/null 2>&1; then
  123. mpv "${FPATH}" >/dev/null 2>&1 &
  124. exit 0
  125. elif which mediainfo >/dev/null 2>&1; then
  126. mediainfo "${FPATH}" | less -R
  127. exit 0
  128. elif which exiftool >/dev/null 2>&1; then
  129. exiftool "${FPATH}"| less -R
  130. exit 0
  131. fi
  132. exit 1;;
  133. ## BitTorrent
  134. torrent)
  135. if which transmission-show >/dev/null 2>&1; then
  136. transmission-show -- "${FPATH}"
  137. exit 0
  138. fi
  139. exit 1;;
  140. ## OpenDocument
  141. odt|ods|odp|sxw)
  142. if which odt2txt >/dev/null 2>&1; then
  143. ## Preview as text conversion
  144. odt2txt "${FPATH}" | less -R
  145. exit 0
  146. fi
  147. exit 1;;
  148. ## HTML
  149. htm|html|xhtml)
  150. ## Preview as text conversion
  151. if which w3m >/dev/null 2>&1; then
  152. w3m -dump "${FPATH}" | less -R
  153. exit 0
  154. elif which lynx >/dev/null 2>&1; then
  155. lynx -dump -- "${FPATH}" | less -R
  156. exit 0
  157. elif which elinks >/dev/null 2>&1; then
  158. elinks -dump "${FPATH}" | less -R
  159. exit 0
  160. fi
  161. ;;
  162. ## JSON
  163. json)
  164. if which jq >/dev/null 2>&1; then
  165. jq --color-output . "${FPATH}" | less -R
  166. exit 0
  167. elif which python >/dev/null 2>&1; then
  168. python -m json.tool -- "${FPATH}" | less -R
  169. exit 0
  170. fi
  171. ;;
  172. esac
  173. }
  174. handle_multimedia() {
  175. ## Size of the preview if there are multiple options or it has to be
  176. ## rendered from vector graphics. If the conversion program allows
  177. ## specifying only one dimension while keeping the aspect ratio, the width
  178. ## will be used.
  179. # local DEFAULT_SIZE="1920x1080"
  180. mimetype="${1}"
  181. case "${mimetype}" in
  182. ## SVG
  183. # image/svg+xml|image/svg)
  184. # convert -- "${FPATH}" "${IMAGE_CACHE_PATH}" && exit 6
  185. # exit 1;;
  186. ## DjVu
  187. # image/vnd.djvu)
  188. # ddjvu -format=tiff -quality=90 -page=1 -size="${DEFAULT_SIZE}" \
  189. # - "${IMAGE_CACHE_PATH}" < "${FPATH}" \
  190. # && exit 6 || exit 1;;
  191. ## Image
  192. image/*)
  193. if [ $GUI -ne 0 ] && which sxiv >/dev/null 2>&1; then
  194. sxiv -q "${FPATH}" &
  195. exit 0
  196. elif which viu >/dev/null 2>&1; then
  197. viu -n "${FPATH}" | less -R
  198. exit 0
  199. elif which img2txt >/dev/null 2>&1; then
  200. img2txt --gamma=0.6 -- "${FPATH}" | less -R
  201. exit 0
  202. elif which exiftool >/dev/null 2>&1; then
  203. exiftool "${FPATH}" | less -R
  204. exit 0
  205. fi
  206. # local orientation
  207. # orientation="$( identify -format '%[EXIF:Orientation]\n' -- "${FPATH}" )"
  208. ## If orientation data is present and the image actually
  209. ## needs rotating ("1" means no rotation)...
  210. # if [[ -n "$orientation" && "$orientation" != 1 ]]; then
  211. ## ...auto-rotate the image according to the EXIF data.
  212. # convert -- "${FPATH}" -auto-orient "${IMAGE_CACHE_PATH}" && exit 6
  213. # fi
  214. ## `w3mimgdisplay` will be called for all images (unless overriden
  215. ## as above), but might fail for unsupported types.
  216. exit 7;;
  217. ## Video
  218. video/*)
  219. if [ $GUI -ne 0 ] && which smplayer >/dev/null 2>&1; then
  220. smplayer "${FPATH}" >/dev/null 2>&1 &
  221. exit 0
  222. elif [ $GUI -ne 0 ] && which mpv >/dev/null 2>&1; then
  223. mpv "${FPATH}" >/dev/null 2>&1 &
  224. exit 0
  225. elif which ffmpegthumbnailer >/dev/null 2>&1; then
  226. # Thumbnail
  227. [ -d "${IMAGE_CACHE_PATH}" ] || mkdir "${IMAGE_CACHE_PATH}"
  228. ffmpegthumbnailer -i "${FPATH}" -o "${IMAGE_CACHE_PATH}/${FNAME}.jpg" -s 0
  229. viu -n "${IMAGE_CACHE_PATH}/${FNAME}.jpg" | less -R
  230. exit 0
  231. elif which mediainfo >/dev/null 2>&1; then
  232. mediainfo "${FPATH}" | less -R
  233. exit 0
  234. elif which exiftool >/dev/null 2>&1; then
  235. exiftool "${FPATH}"| less -R
  236. exit 0
  237. fi
  238. exit 1;;
  239. ## Audio
  240. audio/*)
  241. if which mocp >/dev/null 2>&1; then
  242. mocplay "${FPATH}" >/dev/null 2>&1
  243. exit 0
  244. elif which mpv >/dev/null 2>&1; then
  245. mpv "${FPATH}" >/dev/null 2>&1 &
  246. exit 0
  247. elif which mediainfo >/dev/null 2>&1; then
  248. mediainfo "${FPATH}" | less -R
  249. exit 0
  250. elif which exiftool >/dev/null 2>&1; then
  251. exiftool "${FPATH}"| less -R
  252. exit 0
  253. fi
  254. exit 1;;
  255. ## PDF
  256. application/pdf)
  257. if [ $GUI -ne 0 ] && which zathura >/dev/null 2>&1; then
  258. zathura "${FPATH}" >/dev/null 2>&1 &
  259. exit 0
  260. elif which pdftotext >/dev/null 2>&1; then
  261. ## Preview as text conversion
  262. pdftotext -l 10 -nopgbrk -q -- "${FPATH}" - | less -R
  263. exit 0
  264. elif which mutool >/dev/null 2>&1; then
  265. mutool draw -F txt -i -- "${FPATH}" 1-10 | less -R
  266. exit 0
  267. elif which exiftool >/dev/null 2>&1; then
  268. exiftool "${FPATH}" | less -R
  269. exit 0
  270. fi
  271. exit 1;;
  272. # pdftoppm -f 1 -l 1 \
  273. # -scale-to-x "${DEFAULT_SIZE%x*}" \
  274. # -scale-to-y -1 \
  275. # -singlefile \
  276. # -jpeg -tiffcompression jpeg \
  277. # -- "${FPATH}" "${IMAGE_CACHE_PATH%.*}" \
  278. # && exit 6 || exit 1;;
  279. ## ePub, MOBI, FB2 (using Calibre)
  280. # application/epub+zip|application/x-mobipocket-ebook|\
  281. # application/x-fictionbook+xml)
  282. # # ePub (using https://github.com/marianosimone/epub-thumbnailer)
  283. # epub-thumbnailer "${FPATH}" "${IMAGE_CACHE_PATH}" \
  284. # "${DEFAULT_SIZE%x*}" && exit 6
  285. # ebook-meta --get-cover="${IMAGE_CACHE_PATH}" -- "${FPATH}" \
  286. # >/dev/null && exit 6
  287. # exit 1;;
  288. ## Font
  289. # application/font*|application/*opentype)
  290. # preview_png="/tmp/$(basename "${IMAGE_CACHE_PATH%.*}").png"
  291. # if fontimage -o "${preview_png}" \
  292. # --pixelsize "120" \
  293. # --fontname \
  294. # --pixelsize "80" \
  295. # --text " ABCDEFGHIJKLMNOPQRSTUVWXYZ " \
  296. # --text " abcdefghijklmnopqrstuvwxyz " \
  297. # --text " 0123456789.:,;(*!?') ff fl fi ffi ffl " \
  298. # --text " The quick brown fox jumps over the lazy dog. " \
  299. # "${FPATH}";
  300. # then
  301. # convert -- "${preview_png}" "${IMAGE_CACHE_PATH}" \
  302. # && rm "${preview_png}" \
  303. # && exit 6
  304. # else
  305. # exit 1
  306. # fi
  307. # ;;
  308. ## Preview archives using the first image inside.
  309. ## (Very useful for comic book collections for example.)
  310. # application/zip|application/x-rar|application/x-7z-compressed|\
  311. # application/x-xz|application/x-bzip2|application/x-gzip|application/x-tar)
  312. # local fn=""; local fe=""
  313. # local zip=""; local rar=""; local tar=""; local bsd=""
  314. # case "${mimetype}" in
  315. # application/zip) zip=1 ;;
  316. # application/x-rar) rar=1 ;;
  317. # application/x-7z-compressed) ;;
  318. # *) tar=1 ;;
  319. # esac
  320. # { [ "$tar" ] && fn=$(tar --list --file "${FPATH}"); } || \
  321. # { fn=$(bsdtar --list --file "${FPATH}") && bsd=1 && tar=""; } || \
  322. # { [ "$rar" ] && fn=$(unrar lb -p- -- "${FPATH}"); } || \
  323. # { [ "$zip" ] && fn=$(zipinfo -1 -- "${FPATH}"); } || return
  324. #
  325. # fn=$(echo "$fn" | python -c "import sys; import mimetypes as m; \
  326. # [ print(l, end='') for l in sys.stdin if \
  327. # (m.guess_type(l[:-1])[0] or '').startswith('image/') ]" |\
  328. # sort -V | head -n 1)
  329. # [ "$fn" = "" ] && return
  330. # [ "$bsd" ] && fn=$(printf '%b' "$fn")
  331. #
  332. # [ "$tar" ] && tar --extract --to-stdout \
  333. # --file "${FPATH}" -- "$fn" > "${IMAGE_CACHE_PATH}" && exit 6
  334. # fe=$(echo -n "$fn" | sed 's/[][*?\]/\\\0/g')
  335. # [ "$bsd" ] && bsdtar --extract --to-stdout \
  336. # --file "${FPATH}" -- "$fe" > "${IMAGE_CACHE_PATH}" && exit 6
  337. # [ "$bsd" ] || [ "$tar" ] && rm -- "${IMAGE_CACHE_PATH}"
  338. # [ "$rar" ] && unrar p -p- -inul -- "${FPATH}" "$fn" > \
  339. # "${IMAGE_CACHE_PATH}" && exit 6
  340. # [ "$zip" ] && unzip -pP "" -- "${FPATH}" "$fe" > \
  341. # "${IMAGE_CACHE_PATH}" && exit 6
  342. # [ "$rar" ] || [ "$zip" ] && rm -- "${IMAGE_CACHE_PATH}"
  343. # ;;
  344. esac
  345. }
  346. handle_mime() {
  347. mimetype="${1}"
  348. case "${mimetype}" in
  349. ## Text
  350. text/* | */xml)
  351. vi "${FPATH}"
  352. exit 1;;
  353. ## Syntax highlight
  354. # if [[ "$( stat --printf='%s' -- "${FPATH}" )" -gt "${HIGHLIGHT_SIZE_MAX}" ]]; then
  355. # exit 2
  356. # fi
  357. # if [[ "$( tput colors )" -ge 256 ]]; then
  358. # local pygmentize_format='terminal256'
  359. # local highlight_format='xterm256'
  360. # else
  361. # local pygmentize_format='terminal'
  362. # local highlight_format='ansi'
  363. # fi
  364. # env HIGHLIGHT_OPTIONS="${HIGHLIGHT_OPTIONS}" highlight \
  365. # --out-format="${highlight_format}" \
  366. # --force -- "${FPATH}" && exit 5
  367. # pygmentize -f "${pygmentize_format}" -O "style=${PYGMENTIZE_STYLE}"\
  368. # -- "${FPATH}" && exit 5
  369. # exit 2;;
  370. ## DjVu
  371. image/vnd.djvu)
  372. if which djvutxt >/dev/null 2>&1; then
  373. ## Preview as text conversion (requires djvulibre)
  374. djvutxt "${FPATH}" | less -R
  375. exit 0
  376. elif which exiftool >/dev/null 2>&1; then
  377. exiftool "${FPATH}" | less -R
  378. exit 0
  379. fi
  380. exit 1;;
  381. esac
  382. }
  383. handle_fallback() {
  384. if [ $GUI -ne 0 ]; then
  385. xdg-open "${FPATH}" >/dev/null 2>&1 &
  386. exit 0
  387. fi
  388. echo '----- File details -----' && file --dereference --brief -- "${FPATH}"
  389. exit 1
  390. }
  391. handle_blocked() {
  392. case "${MIMETYPE}" in
  393. application/x-sharedlib)
  394. exit 0;;
  395. application/x-shared-library-la)
  396. exit 0;;
  397. application/x-executable)
  398. exit 0;;
  399. application/x-shellscript)
  400. exit 0;;
  401. esac
  402. }
  403. MIMETYPE="$( file --dereference --brief --mime-type -- "${FPATH}" )"
  404. handle_blocked "${MIMETYPE}"
  405. handle_extension
  406. handle_multimedia "${MIMETYPE}"
  407. handle_mime "${MIMETYPE}"
  408. handle_fallback
  409. exit 1