#!/usr/bin/env bash # This is an attempt to replace xdg-open with something sane. 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_target # 1: cmd failed # 3: no handler handle_target() { declare -n result=$1 declare h cmd regex target_is_file target target_left target_is_file=0 target=$2 target_left=$target if [[ -e "$target" ]]; then target_is_file=1 [[ "$target" =~ ^/.* ]] || { target="${PWD}/${target}"; } # Turn relative paths to absolute ones. IFS=';' read target_mimetype charset <<< $( file -ib "$target" ) target_left=$target_mimetype set -- "${mime_handlers[@]}" elif is_uri "$target"; then set -- "${uri_handlers[@]}" else return 2 fi while (( $# )); do cmd=( $1 ); regex=$2 if [[ "$target_left" =~ $regex ]]; then act "${cmd[@]}" "$target"; result=$? (( result )) && return 1 return 0 fi shift 2 done return 3 } # DSL uri() { declare r handler=$1; shift for r in "$@"; do uri_handlers+=( "$handler" "$r" ) done } mime() { declare r handler=$1; shift for r in "$@"; do mime_handlers+=( "$handler" "$r" ) done } scheme() { declare r handler=$1; shift for s in "$@"; do uri_handlers+=( "$handler" "^$s:" ) done } 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) dry_run=1; verbose=1;; (-v) verbose=1;; (-h) usage; return 0;; (--) shift; break;; (*) break;; esac shift done target=$1; [[ "$target" ]] || { usage; exit; } (( dry_run )) && printf 'Dry run: not actually running the handler\n' >&2 # Treat file:// as local paths. [[ "$target" =~ ^file:(//)?(/.+) ]] && target=${BASH_REMATCH[2]} handle_target cmd_result "$target" case $? in (1) printf 'Action failed with exit code: “%s”\n' "$cmd_result" >&2 return 4 ;; (2) printf 'No such file or directory: “%s”\n' "$target" >&2 return 2 ;; (3) printf 'No handlers found for “%s”\n' "$target" >&2 return 3 ;; esac return 0 } main "$@"