]> git.madduck.net Git - etc/awesome.git/blob - widgets/yawn/init.lua

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

widget module loads optimization
[etc/awesome.git] / widgets / yawn / init.lua
1
2 --[[
3                                                   
4      Licensed under GNU General Public License v2 
5       * (c) 2013, Luke Bonham                     
6                                                   
7 --]]
8
9 local newtimer     = require("lain.helpers").newtimer
10 local async        = require("lain.asyncshell")
11
12 local naughty      = require("naughty")
13 local wibox        = require("wibox")
14
15 local debug        = { getinfo = debug.getinfo }
16 local io           = { lines   = io.lines,
17                        open    = io.open }
18 local os           = { date    = os.date,
19                        getenv  = os.getenv }
20 local string       = { find    = string.find,
21                        match   = string.match,
22                        gsub    = string.gsub,
23                        sub     = string.sub }
24 local tonumber     = tonumber
25
26 local setmetatable = setmetatable
27
28 -- YAhoo! Weather Notification
29 -- lain.widgets.yawn
30 local yawn =
31 {
32     icon   = wibox.widget.imagebox(),
33     widget = wibox.widget.textbox('')
34 }
35
36 local project_path        = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]]
37 local localizations_path  = project_path .. 'localizations/'
38 local icon_path           = project_path .. 'icons/'
39 local api_url             = 'http://weather.yahooapis.com/forecastrss'
40 local units_set           = '?u=c&w=' -- Default is Celsius
41 local language            = string.match(os.getenv("LANG"), "(%S*$*)[.]") or "en_US" -- if LANG is not set
42 local weather_data        = nil
43 local notification        = nil
44 local city_id             = nil
45 local sky                 = nil
46 local settings            = function() end
47
48 yawn_notification_preset = {}
49
50 local function fetch_weather()
51     local url = api_url .. units_set .. city_id
52     local cmd = "curl --connect-timeout 1 -fsm 3 '" .. url .. "'"
53
54     async.request(cmd, function(f)
55         local text = f:read("*a")
56         f:close()
57
58         -- In case of no connection or invalid city ID
59         -- widgets won't display
60         if text == "" or text:match("City not found")
61         then
62             yawn.icon:set_image(icon_path .. "na.png")
63             if text == "" then
64                 weather_data = "Service not available at the moment."
65                 yawn.widget:set_text(" N/A ")
66             else
67                 weather_data = "City not found!\n" ..
68                                "Are you sure " .. city_id ..
69                                " is your Yahoo city ID?"
70                 yawn.widget:set_text(" ? ")
71             end
72             return
73         end
74
75         -- Processing raw data
76         weather_data = text:gsub("<.->", "")
77         weather_data = weather_data:match("Current Conditions:.-Full") or ""
78
79         -- may still happens in case of bad connectivity
80         if weather_data == "" then
81             yawn.icon:set_image(icon_path .. "na.png")
82             yawn.widget:set_text(" ? ")
83             return
84         end
85
86         weather_data = weather_data:gsub("Current Conditions:.-\n", "Now: ")
87         weather_data = weather_data:gsub("Forecast:.-\n", "")
88         weather_data = weather_data:gsub("\nFull", "")
89         weather_data = weather_data:gsub("[\n]$", "")
90         weather_data = weather_data:gsub(" [-] " , ": ")
91         weather_data = weather_data:gsub("[.]", ",")
92         weather_data = weather_data:gsub("High: ", "")
93         weather_data = weather_data:gsub(" Low: ", " - ")
94
95         -- Getting info for text widget
96         local now      = weather_data:sub(weather_data:find("Now:")+5,
97                          weather_data:find("\n")-1)
98         forecast       = now:sub(1, now:find(",")-1)
99         units          = now:sub(now:find(",")+2, -2)
100
101         -- Day/Night icon change
102         local hour = tonumber(os.date("%H"))
103         sky = icon_path
104
105         if forecast == "Clear"         or
106            forecast == "Fair"          or
107            forecast == "Partly Cloudy" or
108            forecast == "Mostly Cloudy"
109            then
110                if hour >= 6 and hour <= 18
111                then
112                    sky = sky .. "Day"
113                else
114                    sky = sky .. "Night"
115                end
116         end
117
118         sky = sky  .. forecast:gsub(" ", ""):gsub("/", "") .. ".png"
119
120         -- In case there's no defined icon for current forecast
121         if io.open(sky) == nil then
122             sky = icon_path .. "na.png"
123         end
124
125         -- Localization
126         local f = io.open(localizations_path .. language, "r")
127         if language:find("en_") == nil and f ~= nil
128         then
129             f:close()
130             for line in io.lines(localizations_path .. language)
131             do
132                 word = string.sub(line, 1, line:find("|")-1)
133                 translation = string.sub(line, line:find("|")+1)
134                 weather_data = string.gsub(weather_data, word, translation)
135             end
136         end
137
138         -- Finally setting infos
139         yawn.icon:set_image(sky)
140         widget = yawn.widget
141
142         _data = weather_data:match(": %S.-,") or weather_data
143         forecast = _data:gsub(": ", ""):gsub(",", "")
144         units = units:gsub(" ", "")
145
146         settings()
147     end)
148 end
149
150 function yawn.hide()
151     if notification ~= nil then
152         naughty.destroy(notification)
153         notification = nil
154     end
155 end
156
157 function yawn.show(t_out)
158     if yawn.widget._layout.text:match("?")
159     then
160         fetch_weather(settings)
161     end
162
163     yawn.hide()
164
165     notification = naughty.notify({
166         preset = yawn_notification_preset,
167         text = weather_data,
168         icon = sky,
169         timeout = t_out,
170         screen = client.focus and client.focus.screen or 1
171     })
172 end
173
174 function yawn.register(id, args)
175     local args     = args or {}
176     local timeout  = args.timeout or 600
177     settings       = args.settings or function() end
178
179     if args.u == "f" then units_set = '?u=f&w=' end
180
181     city_id = id
182
183     newtimer("yawn", timeout, fetch_weather)
184
185     yawn.icon:connect_signal("mouse::enter", function()
186         yawn.show(0)
187     end)
188     yawn.icon:connect_signal("mouse::leave", function()
189         yawn.hide()
190     end)
191
192     return yawn
193 end
194
195 function yawn.attach(widget, id, args)
196     yawn.register(id, args)
197
198     widget:connect_signal("mouse::enter", function()
199         yawn.show(0)
200     end)
201
202     widget:connect_signal("mouse::leave", function()
203         yawn.hide()
204     end)
205 end
206
207 return setmetatable(yawn, { __call = function(_, ...) return yawn.register(...) end })