Include notionflux in the main repo instead of its own submodule
[notion/jeffpc.git] / contrib / statusd / statusd_exec.lua
blobfd5958ca66cd2d56e64a8c9a0a237c5c0b74b7ee
1 -- Authors: Antti Vähäkotamäki
2 -- License: LGPL, version 2.1 or later
3 -- Last Changed: 2006
4 --
5 -- statusd_exec.lua
6 --
7 --
8 -- -- What is this?
9 --
10 -- This is a simple "general" statusd Lua script which
11 -- lets you show output of external programs in ion
12 -- statusbar. This is convenient if you are not familiar
13 -- with Lua but can handle yourself with some other
14 -- language enough to output what you would want the
15 -- statusbar to show.
17 -- After this script is loaded it starts executing all
18 -- the provided programs (wether a placeholder exists in
19 -- template or not) and updates the statusbar every time
20 -- one of them prints (and flushes) a line.
21 --
22 -- -- How to use it?
24 -- 1 ) update statusbar template to include %exec_something
25 -- 2 ) specify parameters in cfg_statusbar.lua like this:
27 -- mod_statusbar.launch_statusd{
29 -- [ ... some other config here ... ],
31 -- exec = {
33 -- -- show date each second in %exec_date with.. date!
34 --
35 -- date = {
36 -- program = 'date',
37 -- retry_delay = 1 * 1000,
38 -- },
39 --
40 -- -- show percentage of hda1 every 30 seconds in
41 -- -- %exec_hda1u with df, grep and sed.
42 -- -- also highlights entry if usage is high.
44 -- hda1u = {
45 -- program = 'df|grep hda1|sed "s/.*\\(..%\\).*/\\1/"',
46 -- retry_delay = 30 * 1000,
47 -- meter_length = 4,
48 -- hint_regexp = {
49 -- important = '9[456].',
50 -- critical = {
51 -- '9[789].',
52 -- '1...',
53 -- },
54 -- },
55 -- },
56 --
57 -- -- keep continous track of a remote machine in
58 -- -- %exec_remote with ssh, bash and uptime.
59 -- -- if the connection breaks, wait 60 seconds and retry
60 --
61 -- remote = {
62 -- program = 'ssh -tt myhost.com "while (uptime);' ..
63 -- 'do sleep 1; done"',
64 -- retry_delay = 60 * 1000,
65 -- },
66 -- }
67 -- }
69 -- -- Description of variables:
70 --
71 -- * program
72 -- The program to execute. The last line of each
73 -- flushed output this program writes to stdout is
74 -- inserted as the content of the meter.
76 -- * retry_delay (optional)
77 -- The delay to wait (ms) before running the program again
78 -- once it stops sending data. Some programs just
79 -- send the data and exit while others continue
80 -- sending data periodically. This value can be used
81 -- to control the update rate for the first type of
82 -- programs. You can also specify a value for the other
83 -- type of programs to retry if the program stops for
84 -- some reason.
86 -- * meter_length (optional)
87 -- The space reserved for this meter in characters.
88 -- If the value is not specified or is less than 1
89 -- then the space is determined by the length of the
90 -- data being shown but some people do not want their
91 -- statusbar width to change randomly.
93 -- * hint_regexp (optional)
94 -- These regular expressions (in Lua syntax) are
95 -- matched with the data and in case of a match the
96 -- named hint is set to the meter. The value can be
97 -- either a string containing the regexp or a table
98 -- containing several possible regexps (Lua regexp
99 -- doesn't have an 'or'). By default the themes define
100 -- a color for 'important' and 'critical' hints.
104 local settings = table.join( statusd.get_config("exec"), {} )
105 local start_execution = nil
106 local timers = {}
108 -- Function for starting and restarting execution of a process
110 start_execution = function ( key )
112 -- Set up a function for receiving the data
113 -- and informing the statusbar
115 local process_input = function ( new_data )
117 local received_data = ""
119 -- When we get new data, output the last complete line
121 while new_data do
122 received_data = received_data .. new_data
124 -- Erase old data which we do not need anymore
126 received_data = string.gsub( received_data,
127 ".*\n(.*\n.*)", "%1" )
129 -- Set the last complete line as the current line
131 local current_line = string.gsub( received_data,
132 "(.*)\n.*", "%1" )
134 local t_key = "exec_" .. key
135 local t_length = settings[key].meter_length
136 local h_regexp = settings[key].hint_regexp
138 if not tlength or t_length < 1 then
139 t_length = string.len( current_line )
142 statusd.inform( t_key .. "_hint", '' )
143 statusd.inform( t_key .. "_template",
144 string.rep( 'x', t_length ) )
145 statusd.inform( t_key, current_line )
147 if not h_regexp then h_regexp = {} end
149 for hint, re in pairs( h_regexp ) do
150 if ( type( re ) == 'string' ) then
151 re = { re }
154 for _, r in ipairs( re ) do
155 if ( string.find( current_line, r ) ) then
156 statusd.inform(t_key .. "_hint", hint)
161 -- Wait for bgread to signal that more data
162 -- is available or the program has exited
164 new_data = coroutine.yield()
167 -- Program has exited.
168 -- Start a timer for a new execution if set.
170 if settings[key].retry_delay then
171 timers[key]:set( settings[key].retry_delay,
172 function()
173 start_execution(key)
174 end )
178 -- Set up a simple function for printing errors
180 local process_error = function( new_data )
181 while new_data do
182 io.stderr:write( "ion-statusd [statusd_exec, key='"
183 .. key .. "']: " .. new_data )
184 io.stderr:flush()
185 new_data = coroutine.yield()
189 -- Execute the program in the background and create
190 -- coroutine functions to handle input and error data
192 statusd.popen_bgread( settings[key].program,
193 coroutine.wrap( process_input ),
194 coroutine.wrap( process_error ) )
198 -- Now start execution of all defined processes
200 for key in pairs(settings) do
201 timers[key] = statusd.create_timer()
202 start_execution(key)
206 -- Copyright (c) Antti Vähäkotamäki 2006.
208 -- Ion is free software; you can redistribute it and/or modify it under
209 -- the terms of the GNU Lesser General Public License as published by
210 -- the Free Software Foundation; either version 2.1 of the License, or
211 -- (at your option) any later version.