ohmu
·
2026-07-25
1#!/bin/sh
2#
3# Copyright (c) 2015 Greduan <me@greduan.com>, licensed under the WTFPL
4# Adds group-like capabilities, sorta like those you find in CWM and such WMs
5
6usage() {
7 cat << EOF
8usage: $(basename $0) [-hCU] [-c wid] [-s wid group] [-tmMu group]
9 -h shows this help
10 -c cleans WID from group files (and makes it visible)
11 -C runs cleanup routine
12 -s sets WID's group
13 -t toggle group visibility state
14 -m maps (shows) group
15 -M maps group and unmaps all other groups
16 -u unmaps (hides) group
17 -U unmaps all the groups
18EOF
19
20 exit 1
21}
22
23# test for no arguments
24test $# -eq 0 && usage
25
26# I suggest it's under /tmp or somewhere that gets cleaned up at reboot or gets
27# cleaned up after X stops running
28FSDIR=${FSDIR:-/tmp/groups.sh}
29
30# define our functions
31
32# clean WID ($1) from group files
33clean_wid() {
34 t=$(mktemp /tmp/groups.XXXXXX)
35 for x in $(ls $FSDIR/group.*); do
36 sed "/$1/d" "$x" >"$t"
37 mv "$t" "$x"
38 done
39 rm -f "$t"
40}
41
42# cleans group ($1) from (in)active files
43clean_status() {
44 t=$(mktemp /tmp/groups.XXXXXX)
45 sed "/$1/d" $FSDIR/active >"$t"
46 mv "$t" $FSDIR/active
47 sed "/$1/d" $FSDIR/inactive >"$t"
48 mv "$t" $FSDIR/inactive
49}
50
51# shows all the windows in group ($1)
52map_group() {
53 # safety
54 if ! grep -q $1 < $FSDIR/all; then
55 echo "Group doesn't exist"
56 exit 1
57 fi
58
59 # clean statuses
60 clean_status $1
61 # add to active
62 echo $1 >> $FSDIR/active
63
64 # loop through group and map windows
65 xargs mapw -m <$FSDIR/group.$1
66}
67
68# hides all the windows in group ($1)
69unmap_group() {
70 # safety
71 if ! grep -q $1 < $FSDIR/all; then
72 echo "Group doesn't exist"
73 exit 1
74 fi
75
76 # clean statuses
77 clean_status $1
78 # add to inactive
79 echo $1 >> $FSDIR/inactive
80
81 # loop through group and unmap windows
82 while read line; do
83 mapw -u $line
84 done < $FSDIR/group.$1
85}
86
87# assigns WID ($1) to the group ($2)
88set_group() {
89 #so that neither grep nor ls in clean_wid complain
90 #when group.$2 does not exist
91 touch $FSDIR/group.$2
92
93 # make sure we've no duplicates
94 clean_wid $1
95 clean_status $2
96
97 # insert WID into new group if not already there
98 grep -q $1 < $FSDIR/group.$2 || \
99 echo $1 >> $FSDIR/group.$2
100
101 # if we can't find the group add it to groups and make it active
102 grep -q $2 < $FSDIR/all || \
103 echo $2 >> $FSDIR/all && \
104 echo $2 >> $FSDIR/active
105
106 # map WID if group is active
107 grep -q $2 < $FSDIR/active && \
108 mapw -m $1
109
110 # unmap WID if group is inactive
111 grep -q $2 < $FSDIR/inactive && \
112 mapw -u $1
113}
114
115# toggles visibility state of all the windows in group ($1)
116toggle_group() {
117 # safety
118 if ! grep -q $1 < $FSDIR/all; then
119 echo "Group doesn't exist"
120 return
121 fi
122
123 # search through active groups first
124 grep -q $1 < $FSDIR/active && \
125 unmap_group $1 && \
126 return
127
128 # search through inactive groups next
129 grep -q $1 < $FSDIR/inactive && \
130 map_group $1 && \
131 return
132}
133
134# removes all the unexistent WIDs from groups
135# removes all group files that don't exist
136# removes from 'all' file all groups that don't exist
137cleanup_everything() {
138 # clean WIDs that don't exist
139 # using `cat` instead of `<` because error suppression
140 cat $FSDIR/group.* 2>/dev/null | while read wid; do
141 wattr $wid || \
142 clean_wid $wid
143 done
144
145 # clean group files that are empty
146 for file in $FSDIR/group.*; do
147 # is the group empty?
148 if [ ! -s $file ]; then
149 rm -f $file
150 fi
151 done
152
153 # remove groups that don't exist from 'all'
154 while read line; do
155 if [ ! -f $FSDIR/group.$line ]; then
156 t=$(mktemp /tmp/groups.XXXXXX)
157 sed "/$line/d" $FSDIR/all >"$t"
158 mv "$t" $FSDIR/all
159 clean_status $line
160 fi
161 done < $FSDIR/all
162}
163
164# actual run logic (including arguments and such)
165
166# check $FSDIR exists
167test -d $FSDIR || mkdir -p $FSDIR
168
169# touch all the files
170test -f $FSDIR/active || :> $FSDIR/active
171test -f $FSDIR/inactive || :> $FSDIR/inactive
172test -f $FSDIR/all || :> $FSDIR/all
173
174cleanup_everything
175
176# getopts yo
177while getopts "hc:Cs:t:m:M:u:U" opt; do
178 case $opt in
179 h)
180 usage
181 ;;
182 c)
183 clean_wid $OPTARG
184 mapw -m $OPTARG
185 break
186 ;;
187 C)
188 cleanup_everything
189 break
190 ;;
191 s)
192 set_group $OPTARG $(eval echo "\$$OPTIND")
193 break
194 ;;
195 t)
196 toggle_group $OPTARG
197 break
198 ;;
199 m)
200 map_group $OPTARG
201 break
202 ;;
203 M)
204 for file in $FSDIR/group.*; do
205 group=${file##*.}
206 unmap_group $group
207 done
208 map_group $OPTARG
209 break
210 ;;
211 u)
212 unmap_group $OPTARG
213 break
214 ;;
215 U)
216 for file in $FSDIR/group.*; do
217 group=${file##*.}
218 unmap_group $group
219 done
220 break
221 ;;
222 esac
223done