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