]> git.lizzy.rs Git - bspwm.git/blob - examples/external_rules/ruld
e4a8674c3ba8c6efbd6221a93c9605a8902fd05a
[bspwm.git] / examples / external_rules / ruld
1 #! /usr/bin/env lua
2
3 local p = require("posix")
4 local port = 54321
5
6 local short = "hp:"
7 local long = {
8     {"help", "none", 'h'},
9     {"port", "required", 'p'},
10 }
11
12 local rules = {}
13
14 for opt, optarg, optind, longind in p.getopt(arg, short, long) do
15     if opt == '?' then
16         print("Unrecognized option")
17         os.exit(1)
18     elseif opt == 'h' then
19         print("Usage: ruld [-h|-p PORT]")
20         os.exit(0)
21     elseif opt == 'p' then
22         port = optarg
23     end
24 end
25
26 function eval(exp, env)
27     local f
28     local value = "return " .. exp
29     if env then
30         f = load(value, nil, nil, env)
31     else
32         f = load(value)
33     end
34     return f and f()
35 end
36
37 function test(env)
38     local rsp = ""
39     for index = #rules, 1, -1 do
40         local entry = rules[index]
41         if eval(entry[1], env) then
42             local delay, duration
43             if entry[3] then
44                 delay = entry[3].delay
45                 duration = entry[3].duration
46                 if delay and delay > 0 then
47                     entry[3].delay = delay - 1
48                 end
49                 if ((not delay) or delay == 0) and duration and duration > 0 then
50                     entry[3].duration = duration - 1
51                 end
52             end
53             if (((not delay) or delay == 0) and ((not duration) or duration > 0)) then
54                 if #rsp > 0 then
55                     rsp = rsp .. " " .. entry[2]
56                 else
57                     rsp = entry[2]
58                 end
59             end
60             if duration and duration <= 1 then
61                 table.remove(rules, index)
62             end
63         end
64     end
65     return rsp
66 end
67
68 local fd = p.socket(p.AF_INET, p.SOCK_STREAM, 0)
69 p.setsockopt(fd, p.SOL_SOCKET, p.SO_REUSEADDR, 1)
70 p.bind(fd, {family=p.AF_INET, addr="127.0.0.1", port=port})
71 p.listen(fd, p.SOMAXCONN)
72 local running = true
73
74 while running do
75     ret_fd = p.accept(fd)
76     if ret_fd then
77         local msg = p.recv(ret_fd, p.BUFSIZ)
78         if msg then
79             local cmd, data = nil
80             sep = msg:find(" ")
81             if sep then
82                 cmd = msg:sub(1, sep - 1)
83                 data = msg:sub(sep + 1)
84             else
85                 cmd = msg
86             end
87             if cmd == "test" then
88                 local env = eval(data)
89                 if env then
90                     rsp = test(env)
91                     p.send(ret_fd, rsp)
92                 end
93             elseif cmd == "add" then
94                 local value = eval(data)
95                 if value then
96                     table.insert(rules, value)
97                 end
98             elseif cmd == "remove" then
99                 if data == "tail" then
100                     table.remove(rules, #rules)
101                 elseif data == "head" then
102                     table.remove(rules, 1)
103                 else
104                     for index = #rules, 1, -1 do
105                         if rules[index][1]:find(data) then
106                             table.remove(rules, index)
107                         end
108                     end
109                 end
110             elseif cmd == "quit" then
111                 running = false
112             elseif cmd == "list" then
113                 local rsp = ""
114                 for index, entry in pairs(rules) do
115                     rsp = rsp .. string.format("%s => %s", entry[1], entry[2])
116                     if entry[3] then
117                         if entry[3].delay then
118                             rsp = rsp .. string.format(" @%i", entry[3].delay)
119                         end
120                         if entry[3].duration then
121                             rsp = rsp .. string.format(" +%i", entry[3].duration)
122                         end
123                     end
124                     if index < #rules then
125                         rsp = rsp .. "\n"
126                     end
127                 end
128                 p.send(ret_fd, rsp)
129             end
130         end
131         p.close(ret_fd)
132     end
133 end
134
135 p.close(fd)