Include notionflux in the main repo instead of its own submodule
[notion/jeffpc.git] / contrib / statusd / statusd_fortune.lua
blob31e8f0d0674c009ff559b5fdc183c9847b43797e
1 -- Authors: Hendrik Iben <hiben@tzi.de>
2 -- License: GPL, version 2
3 -- Last Changed: 2006-03-23
4 --
5 -- statusd_fortune.lua v20060323
6 --
7 -- Displays a fortune (in a sane way for one line).
8 -- My first attempt at writing in lua and for ion.
9 --
10 -- Written by Hendrik Iben < hiben at tzi dot de >
12 -- How to use :
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.
24 -- Requirements:
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 :-)
29 -- Options :
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
38 -- (' - ')
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...
52 --
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)
61 -- ...
62 -- ...
63 -- rotate_statusbar.configurations = {
64 -- ...
65 -- ...
66 -- fortune = {
67 -- prefix = "Fortune : ",
68 -- interval = 30*1000,
69 -- },
70 -- ...
71 -- ...
72 --
73 -- rotate_statusbar.settings = {
74 -- ...
75 -- ...
76 -- all_statusbars = {
77 -- "[ %date || %xmmsip_user ]%filler%systray",
78 -- "[ %fortune ]%filler%systray",
79 -- ...
80 -- ...
81 --
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.
91 -- -- Hendrik
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
97 statusd_fortune={
98 interval=60*1000,
99 minwait=6*1000,
100 cpers=20,
101 command="fortune -s",
102 prefix="",
103 postfix="",
104 spacereplace=" - ",
105 newline=" > ",
106 newlinetrick=true,
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)
115 return
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
121 , "[%c%s]+$"
122 , ""
123 ) -- > 4.
124 , "%s%s%s%s+"
125 , settings.spacereplace
126 ) -- > 3.
127 , "\n+"
128 , settings.newline
129 ) -- > 2.
130 , "%c"
131 , ""
132 ) -- > 1.
135 -- our timer
136 local fortune_timer
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 = ""
145 while partial_data
147 fortunestring = fortunestring .. partial_data
148 partial_data = coroutine.yield()
151 if (not fortunestring) or (fortunestring == "")
152 then
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
159 then
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
170 local waittime =
171 settings.interval
172 + math.max(
173 settings.minwait -- minimun
174 ,1000 * (string.len(f) / settings.cpers) -- maybe more
177 -- feed the monitor
178 statusd.inform("fortune", settings.prefix..f..settings.postfix)
180 -- update callback
181 fortune_timer:set(waittime, update_fortune)
184 local function flush_stderr(partial_data)
185 local r = ""
187 while partial_data
189 r = r .. partial_data
190 partial_data = coroutine.yield()
192 -- update last error to give the user a hint...
193 last_error = r
196 --- monitor-update
197 function update_fortune()
198 statusd.popen_bgread(
199 settings.command
200 , coroutine.wrap(receive_fortune_status)
201 , coroutine.wrap(flush_stderr)
205 -- initialize our timer
206 fortune_timer = statusd.create_timer()
207 -- begin
208 update_fortune()