citadel

My dotfiles, scripts and nix configs
git clone git://jb55.com/citadel
Log | Files | Refs | README | LICENSE

xdg-open (2618B)


      1 #!/usr/bin/env bash
      2 
      3 readonly CONFIG="$HOME/.config/mimi/mime.conf"
      4 
      5 find_in_config() {
      6 	[[ -f "$CONFIG" ]] || return
      7 	grep -m 1 "^$1: " "$CONFIG" | cut -d ' ' -f 2-
      8 }
      9 
     10 need_terminal() {
     11 	grep -m 1 -q '^Terminal=true$'
     12 }
     13 
     14 find_exec_in_desktop_file() {
     15 	awk -F '[= ]' '$1 == "Exec" {print $2; exit}'
     16 }
     17 
     18 find_desktop_file_by() {
     19 	[[ -d "$HOME/.local/share/applications" ]] && path+=("$HOME/.local/share/applications")
     20 	grep -m 1 "^$1=.*$2" -R "${path[@]}" | awk -F : -v pat="$2" '{ print index($2, pat), length($2), $1 }' | sort -t ' ' -k1,1n -k2,2nr | awk '{ print $3; exit }'
     21 }
     22 
     23 url_decode() {
     24 	echo -e "$(sed 's/%\([a-f0-9A-F]\{2\}\)/\\x\1/g')"
     25 }
     26 
     27 fork_run() {
     28 	echo "$*"
     29 	"$@" &>/dev/null &
     30 	exit 0
     31 }
     32 
     33 exist() {
     34 	type "$@" &>/dev/null
     35 }
     36 
     37 usage() {
     38 	cat <<-EOF
     39 
     40 	Usage: xdg-open [file|directory|protocol]
     41 
     42 	It opens a file according to the extension
     43 	To setup the extension, create $CONFIG
     44 
     45 	mimi :)
     46 	EOF
     47 	exit 1
     48 }
     49 
     50 # config
     51 # 1. ext
     52 # 2. protocol
     53 # 3. mime
     54 # 4. general mime
     55 # .desktop (mime and general mime)
     56 # 5. ask
     57 
     58 [[ ! "$*" ]] && usage
     59 
     60 arg="$*"
     61 ext=''
     62 protocol=''
     63 mime=''
     64 general_mime=''
     65 
     66 # fix file://
     67 if [[ "$arg" =~ ^file://(.*)$ ]]; then
     68 	# strip file://
     69 	arg="$(url_decode <<<"${BASH_REMATCH[1]}")"
     70 	protocol=file
     71 fi
     72 
     73 if [[ -e "$arg" ]]; then
     74 	# file or dir
     75 	mime="$(file -ib "$arg" | cut -d';' -f1)"
     76 	if [[ -f "$arg" ]]; then
     77 		ext="$(tr '[:upper:]' '[:lower:]' <<< "${arg##*.}")"
     78 	fi
     79 fi
     80 
     81 # protocol to mime ext
     82 if [[ "$arg" =~ ^([a-zA-Z-]+): ]]; then
     83 	# use protocol to guess mime ext
     84 	protocol="${BASH_REMATCH[1]}"
     85 	case "$protocol" in
     86 		http|https)
     87 			mime=text/html
     88 			ext=html
     89 			;;
     90 		magnet)
     91 			mime=application/x-bittorrent
     92 			ext=torrent
     93 			;;
     94 		irc)
     95 			mime=x-scheme-handler/irc
     96 			;;
     97 	esac
     98 fi
     99 
    100 
    101 # application mime is specific
    102 [[ "$mime" =~ ^(audio|image|text|video)/ ]] && general_mime="${BASH_REMATCH[1]}/"
    103 
    104 exist "$TERM" || TERM="$(find_in_config TERM)"
    105 
    106 # config
    107 for search in $ext $protocol $mime $general_mime; do
    108 	app=($(find_in_config "$search"))
    109 	[[ "${app[0]}" == TERM ]] && exist "$TERM" && app[0]="$TERM"
    110 	[[ "${app[*]}" ]] && fork_run "${app[@]}" "$arg"
    111 done
    112 
    113 # .desktop
    114 for search in $mime $general_mime; do
    115 	desktop="$(find_desktop_file_by MimeType "$search")"
    116 	if [[ "$desktop" ]]; then
    117 		echo "$desktop"
    118 		app=($(find_exec_in_desktop_file <"$desktop"))
    119 		if need_terminal <"$desktop"; then
    120 			echo "term: $TERM"
    121 			exist "$TERM" && fork_run "$TERM" -e "${app[@]}" "$arg"
    122 		else
    123 			fork_run "${app[@]}" "$arg"
    124 		fi
    125 	fi
    126 done
    127 
    128 # ask
    129 if exist dmenu; then
    130 	app=($(IFS=: stest -flx $PATH | sort -u | dmenu -p "how to open $arg"))
    131 	[[ "${app[*]}" ]] && fork_run "${app[@]}" "$arg"
    132 fi