#!/usr/bin/env bash # @file /usr/bin/opener # @brief Opens a file type with the appropriate program based on the mime-type # @description # This script heavily borrows from [opener](https://github.com/Docbroke/shell_tools/blob/main/opener). # It makes some minor tweaks including linting fixes. It is configured # to properly work with [Gas Station](https://github.com/megabyte-labs/Gas-Station). # It is used to handle cross-VM links when Gas Station is used to provision [Qubes](https://www.qubes-os.org/). # When called with -d, the default program is used. # TODO Add support for opening .desktop files with gtk-launch (i.e. `gtk-launch my-app.desktop`) # TODO See if this is useful https://github.com/sindresorhus/open # TODO Integrate handlr # Default to system open executable on macOS if [ -d /Applications ] && [ -d /Library ]; then /usr/bin/open "$*" && exit 0 fi # shellcheck disable=SC2124 getopts d: name case $name in d) file=$OPTARG default=true ;; *) file="$@" ;; esac [[ -z $file || ! -e $file ]] && exit 1 ## mimetype from perl-file-mimeinfo gives better results compared to file type mimetype &> /dev/null && mime_type="$(mimetype -b "$file")" || \ mime_type="$(file -b --mime-type "$file")" ## create some lists XBROWSERS=("firefox" "chromium" "vimb" "qutebrowser" "weaver" "vivaldi") TBROWSERS=("w3m" "links" "lynx" "elinks") XEDITORS=("gvim" "geany" "leafpad" "mousepad") TEDITORS=("cat" "less" "vim" "vis" "nano" "micro") XFMS=("pcmanfm" "nautilus" "rof" "thunar") TFMS=("ncdu" "du -h" "vifm" "ranger" "mc" "fff" "nnn" "clifm") PDFVIEWERS=("llpp" "xournalpp" "mupdf" "qpdfview") DOCVIEWERS=("llpp" "foliate" "mupdf" "qpdfview") CHMVIEWERS=("kchmviewer" "xchm" "chmopen") BOOKVIEWERS=("$TERMINAL --geometry=1920x1050 -p Large -x epy.py" "foliate" "llpp" "mupdf") ARCHIVERS=("als" "lsar" "unar" "aunpack -D") VIEWERS=("feh" "sxiv" "gifview -a" "display" "mtpaint" "gimp" "viewnoir" "fbi" "lp") VPLAYERS=("mpv --player-operation-mode=pseudo-gui" "vlc" "cvlc" "ffplay" "ffprobe" "mediainfo") APLAYERS=("mpv --player-operation-mode=pseudo-gui" "vlc" "cvlc" "ffplay" "ffprobe" "mediainfo" "soxi" "mpg123") ## some defaults if [[ -n "$DISPLAY" ]]; then PLAYER="mpv --player-operation-mode=pseudo-gui" else PLAYER="mpv --vo=drm" fi if [[ -n "$DISPLAY" ]]; then VIEWER="sxiv -fbq $file $PWD" else VIEWER=fbi fi TERMINAL=terminator EDITOR=vis BROWSER=weaver PDFVIEWER=llpp DOCVIEWER=llpp CHMVIEWER=kchmviewer BOOKVIEWER="$TERMINAL --geometry=1920x1050 -p Large -x epy.py" case "$mime_type" in text/html|text/xml|application/x-mimearchive|message/rfc822) if [[ $default == true ]]; then $BROWSER "$file" && exit elif [[ $TERM = linux && -n $DISPLAY ]]; then select ops in exit "${XBROWSERS[@]}" "${TBROWSERS[@]}" $EDITOR; do [[ $ops = exit ]] && exit [[ $ops = w3m || $ops = links || $ops = elinks || $EDITOR ]] && $TERMINAL -x "$ops" "$file" & "$ops" "$file" &> /dev/null & done elif [[ $TERM != linux && -n $DISPLAY ]]; then select ops in exit "${XBROWSERS[@]}" "${TBROWSERS[@]}" $EDITOR; do [[ $ops = exit ]] && exit "$ops" "$file" done else select ops in exit "${TBROWSERS[@]}" $EDITOR; do [[ $ops = exit ]] && exit "$ops" "$file" done fi ;; text/*|*/xml|application/x-httpd-php3|application/x-httpd-php4|application/x-httpd-php5|application/x-shellscript) [[ $default == true ]] && \ if [[ $TERM = linux && -n $DISPLAY ]]; then $TERMINAL -x "${VISUAL:-${EDITOR:-vis}}" "$file" else "${VISUAL:-${EDITOR:-vis}}" "$file" fi && exit select ops in exit "${XEDITORS[@]}" "${TEDITORS[@]}"; do [[ $ops = exit ]] && exit "$ops" "$file" done ;; image/*) [[ $default == true ]] && $VIEWER "$file" && exit select ops in exit "${VIEWERS[@]}"; do [[ $ops = exit ]] && break $ops "$file" &> /dev/null & done ;; video/*|application/x-matroska) [[ $default == true ]] && $PLAYER "$file" && exit if [[ -n $DISPLAY ]]; then select ops in exit "${VPLAYERS[@]}"; do [[ $ops = exit ]] && break $ops "$file" & done else mpv --vo=drm -- "$file" fi ;; audio/*| application/ogg|application/x-ogg|application/mxf|application/sdp|application/smil|application/x-smil|application/streamingmedia|application/x-streamingmedia|application/vnd.rn-realmedia|application/vnd.rn-realmedia-vbr) [[ $default == true ]] && $PLAYER "$file" && exit select ops in exit "${APLAYERS[@]}"; do [[ $ops = exit ]] && break $ops "$file" & done ;; application/pdf|application/x-pdf) [[ $default == true ]] && $PDFVIEWER "$file" && exit if [[ -n $DISPLAY ]]; then select ops in exit "${PDFVIEWERS[@]}"; do [[ $ops = exit ]] && break $ops "$file" &> /dev/null & done else fbgs "$file" fi ;; application/x-cbz|applilcation/oxps|application/vnd.ms-xpsdocument) [[ $default == true ]] && $DOCVIEWER "$file" && exit select ops in exit "${DOCVIEWERS[@]}"; do [[ $ops = exit ]] && break $ops "$file" &> /dev/null & done ;; application/octet-stream) case "$file" in *.chm|*.CHM) [[ $default == true ]] && $CHMVIEWER "$file" && exit select ops in exit "${CHMVIEWERS[@]}"; do [[ $ops = exit ]] && break $ops "$file" & done ;; *.gpg) gpg -d "$file" ;; *.mobi) [[ $default == true ]] && $BOOKVIEWER "$file" && exit select ops in exit "${BOOKVIEWERS[@]}"; do [[ $ops = exit ]] && break $ops "$file" &> /dev/null & done ;; *) echo "unknow filetype, probably binary" ;; esac ;; application/vnd.ms-htmlhelp) [[ $default == true ]] && $CHMVIEWER "$file" && exit select ops in exit "${CHMVIEWERS[@]}"; do [[ $ops = exit ]] && break $ops "$file" & done ;; application/vnd.comicbook*) select ops in exit llpp mupdf foliate; do [[ $ops = exit ]] && break $ops "$file" & done ;; application/epub+zip|application/x-mobipocket-ebook) [[ $default == true ]] && $BOOKVIEWER "$file" && exit select ops in exit "${BOOKVIEWERS[@]}"; do [[ $ops = exit ]] && break $ops "$file" &> /dev/null & done ;; application/pgp-encrypted) gpg -d "$file" ;; application/*zip*|application/x-?ar|application/x-?z*|application/x-compressed*|application/vnd.rar|application/x-*-image|application/x-msi) case "$file" in *.xoj|*.xopp) xournalpp "$file" &> /dev/null ;; *.cb?) select ops in exit llpp mupdf foliate als unar; do [[ $ops = exit ]] && break [[ $ops = als || $ops = unar ]] && "$ops" "$file" "$ops" "$file" &> /dev/null & done ;; *) if [[ $default == true ]]; then mkdir "$file.tmp" archivemount "$file" "$file.tmp" echo -e "$file mounted at $file.tmp directory\n remove with fusermount -u $file.tmp" else select ops in exit "${ARCHIVERS[@]}" ; do [[ $ops = exit ]] && break # [[ $ops = aunpack ]] && aunpack -D "$file" $ops "$file" done fi ;; esac ;; *opendocument*|*openxmlformats*|*msword|*ms-excel|*ms-powerpoint|*abiword|*write*) [[ -n $DISPLAY ]] && libreoffice "$file" --norestore &> /dev/null [[ -z $DISPLAY ]] && \ case "$file" in *.odt|*.odp|*.ods|*.sxw) odt2txt "$file" ;; *.doc) antiword "$file" ;; *.docx) docx2txt "$file" - | $PAGER ;; *) echo "unable to open" ;; esac ;; inode/directory) select ops in exit "${TFMS[@]}" "${XFMS[@]}"; do [[ $ops = exit ]] && break $ops "$file" done ;; inode/x-empty) echo "empty file" rm -i "$file" ;; inode/mount-point) ## unmount by default # select ops in exit unmount; do # [[ $ops = exit ]] && break # [[ $ops = unmount ]] && fusermount -zu "$file" && rmdir "$file" fusermount -zu "$file" && rmdir "$file" && echo "$file unmounted and removed" # done ;; *) case "$file" in *) echo "no filetype association for $file" ;; esac ;; esac