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.

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