Add nplay: a custom opener

This commit is contained in:
Arun Prakash Jana 2019-12-07 22:48:33 +05:30
parent 3b2b6f2b46
commit 5826da920f
No known key found for this signature in database
GPG key ID: A75979F35C080412
7 changed files with 453 additions and 175 deletions

View file

@ -153,7 +153,7 @@ There is no config file. Associated files are stored under `${XDG_CONFIG_HOME:-$
| Example `export` | Description | | Example `export` | Description |
| --- | --- | | --- | --- |
| `NNN_OPENER=mimeopen` | custom file opener | | `NNN_OPENER=nplay` | custom file opener ([nplay](https://github.com/jarun/nnn/blob/master/misc/nplay/nplay)) |
| `NNN_BMS='d:~/Documents;D:~/Docs archive/'` | key-bookmark pairs [max 10] | | `NNN_BMS='d:~/Documents;D:~/Docs archive/'` | key-bookmark pairs [max 10] |
| `NNN_PLUG='o:fzopen;m:nmount;x:_chmod +x $nnn'` | key-plugin (or cmd) pairs (<kbd>:key</kbd> to run) [max 15] | | `NNN_PLUG='o:fzopen;m:nmount;x:_chmod +x $nnn'` | key-plugin (or cmd) pairs (<kbd>:key</kbd> to run) [max 15] |
| `NNN_USE_EDITOR=1` | open text files in `$VISUAL` (else `$EDITOR`, fallback vi) | | `NNN_USE_EDITOR=1` | open text files in `$VISUAL` (else `$EDITOR`, fallback vi) |

View file

@ -1,31 +0,0 @@
## nlay
`nlay` (*NnnpLAY*) is a customizable media type or action handler
### Usage
`nlay` is not used by `nnn` now. However, the bash script can be used to run desktop search utility or screensaver:
nlay file type
file: absolute path to file ("" for an action)
type: type of media or action
### Default apps
* gnome-search-tool, catfish - file search
* vlock - terminal screensaver (alternatives - cmatrix, termsaver)
### Perks
- simple to modify (extensive in-file notes, comments and indicative code)
- handle files by category (e.g. plaintext, search, screensaver)
- support for multiple apps by order of preference
- run app in the foreground or silently detached in the background
- optionally add app arguments
### Tips to modify
- set `app=` in any category to change the player
- set `opts=` to use app options
- toggle `bg=` to enable or disable running app silently (`stdout` and `stderr` redirected to `/dev/null`) in background. E.g., vim (CLI) should be verbose and in the foreground while Sublime Text (GUI) can be started silently in the background.
- enable the commented out code under `ENABLE_FILE_TYPE_HANDLING` to handle specific file extensions e.g. use a different app than the one used for the category.

View file

@ -1,105 +0,0 @@
#!/usr/bin/env bash
# #############################################################################
# nlay: a customizable script to play files in different apps by file type
#
# usage: nlay file/path type/action
#
# MUST READ:
#
# 1. Feel free to change the default apps to your favourite ones.
# If you change the app for a group you may also need to modify the opts and
# bg settings. If bg is set the app is detached and started in the background
# in silent mode.
#
# The bg setting depends on personal preferences and type of utility, e.g., I
# would start vi (CLI) in the foreground but Sublime Text (GUI) in background.
#
# Check (and TOGGLE as you wish) the default bg settings.
#
# 2. Detached apps are not killed when nnn exits. Use kill(1) or killall(1) to
# stop console based background apps.
#
# 3. nlay is OVERWRITTEN during nnn upgrade. You can store your custom nlay in a
# location other than the default and have an alias with nnn option '-p' to
# invoke it. Remember it might break or lack new capabilities added to nlay
# in future releases. Check the file diff once in a while.
#
# Author: Arun Prakash Jana
# Email: engineerarun@gmail.com
# Homepage: https://github.com/jarun/nnn
# Copyright © 2016-2019 Arun Prakash Jana
# #############################################################################
# Enable the lines below to handle file by extension
# This is provided for using a custom player for specific files
# $ext holds the extension
<<ENABLE_FILE_TYPE_HANDLING
fname=$(basename "$1")
if [[ $fname != *"."* ]]; then
exit 1
fi
ext="${fname##*.}"
if [ -z "$ext" ]; then
exit 1
fi
# bash 4.0 way to switch to lowercase
ext="${ext,,}"
# handle this extension and exit
ENABLE_FILE_TYPE_HANDLING
#------------ PLAINTEXT (UNUSED) ------------
if [ "$2" == "text" ]; then
app=("vi")
opts=("")
bg=("")
#----------------- SEARCH -------------------
elif [ "$2" == "search" ]; then
app=("gnome-search-tool"
"catfish")
opts=("--path"
"--path")
bg=(">/dev/null 2>&1 &"
">/dev/null 2>&1 &")
#------------------ LOCKER ------------------
elif [ "$2" == "locker" ]; then
app=("vlock"
"bashlock"
"lock")
for index in ${!app[@]}
do
type -P ${app[$index]} &>/dev/null &&
eval ${app[$index]} &&
exit 0
done
#------------------ SCRIPT ------------------
elif [ "$2" == "script" ]; then
# add commands or a custom script below
# echo "my commands or custom script"
# sh "path_to_script.sh"
$SHELL "$1"
exit 0
fi
#----------------- RUN APP ------------------
for index in ${!app[@]}
do
type -P ${app[$index]} &>/dev/null &&
eval ${app[$index]} ${opts[$index]} "\"$1\"" ${bg[$index]} &&
break
done

View file

@ -1,37 +0,0 @@
.Dd Mar 14, 2018
.Dt NLAY 1
.Os
.Sh NAME
.Nm nlay
.Nd a bash script to play files in different apps by file type or run some actions.
.Sh SYNOPSIS
.Nm
file/path type/action
.Sh DESCRIPTION
.Nm
is shipped with \fInnn\fR to deliver a level of flexibility to users to choose their own apps when running some actions, run some commands or custom scripts. It has provisions to handle text files too. However, the capability is not used in the latest releases. Now
.Nm
is invoked to run a desktop search (\fIgnome-search-tool\fR or \fIcatfish\fR) or screen locker (\fIvlock\fR or \fIbashlock\fR or \fIlock\fR) utility. However,
.Nm
can run independently and can be highly customized for personal usage.
.Pp
.Nm
supports the following options:
.Pp
"file/path"
The first argument can be the file or path to pass as an argument to the app. It can also be an empty string e.g., while locking the terminal.
.Pp
"type/action"
This can be any of the strings \fItext\fR, \fIsearch\fR, \fIscript\fR or \fIlocker\fR.
.Sh USAGE
.Pp
.Bd -literal
$ nlay info.txt text
$ nlay . search
$ nlay ~/script.sh script
$ nlay "" locker
.Ed
.Sh AUTHOR
.An Arun Prakash Jana Aq Mt engineerarun@gmail.com .
.Sh HOME
.Em https://github.com/jarun/nnn

26
misc/nplay/README.md Normal file
View file

@ -0,0 +1,26 @@
## nplay
`nplay` (*NnnPLAY*) is a customizable file opener by file extension or mime type.
It is customizable and written for the CLI mode by default. To set GUI mode and use GUI apps by change the line
GUI=0
to
GUI=1
### Usage
nplay filepath
### Integration with `nnn`
1. Export the required config:
export NNN_OPENER=/path/to/nplay
# Otherwise, if nplay is in $PATH
export NNN_OPENER=nplay
2. Run `nnn` with the program option to indicate a CLI opener
nnn -c
3. `nplay` can use `nnn` plugins (e.g. mocplay is used for audio), $PATH is updated to include `nnn` plugins dir.

423
misc/nplay/nplay Executable file
View file

@ -0,0 +1,423 @@
#!/usr/bin/env sh
# #############################################################################
# nplay: a sample script to play files in different apps by file type and mime
# shell: POSIX compliant
# usage: nplay filepath
#
# nnn integration:
# 1. Export the required config:
# export NNN_OPENER=/path/to/nplay
# # Otherwise, if nplay is in $PATH
# export NNN_OPENER=nplay
# 2. Run nnn with the program option to indicate a CLI opener
# nnn -c
# 3. nplay can use nnn plugins (e.g. mocplay is used for audio), $PATH is updated.
#
# details:
# Inspired by ranger's scope.sh, modified for usage with nnn.
#
# Tries to play 'file' (1st argument) in the following order:
# i. by extension
# ii. by mime (image, video, audio, pdf)
# iii. by mime (other file types)
#
# modification tips:
# 1. Invokes CLI utilities by default. Set GUI to 1 to enable GUI apps.
# 2. PAGER is "less -R".
# 3. Start GUI apps in bg to unblock. Redirect stdout and strerr if required.
# 4. Some CLI utilities are piped to the $PAGER, to wait and quit uniformly.
# 5. If the output cannot be paged use "read -r _" to wait for user input.
# 6. On a DE, try 'xdg-open' in handle_fallback() as last resort.
#
# Feel free to change the utilities to your favourites and add more mimes.
#
# defaults:
# By extension (only the enbaled ones):
# most archives: list with atool, bsdtar
# rar: list with unrar
# 7-zip: list with 7z
# pdf: zathura (GUI), pdftotext, mutool, exiftool
# m4a: mocplay (nnn plugin using MOC), mpv, mediainfo, exiftool
# torrent: transmission-show
# odt|ods|odp|sxw: odt2txt
# htm|html|xhtml: w3m, lynx, elinks
# json: jq, python (json.tool module)
# Multimedia by mime:
# image/*: sxiv (GUI), viu, img2txt, exiftool
# video/*: smplayer, mpv (GUI), ffmpegthumbnailer, mediainfo, exiftool
# audio/*: mocplay (nnn plugin using MOC), mpv, mediainfo, exiftool
# application/pdf: zathura (GUI), pdftotext, mutool, exiftool
# Other mimes:
# text/* | */xml: vi
# image/vnd.djvu): djvutxt, exiftool
#
# ToDo:
# 1. Adapt, test and enable all mimes
# 2. Clean-up unnecessary the exit codes
# #############################################################################
# set to 1 to enable GUI apps
GUI=0
set -euf -o noclobber -o noglob -o nounset
IFS="$(printf '%b_' '\n')"; IFS="${IFS%_}" # protect trailing \n
PATH=$PATH:"${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins"
IMAGE_CACHE_PATH="$(dirname "$1")"/.thumbs
FPATH="$1"
FNAME=$(basename "$1")
ext="${FNAME##*.}"
if ! [ -z "$ext" ]; then
ext="$(printf "%s" "${ext}" | tr '[:upper:]' '[:lower:]')"
fi
# handle this extension and exit
handle_extension() {
case "${ext}" in
## Archive
a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|\
rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z|zip)
if which atool >/dev/null 2>&1; then
atool --list -- "${FPATH}" | less -R
exit 0
elif which bsdtar >/dev/null 2>&1; then
bsdtar --list --file "${FPATH}" | less -R
exit 0
fi
exit 1;;
rar)
if which unrar >/dev/null 2>&1; then
## Avoid password prompt by providing empty password
unrar lt -p- -- "${FPATH}" | less -R
fi
exit 1;;
7z)
if which 7z >/dev/null 2>&1; then
## Avoid password prompt by providing empty password
7z l -p -- "${FPATH}" | less -R
exit 0
fi
exit 1;;
## PDF
pdf)
if [ $GUI -ne 0 ] && which zathura >/dev/null 2>&1; then
zathura "${FPATH}" >/dev/null 2>&1 &
exit 0
elif which pdftotext >/dev/null 2>&1; then
## Preview as text conversion
pdftotext -l 10 -nopgbrk -q -- "${FPATH}" - | less -R
exit 0
elif which mutool >/dev/null 2>&1; then
mutool draw -F txt -i -- "${FPATH}" 1-10
exit 0
elif which exiftool >/dev/null 2>&1; then
exiftool "${FPATH}" | less -R
exit 0
fi
exit 1;;
## M4A audio
m4a)
if which mocp >/dev/null 2>&1; then
mocplay "${FPATH}" >/dev/null 2>&1
exit 0
elif which mpv >/dev/null 2>&1; then
mpv "${FPATH}" >/dev/null 2>&1 &
exit 0
elif which mediainfo >/dev/null 2>&1; then
mediainfo "${FPATH}" | less -R
exit 0
elif which exiftool >/dev/null 2>&1; then
exiftool "${FPATH}"| less -R
exit 0
fi
exit 1;;
## BitTorrent
torrent)
if which transmission-show >/dev/null 2>&1; then
transmission-show -- "${FPATH}"
exit 0
fi
exit 1;;
## OpenDocument
odt|ods|odp|sxw)
if which odt2txt >/dev/null 2>&1; then
## Preview as text conversion
odt2txt "${FPATH}" | less -R
exit 0
fi
exit 1;;
## HTML
htm|html|xhtml)
## Preview as text conversion
if which w3m >/dev/null 2>&1; then
w3m -dump "${FPATH}" | less -R
exit 0
elif which lynx >/dev/null 2>&1; then
lynx -dump -- "${FPATH}" | less -R
exit 0
elif which elinks >/dev/null 2>&1; then
elinks -dump "${FPATH}" | less -R
exit 0
fi
;;
## JSON
json)
if which jq >/dev/null 2>&1; then
jq --color-output . "${FPATH}" | less -R
exit 0
elif which python >/dev/null 2>&1; then
python -m json.tool -- "${FPATH}" | less -R
exit 0
fi
;;
esac
}
handle_multimedia() {
## Size of the preview if there are multiple options or it has to be
## rendered from vector graphics. If the conversion program allows
## specifying only one dimension while keeping the aspect ratio, the width
## will be used.
# local DEFAULT_SIZE="1920x1080"
mimetype="${1}"
case "${mimetype}" in
## SVG
# image/svg+xml|image/svg)
# convert -- "${FPATH}" "${IMAGE_CACHE_PATH}" && exit 6
# exit 1;;
## DjVu
# image/vnd.djvu)
# ddjvu -format=tiff -quality=90 -page=1 -size="${DEFAULT_SIZE}" \
# - "${IMAGE_CACHE_PATH}" < "${FPATH}" \
# && exit 6 || exit 1;;
## Image
image/*)
if [ $GUI -ne 0 ] && which sxiv >/dev/null 2>&1; then
sxiv -q "$1" "$(dirname "${FPATH}")" &
exit 0
elif which viu >/dev/null 2>&1; then
viu -n "${FPATH}" | less -R
exit 0
elif which img2txt >/dev/null 2>&1; then
img2txt --gamma=0.6 -- "${FPATH}" | less -R
exit 0
elif which exiftool >/dev/null 2>&1; then
exiftool "${FPATH}" | less -R
exit 0
fi
# local orientation
# orientation="$( identify -format '%[EXIF:Orientation]\n' -- "${FPATH}" )"
## If orientation data is present and the image actually
## needs rotating ("1" means no rotation)...
# if [[ -n "$orientation" && "$orientation" != 1 ]]; then
## ...auto-rotate the image according to the EXIF data.
# convert -- "${FPATH}" -auto-orient "${IMAGE_CACHE_PATH}" && exit 6
# fi
## `w3mimgdisplay` will be called for all images (unless overriden
## as above), but might fail for unsupported types.
exit 7;;
## Video
video/*)
if [ $GUI -ne 0 ] && which smplayer >/dev/null 2>&1; then
smplayer "${FPATH}" >/dev/null 2>&1 &
exit 0
elif [ $GUI -ne 0 ] && which mpv >/dev/null 2>&1; then
mpv "${FPATH}" >/dev/null 2>&1 &
exit 0
elif which ffmpegthumbnailer >/dev/null 2>&1; then
# Thumbnail
[ -d "${IMAGE_CACHE_PATH}" ] || mkdir "${IMAGE_CACHE_PATH}"
ffmpegthumbnailer -i "${FPATH}" -o "${IMAGE_CACHE_PATH}/${FNAME}.jpg" -s 0
viu -n "${IMAGE_CACHE_PATH}/${FNAME}.jpg" | less -R
exit 0
elif which mediainfo >/dev/null 2>&1; then
mediainfo "${FPATH}" | less -R
exit 0
elif which exiftool >/dev/null 2>&1; then
exiftool "${FPATH}"| less -R
exit 0
fi
exit 1;;
## Audio
audio/*)
if which mocp >/dev/null 2>&1; then
mocplay "${FPATH}" >/dev/null 2>&1
exit 0
elif which mpv >/dev/null 2>&1; then
mpv "${FPATH}" >/dev/null 2>&1 &
exit 0
elif which mediainfo >/dev/null 2>&1; then
mediainfo "${FPATH}" | less -R
exit 0
elif which exiftool >/dev/null 2>&1; then
exiftool "${FPATH}"| less -R
exit 0
fi
exit 1;;
## PDF
application/pdf)
if [ $GUI -ne 0 ] && which zathura >/dev/null 2>&1; then
zathura "${FPATH}" >/dev/null 2>&1 &
exit 0
elif which pdftotext >/dev/null 2>&1; then
## Preview as text conversion
pdftotext -l 10 -nopgbrk -q -- "${FPATH}" - | less -R
exit 0
elif which mutool >/dev/null 2>&1; then
mutool draw -F txt -i -- "${FPATH}" 1-10 | less -R
exit 0
elif which exiftool >/dev/null 2>&1; then
exiftool "${FPATH}" | less -R
exit 0
fi
exit 1;;
# pdftoppm -f 1 -l 1 \
# -scale-to-x "${DEFAULT_SIZE%x*}" \
# -scale-to-y -1 \
# -singlefile \
# -jpeg -tiffcompression jpeg \
# -- "${FPATH}" "${IMAGE_CACHE_PATH%.*}" \
# && exit 6 || exit 1;;
## ePub, MOBI, FB2 (using Calibre)
# application/epub+zip|application/x-mobipocket-ebook|\
# application/x-fictionbook+xml)
# # ePub (using https://github.com/marianosimone/epub-thumbnailer)
# epub-thumbnailer "${FPATH}" "${IMAGE_CACHE_PATH}" \
# "${DEFAULT_SIZE%x*}" && exit 6
# ebook-meta --get-cover="${IMAGE_CACHE_PATH}" -- "${FPATH}" \
# >/dev/null && exit 6
# exit 1;;
## Font
# application/font*|application/*opentype)
# preview_png="/tmp/$(basename "${IMAGE_CACHE_PATH%.*}").png"
# if fontimage -o "${preview_png}" \
# --pixelsize "120" \
# --fontname \
# --pixelsize "80" \
# --text " ABCDEFGHIJKLMNOPQRSTUVWXYZ " \
# --text " abcdefghijklmnopqrstuvwxyz " \
# --text " 0123456789.:,;(*!?') ff fl fi ffi ffl " \
# --text " The quick brown fox jumps over the lazy dog. " \
# "${FPATH}";
# then
# convert -- "${preview_png}" "${IMAGE_CACHE_PATH}" \
# && rm "${preview_png}" \
# && exit 6
# else
# exit 1
# fi
# ;;
## Preview archives using the first image inside.
## (Very useful for comic book collections for example.)
# application/zip|application/x-rar|application/x-7z-compressed|\
# application/x-xz|application/x-bzip2|application/x-gzip|application/x-tar)
# local fn=""; local fe=""
# local zip=""; local rar=""; local tar=""; local bsd=""
# case "${mimetype}" in
# application/zip) zip=1 ;;
# application/x-rar) rar=1 ;;
# application/x-7z-compressed) ;;
# *) tar=1 ;;
# esac
# { [ "$tar" ] && fn=$(tar --list --file "${FPATH}"); } || \
# { fn=$(bsdtar --list --file "${FPATH}") && bsd=1 && tar=""; } || \
# { [ "$rar" ] && fn=$(unrar lb -p- -- "${FPATH}"); } || \
# { [ "$zip" ] && fn=$(zipinfo -1 -- "${FPATH}"); } || return
#
# fn=$(echo "$fn" | python -c "import sys; import mimetypes as m; \
# [ print(l, end='') for l in sys.stdin if \
# (m.guess_type(l[:-1])[0] or '').startswith('image/') ]" |\
# sort -V | head -n 1)
# [ "$fn" = "" ] && return
# [ "$bsd" ] && fn=$(printf '%b' "$fn")
#
# [ "$tar" ] && tar --extract --to-stdout \
# --file "${FPATH}" -- "$fn" > "${IMAGE_CACHE_PATH}" && exit 6
# fe=$(echo -n "$fn" | sed 's/[][*?\]/\\\0/g')
# [ "$bsd" ] && bsdtar --extract --to-stdout \
# --file "${FPATH}" -- "$fe" > "${IMAGE_CACHE_PATH}" && exit 6
# [ "$bsd" ] || [ "$tar" ] && rm -- "${IMAGE_CACHE_PATH}"
# [ "$rar" ] && unrar p -p- -inul -- "${FPATH}" "$fn" > \
# "${IMAGE_CACHE_PATH}" && exit 6
# [ "$zip" ] && unzip -pP "" -- "${FPATH}" "$fe" > \
# "${IMAGE_CACHE_PATH}" && exit 6
# [ "$rar" ] || [ "$zip" ] && rm -- "${IMAGE_CACHE_PATH}"
# ;;
esac
}
handle_mime() {
mimetype="${1}"
case "${mimetype}" in
## Text
text/* | */xml)
vi "${FPATH}"
exit 1;;
## Syntax highlight
# if [[ "$( stat --printf='%s' -- "${FPATH}" )" -gt "${HIGHLIGHT_SIZE_MAX}" ]]; then
# exit 2
# fi
# if [[ "$( tput colors )" -ge 256 ]]; then
# local pygmentize_format='terminal256'
# local highlight_format='xterm256'
# else
# local pygmentize_format='terminal'
# local highlight_format='ansi'
# fi
# env HIGHLIGHT_OPTIONS="${HIGHLIGHT_OPTIONS}" highlight \
# --out-format="${highlight_format}" \
# --force -- "${FPATH}" && exit 5
# pygmentize -f "${pygmentize_format}" -O "style=${PYGMENTIZE_STYLE}"\
# -- "${FPATH}" && exit 5
# exit 2;;
## DjVu
image/vnd.djvu)
if which djvutxt >/dev/null 2>&1; then
## Preview as text conversion (requires djvulibre)
djvutxt "${FPATH}" | less -R
exit 0
elif which exiftool >/dev/null 2>&1; then
exiftool "${FPATH}" | less -R
exit 0
fi
exit 1;;
esac
}
handle_fallback() {
if [ $GUI -ne 0 ]; then
xdg-open "${FPATH}" >/dev/null 2>&1 &
exit 0
fi
echo '----- File details -----' && file --dereference --brief -- "${FPATH}"
exit 1
}
MIMETYPE="$( file --dereference --brief --mime-type -- "${FPATH}" )"
handle_extension
handle_multimedia "${MIMETYPE}"
handle_mime "${MIMETYPE}"
handle_fallback
exit 1

4
nnn.1
View file

@ -232,7 +232,9 @@ when dealing with the !, e and p commands respectively. A single combination to
.Pp .Pp
\fBNNN_OPENER:\fR specify a custom file opener. \fBNNN_OPENER:\fR specify a custom file opener.
.Bd -literal .Bd -literal
export NNN_OPENER=mimeopen export NNN_OPENER=nplay
nplay source: https://github.com/jarun/nnn/blob/master/misc/nplay/nplay
.Ed .Ed
.Pp .Pp
\fBNNN_IDLE_TIMEOUT:\fR set idle timeout (in seconds) to invoke terminal locker (default: disabled). \fBNNN_IDLE_TIMEOUT:\fR set idle timeout (in seconds) to invoke terminal locker (default: disabled).