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