### vim:ft=zsh:foldmethod=marker
### choosing appropriate application to view ebooks (like .pdf, .chm etc.)
###
### Frank Terbeck <ft@bewatermyfriend.org>
### Last-Modified: Wed Dec 26 14:38:21 2007
###
### URI: <http://ft.bewatermyfriend.org/comp/zsh.html>
###

#{{{ vars

emulate zsh
setopt extendedglob
setopt nullglob
setopt localoptions
setopt noksharrays

local -A supported_extensions
local key NO_DISOWN NO_BGROUND MAX_BG FORCE_BG
local sext sup ext

MAX_BG=12
FORCE_BG=0

supported_extensions=(
    ".pdf:0"    "xpdf:Adobe"\'"s Portable Document Format (via xpdf)"
    ".pdf:1"    "acroread:Adobe"\'"s Portable Document Format (via acroread)"
    ".dvi:0"    "xdvi:DeVice Independent, TeX output (via xdvi)"
    ".ps:0"     "gv:Adobe"\'"s PostScript (via gv)"
    ".chm:0"    "xchm:Microsoft Compiled HTML Help (via xchm)"
    ".djvu:0"   "djview:DjVu image format (via djview)"
)

#}}}
#{{{ init

if [[ -z ${DISPLAY} ]] ; then
    printf 'Sorry, no X11 is running. Got no method to handle this. ABORT.\n'
    return 0
fi

if [[ -z ${1} ]] ; then
    printf 'usage: reb [-(l|L|n|o|B)] <file(s...)>\n'
    printf '  -l  list available extensions (human readable)\n'
    printf '  -L  list available extensions (machine readable))\n'
    printf '  -n  do not disown processes\n'
    printf '  -o  do not put processes into background (one-by-one processing)\n'
    printf '  -B  force background processes (even if more than %s files are specified)\n' "${MAX_BG}"
    return 0
fi

#}}}
#{{{ check programs

for key in ${(k)supported_extensions} ; do
    (( DEBUG_REB > 0 )) && printf 'Checking: %s\n ' "${${(s.:.)${supported_extensions[$key]}}[1]}" >&2
    if [[ -n ${supported_extensions[${key%:?}]} ]] ; then
        if (( DEBUG_REB > 0 )) ; then
            printf '  !- Ignoring %s: %s already points to: %s\n ' \
                "${${(s.:.)${supported_extensions[$key]}}[1]}" "${key%:?}" "${supported_extensions[${key%:?}/com]}" >&2
        fi
    else
        if [[ -x $(which ${${(s.:.)${supported_extensions[$key]}}[1]}) ]] ; then
            (( DEBUG_REB > 0 )) && printf '  + Found: %s\n' "${${(s.:.)${supported_extensions[$key]}}[1]}" >&2
            (( DEBUG_REB > 0 )) && printf '  - Setting: %s     to %s\n' "${key%:?}" "${${(s.:.)${supported_extensions[$key]}}[2]}" >&2
            supported_extensions[${key%:?}]=${${(s.:.)${supported_extensions[$key]}}[2]}
            (( DEBUG_REB > 0 )) && printf '  -          %s to %s\n' "${key%:?}/com" "${${(s.:.)${supported_extensions[$key]}}[1]}" >&2
            supported_extensions[${key%:?}/com]=${${(s.:.)${supported_extensions[$key]}}[1]}
        fi
    fi
done

#}}}
#{{{ parsing options

while [[ ${1} == -? ]] ; do
    case ${1} in
        (-l)
            printf 'Available formats:\n'
            for key in ${(M)${(k)supported_extensions}:#*/com} ; do
                printf '%s: %s\n' "${(l:8:)${key%/com}}" "${supported_extensions[${key%/com}]}"
            done
            return 0
            ;;
        (-L)
            print ${${(M)${(k)supported_extensions}:#*/com}%/com}
            return 0
            ;;
        (-n)
            NO_DISOWN=1
            ;;
        (-o)
            NO_BGROUND=1
            ;;
        (-B)
            FORCE_BG=1
            ;;
        (*)
            printf 'Unknown option "%s"\n' "${1}"
            printf 'usage: reb [-(l|L|n|o)]<file(s...)>\n'
            printf '  -l  list available extensions (human readable)\n'
            printf '  -L  list available extensions (machine readable))\n'
            printf '  -n  do not disown processes\n'
            printf '  -o  do not put processes into background (one-by-one processing)\n'
            printf '  -B  force background processes (even if more than %s files are specified)\n' "${MAX_BG}"
            return 1
            ;;
    esac
    shift
done

if (( ${#argv} > ${MAX_BG} )) && (( ${FORCE_BG} == 0 )); then
    printf 'Too many files specified (%s > %s); See -B option.\n' "${#argv}" "${MAX_BG}"
    NO_BGROUND=1
fi

#}}}
#{{{ main()

if (( ${#argv} == 0 )) ; then
    printf 'usage: reb [-(l|L|n|o)]<file(s...)>\n'
    printf '  -l  list available extensions (human readable)\n'
    printf '  -L  list available extensions (machine readable))\n'
    printf '  -n  do not disown processes\n'
    printf '  -o  do not put processes into background (one-by-one processing)\n'
    printf '  -B  force background processes (even if more than %s files are specified)\n' "${MAX_BG}"
    return 0
fi

for file in "$@" ; do
    if [[ ! -e "${file}" ]] ; then
        printf '%s: Cannot open %s: file does not exist.\n' "${0}" "${file}"
    else
        ext=${(L)${file:e}}
        sup=0
        for sext in ${${(M)${(k)supported_extensions}:#*/com}%/com} ; do
            [[ "${sext}" == ".${ext}" ]] && sup=1 && break
        done
        if (( sup > 0 )) ; then
            printf 'Running: %s %s\n' "${supported_extensions[.${ext}/com]}" "${file}"
            if (( NO_BGROUND > 0 )) ; then
                ${supported_extensions[.${ext}/com]} ${file} &> /dev/null
            elif (( NO_DISOWN > 0 )) ; then
                ${supported_extensions[.${ext}/com]} ${file} &> /dev/null &
            else
                ${supported_extensions[.${ext}/com]} ${file} &> /dev/null &!
            fi
        else
            printf 'Cannot open %s: unsupported fileextension (%s)\n' "${file}" "${ext}"
        fi
    fi
done

return 0

#}}}