/
wmgo
executable file
·182 lines (153 loc) · 4.32 KB
/
wmgo
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#!/bin/bash
# wmgo - Launcher for EWMH window managers
# based on Dmenu Launcher by Scott Garret
# We need a display
#if [[ -z "$DISPLAY" ]]; then
# exit 1
#fi
# XDG standard paths.
if [ '!' -d "$XDG_CACHE_HOME" ]; then
XDG_CACHE_HOME="$HOME/.cache"
fi
if [ '!' -d "$XDG_CONFIG_HOME" ]; then
XDG_CONFIG_HOME="$HOME/.config"
fi
if [ '!' -d "$XDG_DATA_HOME" ]; then
XDG_DATA_HOME="$HOME/.local/share"
fi
if [ -z "$XDG_DATA_DIRS" ]; then
XDG_DATA_DIRS="/usr/share:/usr/local/share"
fi
# Path to Dmenu Launcher cache will be stored.
cache="$XDG_CACHE_HOME/wmgo.cache"
# Path to history file.
hist="$XDG_CACHE_HOME/wmgo.history"
# Path to config
conf="$XDG_CONFIG_HOME/wmgo/config"
# Source config file if exists
if [ -f $conf ]; then
source $conf
fi
# Set terminal if unset
if [[ -z "$TERMCMD" ]]; then
TERMCMD="xterm -e"
fi
# Choose proper LSX binary.
if which 'lsx-suckless' &> /dev/null; then
lsx=lsx-suckless
else
lsx=lsx
fi
# Use gtk-launch for desktop files, if present.
if which 'gtk-launch' &> /dev/null; then
gtklaunch=gtk-launch
else
unset gtklaunch
fi
function get-open-windows {
wmctrl -l | cut -d' ' -f5-
}
function raise-window {
wmctrl -a "$@"
}
function get-applications {
# Create cache directory if it doesn't exist.
mkdir -p "${cache%/*}"
# Cache names and executable paths of XDG shortcuts.
xdg_paths=$(echo "$XDG_DATA_DIRS:$XDG_DATA_HOME" | sed 's/:/ /g')
for path in $xdg_paths; do
for file in $(printf '%s/applications/*.desktop\n' "$path"); do
if [ -f "$file" ]; then
# Grab the friendly name and path of the executable.
# (Thanks, <geirha@freenode/#awk>.)
if [ -z "$gtklaunch" ]; then
awk -F'=' '$1 == "Name" {sub(/Name=/, "", $0); name=$0}
$1 == "Exec" {sub(/Exec=/, "", $0); exec=$0}
END { print name "|" exec }' "$file" 2> /dev/null
else
name=$(egrep ^Name= "$file" | head -n 1 | cut -d= -f2)
echo "$name|$gtklaunch $(basename $file)"
fi
fi
done
done > "$cache"
# Start printing out the menu items, starting with XDG
# shortcut names...
sed 's/|.*$//' "$cache" | sort -u
# ...then, the binary names...
(IFS=':'; $lsx $PATH | sort -u)
}
function cache-menu {
get-applications > "${cache}-menu.new"
mv "${cache}-menu"{.new,}
}
function update-history () {
(echo "$1"; head -9 "$hist" | grep -Fvx "$1") > "$hist.new"
mv "$hist"{.new,}
}
build_hist_menu () {
mkdir -p "${hist%/*}"
touch "$hist"
menu_items=$(build_menu)
hist_items=$(grep -Fx "$(echo "$menu_items")" "$hist")
echo "$hist_items" > "$hist" # Keep the history file free of invalids.
# There's probably a better way, but this works, for now.
if [[ ${#hist_items} > 1 ]]; then
echo "$hist_items"
echo "$menu_items" | grep -Fvx "$hist_items"
else
echo "$menu_items"
fi
}
cmd-exists () {
which "$1" &> /dev/null
}
dm-prompt() {
if [ -n "$FONT" ]; then
echo -e "$2" | dmenu -p "$1" -fn "${FONT}" -i ${DMENU_OPTIONS}
else
echo -e "$2" | dmenu -p "$1" -i ${DMENU_OPTIONS}
fi
}
launch () {
if [[ $1 == "1" ]]; then
$TERMCMD "${@:2} && echo 'Press any key to close...' && read"
else
# Shouldn't be set when there won't be a terminal attached anymore...
# ...and won't be interactive...
export TERM='dumb'
unset PS1
"${@:2}" </dev/null &>/dev/null & disown
fi
}
# Cache menu in background
cache-menu &
# If cache exists use cache, else build cache
if [[ ! -f "${cache}-menu" ]]; then
apps="$(get-applications)"
else
apps=`cat "${cache}-menu"`
fi
wins="$(get-open-windows)"
cmd=$(dm-prompt "!" "$wins\n$apps")
# If nothing is selected -- exit
[[ -z $cmd ]] && exit
if [[ $wins == *$cmd* ]]; then
raise-window "$cmd" && exit
fi
interm=0
if [[ "${cmd: -1}" == ";" ]]; then
cmd="${cmd%?}"
interm=1
fi
# If the selection doesn't exist, see if it's an XDG shortcut.
if ! cmd-exists $cmd; then
cmd=$(grep -F "$cmd|" "$cache" | sed 's/.*|//;s/ %.//g')
# If there's more than one, ask which binary to use.
[[ "$(echo "$cmd" | wc -l)" != '1' ]] &&
cmd=$(dm-prompt "Which one?" "$cmd")
[[ -z "$cmd" ]] && exit
fi
if cmd-exists $cmd; then
launch $interm $cmd
fi