#!/usr/bin/env bash # This is an attempt to replace xdg-open with something sane. usage() { printf '%s [-dhv] \n' "${0##*/}"; } usage() { cat <<- EOF sx-open [-dhv] Flags: -d Dry run -v Verbose -h Help EOF } act() { (( verbose )) && printf 'CMD: %s\n' "$*" >&2 (( dry_run )) || { "$@"; return $?; } return 0 } # handle_uri # 1: cmd failed # 3: no handler handle_uri() { declare -n result=$1 declare h cmd regex target=$2 for h in "${uri_handlers[@]}"; do IFS='=' read cmd regex <<< "$h" if [[ "$target" =~ ${regex} ]]; then act ${cmd} "$target"; result=$? (( result )) && return 1 return 0 fi done return 3 } # handle_file # 1: cmd failed # 2: no such file # 3: no handler handle_file() { declare -n result=$1 declare m \ target_mimetype charset \ cmd regex \ target=$2 [[ -e "$target" ]] || return 3 IFS=';' read target_mimetype charset <<< $( file -ib "$target" ) for m in "${mime_handlers[@]}"; do IFS='=' read cmd regex <<< "$m" if [[ "$target_mimetype" =~ ${regex} ]]; then act ${cmd} "$target"; result=$? (( result )) && return 1 return 0 fi done return 3 } # DSL uri() { uri_handlers+=( "$1=$2" ); } mime() { mime_handlers+=( "$1=$2" ); } is_uri() [[ $1 =~ ^[a-zA-Z][a-zA-Z0-9\+\.\-]+:.+ ]] main() { declare cmd_result target # Source the config file. cfg_file="$HOME/.config/sx-open.cfg" [[ -f "$cfg_file" ]] && { source "$cfg_file"; } while (( $# )); do case $1 in (-d) printf 'Dry run: not actually running the handler\n' >&2 dry_run=1 verbose=1 ;; (-h) usage; return 0;; (-v) verbose=1;; (--) shift; break;; (*) break;; esac shift done target=$1 [[ "$target" ]] || { usage; exit; } # Treat file:// as local paths. [[ "$target" =~ ^file:(//)?(/.+) ]] && target=${BASH_REMATCH[2]} if [[ -e "$target" ]]; then [[ "$target" =~ ^/.* ]] || { target="${PWD}/${target}"; } # Turn relative paths to absolute ones. handle_file cmd_result "$target" elif is_uri "$target"; then handle_uri cmd_result "$target" else printf 'No such file or directory: %s\n' "$target" >&2 return 2 fi case $? in (1) printf 'Action failed with exit code: %s\n' "$cmd_result" >&2 return 4 ;; (3) printf 'No handlers found\n' >&2 return 3 ;; esac return 0 } main "$@"