diff --git a/README.md b/README.md index 97ea0a0..a12dd96 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,22 @@ -sx-open -======= +# sx-open sx-open is an attempt to implement a saner alternative to xdg-open. -Installation ------------- +## Installation Clone the repo, drop sx-open.cfg into your $HOME/.config. As this thing is meant to replace xdg-open, you will probably want to link sx-open into xdg-open somewhere in your $PATH as to override the default one. + +## Usage + + sx-open [-dhv] + Flags: + -d Dry run + -v Verbose + -h Help + +### Exit codes + + * 1 — action failed + * 2 — file not found + * 3 — no handlers found diff --git a/sx-open b/sx-open index b3b1326..ce5b40b 100755 --- a/sx-open +++ b/sx-open @@ -1,57 +1,137 @@ #!/usr/bin/env bash # This is an attempt to replace xdg-open with something sane. -# Source the config file. -cfg_file="$HOME/.config/sx-open.cfg" -[[ -f "$cfg_file" ]] && { source "$cfg_file"; } +usage() { printf '%s [-dhv] \n' "${0##*/}"; } -usage() { printf '%s \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() { - local target="$1" + declare -n result=$1 + declare h cmd regex target=$2 for h in "${uri_handlers[@]}"; do IFS='=' read cmd regex <<< "$h" - [[ "$target" =~ ${regex} ]] && { - ${cmd} "$target" & + if [[ "$target" =~ ${regex} ]]; then + act ${cmd} "$target"; result=$? + (( result )) && return 1 + return 0 - } + fi done - return 1 + return 3 } -handle_mime() { +# 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" - [[ "$target_mimetype" =~ ${regex} ]] && { - ${cmd} "$target" & + if [[ "$target_mimetype" =~ ${regex} ]]; then + act ${cmd} "$target"; result=$? + (( result )) && return 1 + return 0 - } + fi done - return 1 + return 3 } +# DSL +uri() { uri_handlers+=( "$1=$2" ); } +mime() { mime_handlers+=( "$1=$2" ); } + +is_uri() [[ $1 =~ ^[a-zA-Z][a-zA-Z0-9\+\.\-]+:.+ ]] + main() { - target="$1" + 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; } - handle_uri "$target" || { - [[ "$target" =~ file://.+ ]] && { target="${target##*file://}"; } + # Treat file:// as local paths. + [[ "$target" =~ ^file:(//)?(/.+) ]] && target=${BASH_REMATCH[2]} - [[ -e "$target" ]] && { - [[ "$target" =~ ^/.* ]] || { target="${PWD}/${target}"; } + if [[ -e "$target" ]]; then + [[ "$target" =~ ^/.* ]] || { target="${PWD}/${target}"; } # Turn relative paths to absolute ones. - handle_mime "$target" - } - } + 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 - [[ "$?" -gt 0 ]] && { printf "No handlers found for %s\n" "$target"; } + 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 } diff --git a/sx-open.cfg b/sx-open.cfg index 78a5fa1..4d27fe0 100644 --- a/sx-open.cfg +++ b/sx-open.cfg @@ -1,14 +1,12 @@ +#!syntax bash # Configuration file for sx-open # Note that as sx-open checks the regexes in order, they should be placed in order from specific to less so. +# Format: type cmd regex -uri_handlers=( - 'steam=^steam://.+' - 'javaws=.+kvm.+?\.cgi$' - 'browser=^https?://.+' -) +# Examples: -mime_handlers=( - 'sxiv=image/.+' -) +#uri browser '^https?:' +#uri steam '^steam:' -# vim: syntax=sh +#mime sxiv '^image/' +#mime libreoffice '^application/msword$'