File: statusd_fortune.lua

package info (click to toggle)
notion 4.0.2%2Bdfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 4,676 kB
  • sloc: ansic: 47,508; sh: 2,096; makefile: 603; perl: 270
file content (208 lines) | stat: -rw-r--r-- 6,403 bytes parent folder | download | duplicates (4)
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
-- Authors: Hendrik Iben <hiben@tzi.de>
-- License: GPL, version 2
-- Last Changed: 2006-03-23
--
-- statusd_fortune.lua v20060323
--
-- Displays a fortune (in a sane way for one line).
-- My first attempt at writing in lua and for ion.
--
-- Written by Hendrik Iben < hiben at tzi dot de >
--
-- How to use :
-- fortune provides a monitor for statusd.
-- This monitor is feed with a fortune obtained from the famous fortune-
-- program. But as fortunes can span several lines and the ion-statusbar
-- only provides one line there is some conversion done.
--
-- As a user you can influence the way this conversion is done by specifying
-- with what string empty space and newlines are to be replaced. Or just
-- leave the defaults.
--
-- For a start you can simple add '%fortune' to your statusbar-template.
--
-- Requirements:
-- ion3 (tested with 20060305 gentoo ebuild)
-- lua (tested with 5.0.2)
-- fortune (any version will do) or anything that returns text :-)
--
-- Options :
-- The settings you can specify (and their defaults) are :
-- interval     : minimum time between fortune updates (60 seconds)
-- minwait      : additional time to always wait for a fortune (6 seconds)
-- cpers        : number of characters to increase waiting by one second (20)
-- command      : command to obtain a fortune (fortune -s)
-- prefix       : head of every fortune
-- postfix      : tail of every fortune
-- spacereplace : string that replaces empty space of more than 3 characters
--                (' - ')
-- newline      : string that replaces newlines (' > ')
-- newlinetrick : try to be smart when killing newlines (true)
--
-- Setting 'interval' and 'minwait' together might seem useless but when
-- calculating  the waiting time the maximum of 'minwait' and the time
-- resulting from 'cpers' is added to 'interval'. The defaults for 'minwait'
-- and 'cpers' are taken from fortunes source.
--
-- The default command triggers a short fortune (see: man fortune) as long
-- fortunes tend to fill more than one line in the status-bar. You may wish
-- to enable offending fortunes but I personally don't like them that much...
-- In my opinion the statusbar should offer things like scrolling text but
-- eventually I will implement this in a later release of this monitor...
--
-- Enabling 'newlinetrick' basicly makes this program look at the ending and
-- beginning of the two lines and check if they are *meant* to be separated.
-- Currently this merges lines that end and begin with lower-case-letters and
-- silently removes newlines in front of 'cite-signs' (e.g.
-- "...blah\n-- Hendrik" becomes "...blah -- Hendrik").
--
-- Example configuration :
-- cfg_statusbar (rotate_statusbar that is)
--   ...
--   ...
--   rotate_statusbar.configurations = {
--     ...
--     ...
--      fortune = {
--        prefix = "Fortune : ",
--        interval = 30*1000,
--     },
--     ...
--     ...
--
--   rotate_statusbar.settings = {
--    ...
--    ...
--    all_statusbars = {
--      "[ %date || %xmmsip_user ]%filler%systray",
--      "[ %fortune ]%filler%systray",
--      ...
--      ...
--
-- This setup makes the basic fortune update all 30 seconds and prepends
-- every fortune with 'Fortune : '. Also using rotate_statusbar I decided
-- to give fortunes the full bar turning of the date-monitor so I don't
-- perceive how much time I spend on watching fortunes instead of doing
-- more creative things... :-)
--
-- Happy fortunes for you!
--
-- Feel free to contact me if you discover bugs or want to comment on this.
--  -- Hendrik
--
-- You are free to distribute this software under the terms of the GNU
-- General Public License Version 2.

if not statusd_fortune then
  statusd_fortune={
    interval=60*1000,
    minwait=6*1000,
    cpers=20,
    command="fortune -s",
    prefix="",
    postfix="",
    spacereplace=" - ",
    newline=" > ",
    newlinetrick=true,
  }
end

local settings = table.join (statusd.get_config("fortune"), statusd_fortune)

-- do things to strings...
-- did I mention I write Haskell normally ? :-)
local function flatspace(s)
  return
    string.gsub( -- 1. remaining controls
      string.gsub( -- 2. newlines not covered by newlinetrick
        string.gsub( -- 3. spaces
          string.gsub( -- 4. remove trailing control + space
            string.gsub(s, "^[%c%s]+", "") -- 5. remove leading control + space
            , "[%c%s]+$"
            , ""
          ) -- > 4.
          , "%s%s%s%s+"
          , settings.spacereplace
        ) -- > 3.
        , "\n+"
        , settings.newline
      ) -- > 2.
      , "%c"
      , ""
    ) -- > 1.
end

-- our timer
local fortune_timer

-- on error we get the message, but a bit to late...
local last_error = "error pending..."

-- receives data from settings.command output
local function receive_fortune_status(partial_data)
  local fortunestring = ""

  while partial_data
    do
      fortunestring = fortunestring .. partial_data
      partial_data = coroutine.yield()
    end

  if (not fortunestring) or (fortunestring == "")
    then
      -- we get here if e.g. the command was not found...
      fortunestring = "could not obtain a fortune! ("..last_error..")"
  end

  -- perform newline-merging
  if settings.newlinetrick
    then
      -- trick 1 : wrapped sentences
      fortunestring = string.gsub(fortunestring, "(%l)\n(%l)", "%1 %2")
      -- trick 2 : 'cite-signs'
      fortunestring = string.gsub(fortunestring, "([^\n]*)[%c%s]*(--.*)", "%1 %2")
  end

  -- flatspace is such a silly name...
  local f = flatspace(fortunestring)

  -- calculate time to wait
  local waittime =
    settings.interval
    + math.max(
       settings.minwait -- minimun
      ,1000 * (string.len(f) / settings.cpers) -- maybe more
    )

  -- feed the monitor
  statusd.inform("fortune", settings.prefix..f..settings.postfix)

  -- update callback
  fortune_timer:set(waittime, update_fortune)
end

local function flush_stderr(partial_data)
  local r = ""

  while partial_data
    do
      r = r .. partial_data
      partial_data = coroutine.yield()
    end
  -- update last error to give the user a hint...
  last_error = r
end

--- monitor-update
function update_fortune()
  statusd.popen_bgread(
      settings.command
    , coroutine.wrap(receive_fortune_status)
    , coroutine.wrap(flush_stderr)
    )
end

-- initialize our timer
fortune_timer = statusd.create_timer()
-- begin
update_fortune()