-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.lua
executable file
·361 lines (267 loc) · 8.03 KB
/
main.lua
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
function AddDisplayValue(name, value, fmtstr, colormap)
local valstr
if fmtstr ~= nil
then
valstr=string.format(fmtstr, value)
else
valstr=value
end
display_values[name]=valstr
if colormap ~= nil
then
display_values[name..":color"]=AutoColorValue(value, colormap)..valstr.."~0"
end
end
function GetDisplayVars(str)
local vars={}
toks=strutil.TOKENIZER(settings.display, "$(|^(|@(|>(|)", "ms")
str=toks:next()
while str ~= nil
do
if str=="$(" or str=="@(" or str==">(" or str== "^(" then table.insert(vars, str..toks:next()..")") end
str=toks:next()
end
return vars
end
-- this function adds lookup functions to the 'lookups' table
-- using the badly named 'name' variable which contains the name
-- of a lookup as it appeared in the main config string for the
-- display bar
function InitializeLookup(lookups, name)
local check_names={}
local prefix
-- set any counter vars to zero initially, so that when the lookup
-- function is called it's counting from the right value!
prefix=string.sub(name, 1, 1)
name=string.sub(name, 3, string.len(name) -1)
if prefix=="@"
then
display_values[name]=0
elseif prefix==">"
then
display_values[name]=0
KvUpdateListFile(name, value)
end
check_names={["time"]=1, ["date"]=1, ["day_name"]=1, ["day"]=1, ["month"]=1, ["month_name"]=1, ["year"]=1, ["hours"]=1, ["minutes"]=1, ["mins"]=1, ["seconds"]=1, ["secs"]=1}
if check_names[name] ~= nil or string.sub(name, 1, 6) == "tztime" or string.sub(name, 1, 6) == "tzdate"
then
table.insert(lookups, LookupTimes)
end
if string.sub(name, 1, 4) == "bat:" or string.sub(name, 1, 5) == "bats:"
then
table.insert(lookups, LookupBatteries)
end
if string.sub(name, 1,3) == "fs:"
then
table.insert(lookups, LookupPartitions)
end
if string.sub(name, 1, 8) == "cpu_temp"
then
table.insert(lookups, LookupTemperatures)
end
if name == "cpu_count" or string.sub(name, 1, 4) == "load"
then
table.insert(lookups, CpuUsage)
end
if string.sub(name, 1, 9) == "cpu_freq:"
then
table.insert(lookups, CpuFreq)
end
if string.sub(name, 1, 4) == "load"
then
table.insert(lookups, LookupLoad)
end
if string.sub(name, 1, 3) == "ip4"
then
table.insert(lookups, LookupIPv4)
end
if string.sub(name, 1, 3) == "up:"
then
table.insert(lookups, LookupServicesUp)
if lookup_values.ServicesUp == nil then lookup_values.ServicesUp={} end
table.insert(lookup_values.ServicesUp, string.sub(name, 4))
end
if string.sub(name, 1, 4) == "dns:" or string.sub(name,1,6)=="dnsup:"
then
table.insert(lookups, LookupDNS)
if lookup_values.DNSLookups == nil then lookup_values.DNSLookups={} end
table.insert(lookup_values.DNSLookups, name)
end
end
-- this function checks which values have been asked for in a display string, and adds the functions needed to look
-- those items up into the 'lookups' table.
function LookupsFromDisplay(display)
local lookups={}
local var_names
-- always lookup basic host details
table.insert(lookups, LookupHostInfo)
var_names=GetDisplayVars(display)
for i, var in ipairs(var_names)
do
InitializeLookup(lookups, var)
end
for i,mod in ipairs(lookup_modules)
do
mod:init(lookups, display)
end
return lookups
end
--this function does the actual building of the output string
--it first calls all the lookups to get up-to-date values, then
--builds an output string using those values and does any
--display translation
function SubstituteDisplayValues(settings)
local toks, str, func, feed
local output=""
-- read up to date values from any key-value files
for i,feed in ipairs(settings.datafeeds)
do
if feed.type=="kvfile" then KvFileRead(feed) end
end
-- call alll lookup functions to get up to date values
for i,func in ipairs(settings.lookups)
do
func()
end
-- go through display string extracting any variables and
-- substituting them for up-to-date values
toks=strutil.TOKENIZER(settings.display, "$(|^(|@(|>(|)", "ms")
str=toks:next()
while str ~= nil
do
if str=="$(" or str=="^(" or str=="@(" or str==">("
then
str=toks:next()
if display_values[str] ~= nil
then
output=output .. display_translations:process(str, display_values[str])
end
elseif strutil.strlen(str) and str ~= ")"
then
output=output..str
end
str=toks:next()
end
if string.find(output, '%(') ~= nil then io.stderr:write("ERR: ["..output.."]\n") end
return output
end
function HandleShellSignals()
-- if we are talking to a shell in a pty (we are in xterm or terminal mode) then
-- there are signals that we must propgate to the pty
if shell ~= nil
then
if process.SIGWINCH ~= nil and process.sigcheck(process.SIGWINCH)
then
shell:ptysize(term:width(), term:length() - settings.steal_lines)
end
if process.SIGINT ~= nil and process.sigcheck(process.SIGINT)
then
shell:write("\x03",1)
end
end
end
function HandleExitedChildProcesses()
-- if any child processes have exited, then collect them here
if process.collect ~= nil
then
process.collect()
else
-- old function call, will go away eventually
process.childExited(-1)
end
end
function ApplicationSetup()
-- assume our output device, whatever it is, can support unicode UTF8
terminal.utf8(3)
-- load some initial settings defaults
SettingsInit()
-- init display_translations system
display_translations=DisplayTranslations()
-- parse command-line, then load config files (which might have been specified on command-line)
-- then parse command-line again because we want command-line options to override config-files
ParseCommandLineConfigFiles(arg)
LoadConfigFiles()
ParseCommandLine(arg)
-- load any modules that extend functionality
LoadModules()
settings.lookups=LookupsFromDisplay(settings.display)
DataSockAdd(settings.datasock)
Out=OpenOutput(settings)
poll_streams:add(Out)
if settings.output == "term"
then
if strutil.strlen(settings.foreground) > 0
then
settings.term_foreground=TranslateColorName(settings.foreground)
end
if strutil.strlen(settings.background) > 0
then
settings.term_background=string.upper(TranslateColorName(settings.background))
end
end
last_time=0
end
function UpdateDisplay()
last_time=now
str=SubstituteDisplayValues(settings)
str=TranslateColorStrings(settings, str)
str=terminal.format(str)
display_update_required=false
-- dwm uses the 'name' value of the root window as it's input, so we have to set that
if settings.output == "dwm"
then
os.execute("xsetroot -name '"..str.."'")
-- for other 'bar' programs we write to standard out
else
Out:writeln(str)
Out:flush()
end
lookup_counter=lookup_counter+1
end
-- MAIN STARTS HERE
ApplicationSetup()
while true
do
now=time.secs()
if now ~= last_time then display_update_required=true end
if display_update_required == true then UpdateDisplay() end
-- if we are talking to a shell in a pty and
-- if we have a recent enough libUseful-lua to support signals, then
-- watch for sigwinch (signal for 'window size changed') and sig int (ctrl-c)
if shell ~= nil
then
if process.SIGWINCH ~= nil then process.sigwatch(process.SIGWINCH) end
if process.SIGINT ~= nil then process.sigwatch(process.SIGINT) end
end
S=poll_streams:select(100)
if S ~= nil
then
if S==stdio
then
shell:write(stdio:getch(), 1)
elseif S==shell
then
shell_result=TerminalReadFromPty()
if shell_result==SHELL_CLOSED then break end
if shell_result==SHELL_CLS then display_update_required=true end
-- activity coming from lemonbar or dzen or other 'bar' program
elseif S==Out
then
ProcessBarProgramOutput(S:readln())
-- our listening datasocket has recieved a connection, accept a new client who will
-- send us messages
elseif S==datasock:get_stream()
then
S=datasock:accept()
poll_streams:add(S)
-- anything else must be coming from a client program that has connected to our datasock
elseif KvLineRead(S) == false
then
poll_streams:delete(S)
S:close()
end
end
HandleShellSignals();
HandleExitedChildProcesses()
end
if settings.ypos=="bottom" then term:clear() end