2 -- ion/mod_statusbar/mod_statusbar.lua
4 -- Copyright (c) Tuomo Valkonen 2004-2009.
6 -- See the included file LICENSE for details.
9 -- This is a slight abuse of the package.loaded variable perhaps, but
10 -- library-like packages should handle checking if they're loaded instead of
11 -- confusing the user with require/include differences.
12 if package
.loaded
["mod_statusbar"] then return end
14 if not ioncore
.load_module("mod_statusbar") then
18 local mod_statusbar
=_G
["mod_statusbar"]
28 function mod_statusbar
.inform(name
, value
)
35 -- Template processing {{{
37 local function process_template(template
, meter_f
, text_f
, stretch_f
)
38 local st
, en
, b
, c
, r
, p
, tmp
42 st
, en
, b
, r
=string.find(template
, '^(.-)%%(.*)')
50 -- Add preciding text as normal text element
55 -- Check for '% ' and '%%'
56 st
, en
, c
, r
=string.find(template
, '^([ %%])(.*)')
66 -- Extract [alignment][zero padding]<meter name>
67 local pat
='([<|>]?)(0*[0-9]*)([a-zA-Z0-9_]+)'
69 st
, en
, c
, p
, b
, r
=string.find(template
, '^{'..pat
..'}(.*)')
72 st
, en
, c
, p
, b
, r
=string.find(template
, '^'..pat
..'(.*)')
75 meter_f(b
, c
, tonumber(p
))
85 function mod_statusbar
.template_to_table(template
)
87 local m
=meters
--set_date(stng, meters)
88 local aligns
={["<"]=0, ["|"]=1, [">"]=2}
90 process_template(template
,
94 table.insert(res
, {type=4})
95 elseif (string.find(s
, "^systray$") or
96 string.find(s
, "^systray_")) then
107 tmpl
=meters
[s
.."_template"],
130 mod_statusbar
._set_template_parser(mod_statusbar
.template_to_table
)
138 -- Update statusbar contents. To be called after series
139 -- of \fnref{mod_statusbar.inform} calls.
140 function mod_statusbar
.update(update_templates
)
141 for _
, sb
in pairs(mod_statusbar
.statusbars()) do
142 if update_templates
then
143 local t
=sb
:get_template_table()
144 for _
, v
in pairs(t
) do
146 v
.tmpl
=meters
[v
.meter
.."_template"]
149 sb
:set_template_table(t
)
158 -- ion-statusd support {{{
162 function mod_statusbar
.rcv_statusd(str
)
167 local function doline(i
)
169 mod_statusbar
.update(updatenw
)
172 local _
, _
, m
, v
=string.find(i
, "^([^:]+):%s*(.*)")
174 mod_statusbar
.inform(m
, v
)
175 updatenw
=updatenw
or string.find(m
, "_template")
183 data
=string.gsub(data
..str
, "([^\n]*)\n", doline
)
184 str
=coroutine
.yield(updated
)
187 ioncore
.warn(TR("ion-statusd quit."))
190 mod_statusbar
.update(updatenw
)
194 function mod_statusbar
.get_modules()
196 local specials
={["filler"]=true, ["systray"]=true}
198 for _
, sb
in pairs(mod_statusbar
.statusbars()) do
199 for _
, item
in pairs(sb
:get_template_table()) do
200 if item
.type==2 and not specials
[item
.meter
] then
201 local _
, _
, m
=string.find(item
.meter
, "^([^_]*)");
213 function mod_statusbar
.cfg_statusd(cfg
)
214 if date_format_backcompat_kludge
then
216 cfg
=table.copy(cfg
, false)
217 cfg
.date={date_format
=date_format_backcompat_kludge
}
218 elseif not cfg
.date.date_format
then
219 cfg
=table.copy(cfg
, true)
220 cfg
.date.date_format
=date_format_backcompat_kludge
224 --TODO: don't construct file name twice.
225 ioncore
.write_savefile("cfg_statusd", cfg
)
226 return ioncore
.get_savefile("cfg_statusd")
230 function mod_statusbar
.rcv_statusd_err(str
)
237 -- Load modules and launch \file{ion-statusd} with configuration
238 -- table \var{cfg}. The options for each \file{ion-statusd} monitor
239 -- script should be contained in the corresponding sub-table of \var{cfg}.
240 function mod_statusbar
.launch_statusd(cfg
)
241 if statusd_pid
>0 then
245 -- Launch tried, don't do it automatically after reading
247 mod_statusbar
.no_autolaunch
=true
249 local mods
=mod_statusbar
.get_modules()
252 for m
in pairs(mods
) do
253 if dopath("statusbar_"..m
, true) then
258 -- Lookup ion-statusd
259 local statusd_script
="ion-statusd"
260 local statusd
=ioncore
.lookup_script(statusd_script
)
262 ioncore
.warn(TR("Could not find %s", statusd_script
))
267 local function initrcverr(str
)
268 statusd_errors
=(statusd_errors
or "")..str
271 local cfg
=mod_statusbar
.cfg_statusd(cfg
or {})
273 for k
in pairs(mods
) do params
=params
.." -m "..k
end
274 local cmd
=statusd
.." -c "..cfg
..params
276 local rcv
=coroutine
.wrap(mod_statusbar
.rcv_statusd
)
277 local rcverr
=mod_statusbar
.rcv_statusd_err
279 statusd_pid
=mod_statusbar
._launch_statusd(cmd
,
283 if statusd_errors
then
284 warn(TR("Errors starting ion-statusd:\n")..statusd_errors
)
287 if statusd_pid
<=0 then
288 warn(TR("Failed to start ion-statusd."))
295 -- Initialisation and default settings {{{
298 -- Create a statusbar. The possible parameters in the
299 -- table \var{param} are:
301 -- \begin{tabularx}{\linewidth}{llX}
302 -- Variable & Type & Description \\
303 -- \var{template} & string & The template; see
304 -- Section \ref{sec:statusbar}. \\
305 -- \var{pos} & string & Position: \codestr{tl}, \codestr{tr},
306 -- \codestr{bl} or \codestr{br}
307 -- (for the obvious combinations of
308 -- top/left/bottom/right). \\
309 -- \var{screen} & integer & Screen number to create the statusbar on. \\
310 -- \var{fullsize} & boolean & If set, the statusbar will waste
311 -- space instead of adapting to layout. \\
312 -- \var{systray} & boolaen & Swallow (KDE protocol) systray icons. \\
315 function mod_statusbar
.create(param
)
316 local scr
=ioncore
.find_screen_id(param
.screen
or 0)
318 error(TR("Screen not found."))
321 if not param
.force
then
322 local stdisp
=scr
:get_stdisp()
323 if stdisp
and stdisp
.reg
then
324 error(TR("Screen already has an stdisp. Refusing to create a "..
329 local sb
=scr
:set_stdisp({
331 pos
=(param
.pos
or "bl"),
332 fullsize
=param
.fullsize
,
334 template
=param
.template
,
335 template_table
=param
.template_table
,
336 systray
=param
.systray
,
340 error(TR("Failed to create statusbar."))
347 -- Function to terminate \file{ion-statusd} on exit or reload. Should
348 -- be called from hook \var{deinit}.
349 function mod_statusbar
.terminate_statusd()
350 if statusd_pid
==0 then
354 mod_statusbar
._terminate_statusd(statusd_pid
)
360 ioncore
.get_hook("ioncore_deinit_hook"):add(mod_statusbar
.terminate_statusd
)
365 -- Mark ourselves loaded.
366 package
.loaded
["mod_statusbar"]=true
369 -- Load user configuration file
370 dopath('cfg_statusbar', true)
372 -- Launch statusd if the user didn't launch it.
373 if not mod_statusbar
.no_autolaunch
then
374 mod_statusbar
.launch_statusd()