1 -- Authors: Hendrik Iben <hiben@tzi.de>
2 -- License: GPL, version 2
3 -- Last Changed: 2006-03-23
5 -- statusd_fortune.lua v20060323
7 -- Displays a fortune (in a sane way for one line).
8 -- My first attempt at writing in lua and for ion.
10 -- Written by Hendrik Iben < hiben at tzi dot de >
13 -- fortune provides a monitor for statusd.
14 -- This monitor is feed with a fortune obtained from the famous fortune-
15 -- program. But as fortunes can span several lines and the ion-statusbar
16 -- only provides one line there is some conversion done.
18 -- As a user you can influence the way this conversion is done by specifying
19 -- with what string empty space and newlines are to be replaced. Or just
20 -- leave the defaults.
22 -- For a start you can simple add '%fortune' to your statusbar-template.
25 -- ion3 (tested with 20060305 gentoo ebuild)
26 -- lua (tested with 5.0.2)
27 -- fortune (any version will do) or anything that returns text :-)
30 -- The settings you can specify (and their defaults) are :
31 -- interval : minimum time between fortune updates (60 seconds)
32 -- minwait : additional time to always wait for a fortune (6 seconds)
33 -- cpers : number of characters to increase waiting by one second (20)
34 -- command : command to obtain a fortune (fortune -s)
35 -- prefix : head of every fortune
36 -- postfix : tail of every fortune
37 -- spacereplace : string that replaces empty space of more than 3 characters
39 -- newline : string that replaces newlines (' > ')
40 -- newlinetrick : try to be smart when killing newlines (true)
42 -- Setting 'interval' and 'minwait' together might seem useless but when
43 -- calculating the waiting time the maximum of 'minwait' and the time
44 -- resulting from 'cpers' is added to 'interval'. The defaults for 'minwait'
45 -- and 'cpers' are taken from fortunes source.
47 -- The default command triggers a short fortune (see: man fortune) as long
48 -- fortunes tend to fill more than one line in the status-bar. You may wish
49 -- to enable offending fortunes but I personally don't like them that much...
50 -- In my opinion the statusbar should offer things like scrolling text but
51 -- eventually I will implement this in a later release of this monitor...
53 -- Enabling 'newlinetrick' basicly makes this program look at the ending and
54 -- beginning of the two lines and check if they are *meant* to be separated.
55 -- Currently this merges lines that end and begin with lower-case-letters and
56 -- silently removes newlines in front of 'cite-signs' (e.g.
57 -- "...blah\n-- Hendrik" becomes "...blah -- Hendrik").
59 -- Example configuration :
60 -- cfg_statusbar (rotate_statusbar that is)
63 -- rotate_statusbar.configurations = {
67 -- prefix = "Fortune : ",
68 -- interval = 30*1000,
73 -- rotate_statusbar.settings = {
77 -- "[ %date || %xmmsip_user ]%filler%systray",
78 -- "[ %fortune ]%filler%systray",
82 -- This setup makes the basic fortune update all 30 seconds and prepends
83 -- every fortune with 'Fortune : '. Also using rotate_statusbar I decided
84 -- to give fortunes the full bar turning of the date-monitor so I don't
85 -- perceive how much time I spend on watching fortunes instead of doing
86 -- more creative things... :-)
88 -- Happy fortunes for you!
90 -- Feel free to contact me if you discover bugs or want to comment on this.
93 -- You are free to distribute this software under the terms of the GNU
94 -- General Public License Version 2.
96 if not statusd_fortune
then
101 command
="fortune -s",
110 local settings
= table.join (statusd
.get_config("fortune"), statusd_fortune
)
112 -- do things to strings...
113 -- did I mention I write Haskell normally ? :-)
114 local function flatspace(s
)
116 string.gsub( -- 1. remaining controls
117 string.gsub( -- 2. newlines not covered by newlinetrick
118 string.gsub( -- 3. spaces
119 string.gsub( -- 4. remove trailing control + space
120 string.gsub(s
, "^[%c%s]+", "") -- 5. remove leading control + space
125 , settings
.spacereplace
138 -- on error we get the message, but a bit to late...
139 local last_error
= "error pending..."
141 -- receives data from settings.command output
142 local function receive_fortune_status(partial_data
)
143 local fortunestring
= ""
147 fortunestring
= fortunestring
.. partial_data
148 partial_data
= coroutine
.yield()
151 if (not fortunestring
) or (fortunestring
== "")
153 -- we get here if e.g. the command was not found...
154 fortunestring
= "could not obtain a fortune! ("..last_error
..")"
157 -- perform newline-merging
158 if settings
.newlinetrick
160 -- trick 1 : wrapped sentences
161 fortunestring
= string.gsub(fortunestring
, "(%l)\n(%l)", "%1 %2")
162 -- trick 2 : 'cite-signs'
163 fortunestring
= string.gsub(fortunestring
, "([^\n]*)[%c%s]*(--.*)", "%1 %2")
166 -- flatspace is such a silly name...
167 local f
= flatspace(fortunestring
)
169 -- calculate time to wait
173 settings
.minwait
-- minimun
174 ,1000 * (string.len(f
) / settings
.cpers
) -- maybe more
178 statusd
.inform("fortune", settings
.prefix
..f
..settings
.postfix
)
181 fortune_timer
:set(waittime
, update_fortune
)
184 local function flush_stderr(partial_data
)
189 r
= r
.. partial_data
190 partial_data
= coroutine
.yield()
192 -- update last error to give the user a hint...
197 function update_fortune()
198 statusd
.popen_bgread(
200 , coroutine
.wrap(receive_fortune_status
)
201 , coroutine
.wrap(flush_stderr
)
205 -- initialize our timer
206 fortune_timer
= statusd
.create_timer()