from asynchshell to awful.spawn.easy_async; started making every widget asynchronous

This commit is contained in:
copycat-killer 2017-01-20 20:58:22 +01:00
parent 7e4175f7aa
commit 0279482eeb
13 changed files with 181 additions and 333 deletions

View File

@ -1,79 +0,0 @@
--[[
Licensed under GNU General Public License v2
* (c) 2015, worron
* (c) 2013, Alexander Yakushev
--]]
-- Asynchronous io.popen for Awesome WM.
-- How to use:
-- asyncshell.request('wscript -Kiev', function(output) wwidget.text = output end)
-- Grab environment
local awful = require('awful')
-- Avoid discrepancies across multiple shells
awful.util.shell = '/bin/sh'
-- Initialize tables for module
asyncshell = { request_table = {}, id_counter = 0 }
-- Request counter
local function next_id()
asyncshell.id_counter = (asyncshell.id_counter + 1) % 10000
return asyncshell.id_counter
end
-- Remove given request
function asyncshell.clear(id)
if asyncshell.request_table[id] then
if asyncshell.request_table[id].timer then
asyncshell.request_table[id].timer:stop()
asyncshell.request_table[id].timer = nil
end
asyncshell.request_table[id] = nil
end
end
-- Sends an asynchronous request for an output of the shell command
-- @param command Command to be executed and taken output from
-- @param callback Function to be called when the command finishes
-- @param timeout Maximum amount of time to wait for the result (optional)
function asyncshell.request(command, callback, timeout)
local id = next_id()
asyncshell.request_table[id] = { callback = callback }
local formatted_command = string.gsub(command, '"','\"')
local req = string.format(
"echo \"asyncshell.deliver(%s, [[\\\"$(%s)\\\"]])\" | awesome-client &",
id, formatted_command
)
if type(awful.spawn) == 'table' and awful.spawn.with_shell then
awful.spawn.with_shell(req)
else
awful.util.spawn_with_shell(req)
end
if timeout then
asyncshell.request_table[id].timer = timer({ timeout = timeout })
asyncshell.request_table[id].timer:connect_signal("timeout", function() asyncshell.clear(id) end)
asyncshell.request_table[id].timer:start()
end
end
-- Calls the remembered callback function on the output of the shell command
-- @param id Request ID
-- @param output Shell command output to be delievered
function asyncshell.deliver(id, output)
local output = string.sub(output, 2, -2)
if asyncshell.request_table[id] then
asyncshell.request_table[id].callback(output)
asyncshell.clear(id)
end
end
return asyncshell

View File

@ -6,17 +6,17 @@
--]]
local debug = require("debug")
local assert = assert
local capi = { timer = require("gears.timer") }
local io = { open = io.open,
lines = io.lines,
popen = io.popen }
local rawget = rawget
local table = { sort = table.sort }
local debug = require("debug")
local io = { lines = io.lines,
open = io.open,
popen = io.popen }
local rawget = rawget
local table = { sort = table.sort }
local wibox = require("wibox")
local easy_async = require("awful.spawn").easy_async
local timer = require("gears.timer")
local wibox = require("wibox")
-- Lain helper functions for internal use
-- lain.helpers
@ -95,7 +95,7 @@ helpers.timer_table = {}
function helpers.newtimer(_name, timeout, fun, nostart)
local name = timeout
if not helpers.timer_table[name] then
helpers.timer_table[name] = capi.timer({ timeout = timeout })
helpers.timer_table[name] = timer({ timeout = timeout })
helpers.timer_table[name]:start()
end
helpers.timer_table[name]:connect_signal("timeout", fun)
@ -108,22 +108,25 @@ end
-- {{{ Pipe operations
-- read the full output of a command output
-- return the full output of an input command (synchronous pipe)
-- @param cmd the input command
-- @return command output (string)
function helpers.read_pipe(cmd)
local f = assert(io.popen(cmd))
local f = io.popen(cmd)
local output = f:read("*all")
f:close()
return output
end
-- return line iterator of a command output
function helpers.pipelines(...)
local f = assert(io.popen(...))
return function () -- iterator
local data = f:read()
if data == nil then f:close() end
return data
end
-- run a command and execute a function on its output (asynchronous pipe)
-- @param cmd the input command
-- @param callback function to execute on cmd output
-- @return cmd PID
function helpers.async(cmd, callback)
return easy_async(cmd,
function (stdout, stderr, reason, exit_code)
callback(stdout)
end)
end
-- }}}

View File

@ -6,10 +6,8 @@
--]]
local newtimer = require("lain.helpers").newtimer
local async = require("lain.asyncshell")
local helpers = require("lain.helpers")
local wibox = require("wibox")
local setmetatable = setmetatable
-- Basic template for custom widgets (asynchronous version)
@ -22,10 +20,10 @@ local function worker(args)
local cmd = args.cmd or ""
local settings = args.settings or function() end
abase.widget = wibox.widget.textbox('')
abase.widget = wibox.widget.textbox()
function abase.update()
async.request(cmd, function(f)
helpers.async(cmd, function(f)
output = f
if output ~= abase.prev then
widget = abase.widget
@ -35,7 +33,7 @@ local function worker(args)
end)
end
newtimer(cmd, timeout, abase.update)
helpers.newtimer(cmd, timeout, abase.update)
return setmetatable(abase, { __index = abase.widget })
end

View File

@ -8,13 +8,9 @@
--]]
local helpers = require("lain.helpers")
local read_pipe = require("lain.helpers").read_pipe
local wibox = require("wibox")
local string = { match = string.match,
format = string.format }
local setmetatable = setmetatable
-- ALSA volume
@ -26,29 +22,20 @@ local function worker(args)
local timeout = args.timeout or 5
local settings = args.settings or function() end
alsa.cmd = args.cmd or "amixer"
alsa.channel = args.channel or "Master"
alsa.togglechannel = args.togglechannel
alsa.last_level = "0"
alsa.last_status = ""
alsa.cmd = args.cmd or "amixer"
alsa.channel = args.channel or "Master"
alsa.last = {}
function alsa.update()
mixer = read_pipe(string.format("%s get %s", alsa.cmd, alsa.channel))
l, s = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
-- HDMIs can have a channel different from Master for toggling mute
if alsa.togglechannel then
s = string.match(read_pipe(string.format("%s get %s", alsa.cmd, alsa.togglechannel)), "%[(%a+)%]")
end
if alsa.last_level ~= l or alsa.last_status ~= s then
volume_now = { level = l, status = s }
alsa.last_level = l
alsa.last_status = s
widget = alsa.widget
settings()
end
helpers.async(alsa.cmd, function(mixer)
local l,s = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
if alsa.last.level ~= l or alsa.last.status ~= s then
volume_now = { level = l, status = s }
widget = alsa.widget
settings()
alsa.last = volume_now
end
end)
end
timer_id = string.format("alsa-%s-%s", alsa.cmd, alsa.channel)

View File

@ -7,8 +7,7 @@
--]]
local newtimer = require("lain.helpers").newtimer
local read_pipe = require("lain.helpers").read_pipe
local helpers = require("lain.helpers")
local awful = require("awful")
local beautiful = require("beautiful")
@ -35,9 +34,6 @@ local alsabar = {
unmute = "#A4CE8A"
},
terminal = terminal or "xterm",
mixer = string.format("%s -e alsamixer", terminal),
notifications = {
font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")),
font_size = "11",
@ -49,46 +45,6 @@ local alsabar = {
_muted = false
}
function alsabar.notify()
alsabar.update()
local preset = {
title = "",
text = "",
timeout = 5,
screen = alsabar.notifications.screen,
font = string.format("%s %s", alsabar.notifications.font,
alsabar.notifications.font_size),
fg = alsabar.notifications.color
}
if alsabar._muted
then
preset.title = string.format("%s - Muted", alsabar.channel)
else
preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level)
end
int = math.modf((alsabar._current_level / 100) * awful.screen.focused().mywibox.height)
preset.text = string.format("[%s%s]", string.rep("|", int),
string.rep(" ", awful.screen.focused().mywibox.height - int))
if alsabar.followtag then
preset.screen = awful.screen.focused()
end
if alsabar._notify ~= nil then
alsabar._notify = naughty.notify ({
replaces_id = alsabar._notify.id,
preset = preset,
})
else
alsabar._notify = naughty.notify ({
preset = preset,
})
end
end
local function worker(args)
local args = args or {}
local timeout = args.timeout or 5
@ -101,7 +57,6 @@ local function worker(args)
alsabar.cmd = args.cmd or "amixer"
alsabar.channel = args.channel or alsabar.channel
alsabar.togglechannel = args.togglechannel
alsabar.step = args.step or alsabar.step
alsabar.colors = args.colors or alsabar.colors
alsabar.notifications = args.notifications or alsabar.notifications
@ -122,66 +77,72 @@ local function worker(args)
alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
function alsabar.update()
-- Get mixer control contents
local mixer = read_pipe(string.format("%s get %s", alsabar.cmd, alsabar.channel))
-- Capture mixer control state: [5%] ... ... [on]
local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
-- HDMIs can have a channel different from Master for toggling mute
if alsabar.togglechannel then
mute = string.match(read_pipe(string.format("%s get %s", alsabar.cmd, alsabar.togglechannel)), "%[(%a+)%]")
end
if (volu and tonumber(volu) ~= alsabar._current_level) or (mute and string.match(mute, "on") ~= alsabar._muted)
then
alsabar._current_level = tonumber(volu) or alsabar._current_level
alsabar.bar:set_value(alsabar._current_level / 100)
if (not mute and tonumber(volu) == 0) or mute == "off"
function alsabar.update(callback)
helpers.async(alsabar.cmd, function(mixer)
local volu,mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
if (volu and tonumber(volu) ~= alsabar._current_level) or (mute and string.match(mute, "on") ~= alsabar._muted)
then
alsabar._muted = true
alsabar.tooltip:set_text ("[Muted]")
alsabar.bar.color = alsabar.colors.mute
else
alsabar._muted = false
alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, volu))
alsabar.bar.color = alsabar.colors.unmute
alsabar._current_level = tonumber(volu) or alsabar._current_level
alsabar.bar:set_value(alsabar._current_level / 100)
if (not mute and tonumber(volu) == 0) or mute == "off"
then
alsabar._muted = true
alsabar.tooltip:set_text ("[Muted]")
alsabar.bar.color = alsabar.colors.mute
else
alsabar._muted = false
alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, volu))
alsabar.bar.color = alsabar.colors.unmute
end
volume_now = {}
volume_now.level = tonumber(volu)
volume_now.status = mute
settings()
if callback then callback() end
end
volume_now = {}
volume_now.level = tonumber(volu)
volume_now.status = mute
settings()
end
end)
end
alsabar.bar:buttons(awful.util.table.join (
awful.button({}, 1, function()
awful.util.spawn(alsabar.mixer)
end),
awful.button({}, 2, function()
awful.util.spawn(string.format("%s set %s 100%%", alsabar.cmd, alsabar.channel))
alsabar.update()
end),
awful.button({}, 3, function()
awful.util.spawn(string.format("%s set %s toggle", alsabar.cmd, alsabar.togglechannel or alsabar.channel))
alsabar.update()
end),
awful.button({}, 4, function()
awful.util.spawn(string.format("%s set %s %s+", alsabar.cmd, alsabar.channel, alsabar.step))
alsabar.update()
end),
awful.button({}, 5, function()
awful.util.spawn(string.format("%s set %s %s-", alsabar.cmd, alsabar.channel, alsabar.step))
alsabar.update()
end)
))
function alsabar.notify()
alsabar.update(function()
local preset = {
title = "",
text = "",
timeout = 5,
screen = alsabar.notifications.screen,
font = string.format("%s %s", alsabar.notifications.font,
alsabar.notifications.font_size),
fg = alsabar.notifications.color
}
if alsabar._muted then
preset.title = string.format("%s - Muted", alsabar.channel)
else
preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level)
end
int = math.modf((alsabar._current_level / 100) * awful.screen.focused().mywibox.height)
preset.text = string.format("[%s%s]", string.rep("|", int),
string.rep(" ", awful.screen.focused().mywibox.height - int))
if alsabar.followtag then preset.screen = awful.screen.focused() end
if alsabar._notify then
alsabar._notify = naughty.notify ({
replaces_id = alsabar._notify.id,
preset = preset,
})
else
alsabar._notify = naughty.notify ({ preset = preset })
end
end)
end
timer_id = string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel)
newtimer(timer_id, timeout, alsabar.update)
helpers.newtimer(timer_id, timeout, alsabar.update)
return alsabar
end

View File

@ -44,8 +44,7 @@ local function worker(args)
function gpmdp.update()
local filelines = helpers.lines_from(file_location)
if not next(filelines)
then
if not next(filelines) then
local gpm_now = { running = false, playing = false }
else
dict, pos, err = json.decode(table.concat(filelines), 1, nil)
@ -67,16 +66,12 @@ local function worker(args)
widget = gpmdp.widget
settings()
if gpm_now.playing
then
if notify == "on" and gpm_now.title ~= helpers.get_map("gpmdp_current")
then
if gpm_now.playing then
if notify == "on" and gpm_now.title ~= helpers.get_map("gpmdp_current") then
helpers.set_map("gpmdp_current", gpm_now.title)
os.execute(string.format("curl %d -o /tmp/gpmcover.png", gpm_now.cover_url))
if followtag then
gpmdp_notification_preset.screen = focused()
end
if followtag then gpmdp_notification_preset.screen = focused() end
gpmdp.id = naughty.notify({
preset = gpmdp_notification_preset,

View File

@ -38,8 +38,10 @@ local function worker(args)
local function run_settings(layout, variant)
widget = kbdlayout.widget
kbdlayout_now = { layout=string.match(layout, "[^,]+"), -- Make sure to match the primary layout only.
variant=variant }
kbdlayout_now = {
layout=string.match(layout, "[^,]+"), -- Make sure to match the primary layout only.
variant=variant
}
settings()
end

View File

@ -6,52 +6,40 @@
--]]
local helpers = require("lain.helpers")
local async = require("lain.asyncshell")
local helpers = require("lain.helpers")
local focused = require("awful.screen").focused
local escape_f = require("awful.util").escape
local naughty = require("naughty")
local wibox = require("wibox")
local shell = require("awful.util").shell
local focused = require("awful.screen").focused
local escape_f = require("awful.util").escape
local naughty = require("naughty")
local wibox = require("wibox")
local io = { popen = io.popen }
local os = { execute = os.execute,
getenv = os.getenv }
local string = { format = string.format,
gmatch = string.gmatch }
local os = { getenv = os.getenv }
local string = { format = string.format,
gmatch = string.gmatch }
local setmetatable = setmetatable
-- MOC audio player
-- lain.widgets.contrib.moc
local moc = {}
local moc = helpers.make_widget_textbox()
local function worker(args)
local args = args or {}
local timeout = args.timeout or 2
local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
local cover_size = args.cover_size or 100
local default_art = args.default_art or ""
local followtag = args.followtag or false
local settings = args.settings or function() end
local args = args or {}
local timeout = args.timeout or 2
local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
local cover_pattern = args.cover_pattern or "*\\.(jpg|jpeg|png|gif)$"
local cover_size = args.cover_size or 100
local default_art = args.default_art or ""
local followtag = args.followtag or false
local settings = args.settings or function() end
local mpdcover = helpers.scripts_dir .. "mpdcover"
moc.widget = wibox.widget.textbox('')
moc_notification_preset = {
title = "Now playing",
timeout = 6
}
moc_notification_preset = { title = "Now playing", timeout = 6 }
helpers.set_map("current moc track", nil)
function moc.update()
-- mocp -i will produce output like:
-- Artist: Travis
-- Album: The Man Who
-- etc.
async.request("mocp -i", function(f)
helpers.async("mocp -i", function(f)
moc_now = {
state = "N/A",
file = "N/A",
@ -64,13 +52,13 @@ local function worker(args)
for line in string.gmatch(f, "[^\n]+") do
for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
if k == "State" then moc_now.state = v
elseif k == "File" then moc_now.file = v
elseif k == "Artist" then moc_now.artist = escape_f(v)
elseif k == "SongTitle" then moc_now.title = escape_f(v)
elseif k == "Album" then moc_now.album = escape_f(v)
if k == "State" then moc_now.state = v
elseif k == "File" then moc_now.file = v
elseif k == "Artist" then moc_now.artist = escape_f(v)
elseif k == "SongTitle" then moc_now.title = escape_f(v)
elseif k == "Album" then moc_now.album = escape_f(v)
elseif k == "CurrentTime" then moc_now.elapsed = escape_f(v)
elseif k == "TotalTime" then moc_now.total = escape_f(v)
elseif k == "TotalTime" then moc_now.total = escape_f(v)
end
end
end
@ -83,18 +71,22 @@ local function worker(args)
if moc_now.state == "PLAY" then
if moc_now.title ~= helpers.get_map("current moc track") then
helpers.set_map("current moc track", moc_now.title)
os.execute(string.format("%s %q %q %d %q", mpdcover, "",
moc_now.file, cover_size, default_art))
if followtag then
moc_notification_preset.screen = focused()
end
if followtag then moc_notification_preset.screen = focused() end
moc.id = naughty.notify({
preset = moc_notification_preset,
icon = "/tmp/mpdcover.png",
local common = {
preset = moc_notification_preset,
icon = default_art,
icon_size = cover_size,
replaces_id = moc.id,
}).id
}
local path = string.format("%s/%s", music_dir, string.match(moc_now.file, ".*/"))
local cover = string.format("%s -c \"find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'\"", shell, path, cover_pattern)
helpers.async(cover, function(current_icon)
common.icon = current_icon:gsub("\n", "")
moc.id = naughty.notify(common).id
end)
end
elseif moc_now.state ~= "PAUSE" then
helpers.set_map("current moc track", nil)

View File

@ -12,7 +12,6 @@ local awful = require("awful")
local beautiful = require("beautiful")
local naughty = require("naughty")
local mouse = mouse
local io = io
local string = { len = string.len }
local tonumber = tonumber

View File

@ -7,7 +7,6 @@
--]]
local helpers = require("lain.helpers")
local async = require("lain.asyncshell")
local naughty = require("naughty")
local wibox = require("wibox")
@ -59,24 +58,19 @@ local function worker(args)
curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:%q %s -k",
head_command, server, port, mail, password, request)
async.request(curl, function(f)
helpers.async(curl, function(f)
_, mailcount = string.gsub(f, "%d+", "")
_ = nil
widget = imap.widget
settings()
if mailcount >= 1 and mailcount > helpers.get_map(mail)
then
if mailcount >= 1 and mailcount > helpers.get_map(mail) then
if mailcount == 1 then
nt = mail .. " has one new message"
else
nt = mail .. " has <b>" .. mailcount .. "</b> new messages"
end
naughty.notify({
preset = mail_notification_preset,
text = nt
})
naughty.notify({ preset = mail_notification_preset, text = nt })
end
helpers.set_map(mail, mailcount)

View File

@ -7,9 +7,9 @@
--]]
local async = require("lain.asyncshell")
local helpers = require("lain.helpers")
local shell = require("awful.util").shell
local escape_f = require("awful.util").escape
local focused = require("awful.screen").focused
local naughty = require("naughty")
@ -29,7 +29,7 @@ local mpd = helpers.make_widget_textbox()
local function worker(args)
local args = args or {}
local timeout = args.timeout or 2
local password = args.password or ""
local password = (args.password and #args.password > 0 and string.format("password %s\\n", args.password)) or ""
local host = args.host or "127.0.0.1"
local port = args.port or "6600"
local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
@ -38,21 +38,18 @@ local function worker(args)
local default_art = args.default_art or ""
local notify = args.notify or "on"
local followtag = args.followtag or false
local echo_cmd = args.echo_cmd or "echo"
local settings = args.settings or function() end
local mpdh = string.format("telnet://%s:%s", host, port)
local echo = string.format("%s 'password %s\nstatus\ncurrentsong\nclose'", echo_cmd, password)
local echo = string.format("printf \"%sstatus\\ncurrentsong\\nclose\\n\"", password)
local cmd = string.format("%s -c '%s | curl --connect-timeout 1 -fsm 3 %s'", shell, echo, mpdh)
mpd_notification_preset = {
title = "Now playing",
timeout = 6
}
mpd_notification_preset = { title = "Now playing", timeout = 6 }
helpers.set_map("current mpd track", nil)
function mpd.update()
async.request(string.format("%s | curl --connect-timeout 1 -fsm 3 %s", echo, mpdh), function (f)
helpers.async(cmd, function(f)
mpd_now = {
random_mode = false,
single_mode = false,
@ -105,22 +102,26 @@ local function worker(args)
if notify == "on" and mpd_now.title ~= helpers.get_map("current mpd track") then
helpers.set_map("current mpd track", mpd_now.title)
local current icon = default_art
if followtag then mpd_notification_preset.screen = focused() end
local common = {
preset = mpd_notification_preset,
icon = default_art,
icon_size = cover_size,
replaces_id = mpd.id,
}
if not string.match(mpd_now.file, "http.*://") then -- local file instead of http stream
local path = string.format("%s/%s", music_dir, string.match(mpd_now.file, ".*/"))
local cover = string.format("find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'", path, cover_pattern)
current_icon = helpers.read_pipe(cover):gsub("\n", "")
local cover = string.format("%s -c \"find '%s' -maxdepth 1 -type f | egrep -i -m1 '%s'\"", shell, path, cover_pattern)
helpers.async(cover, function(current_icon)
common.icon = current_icon:gsub("\n", "")
mpd.id = naughty.notify(common).id
end)
else
mpd.id = naughty.notify(common).id
end
if followtag then mpd_notification_preset.screen = focused() end
mpd.id = naughty.notify({
preset = mpd_notification_preset,
icon = current_icon,
icon_size = cover_size,
replaces_id = mpd.id,
}).id
end
elseif mpd_now.state ~= "pause" then
helpers.set_map("current mpd track", nil)

View File

@ -6,12 +6,10 @@
--]]
local async = require("lain.helpers").async
local newtimer = require("lain.helpers").newtimer
local read_pipe = require("lain.helpers").read_pipe
local async = require("lain.asyncshell")
local json = require("lain.util").dkjson
local lain_icons = require("lain.helpers").icons_dir
local json = require("lain.util").dkjson
local focused = require("awful.screen").focused
local naughty = require("naughty")
@ -54,14 +52,14 @@ local function worker(args)
local notification_preset = args.notification_preset or {}
local notification_text_fun = args.notification_text_fun or
function (wn)
local day = string.gsub(read_pipe(string.format(date_cmd, wn["dt"])), "\n", "")
local day = os.date("%a %d", wn["dt"])
local tmin = math.floor(wn["temp"]["min"])
local tmax = math.floor(wn["temp"]["max"])
local desc = wn["weather"][1]["description"]
return string.format("<b>%s</b>: %s, %d - %d ", day, desc, tmin, tmax)
end
local weather_na_markup = args.weather_na_markup or " N/A "
local followtag = args.followtag or false
local followtag = args.followtag or false
local settings = args.settings or function() end
weather.widget = wibox.widget.textbox(weather_na_markup)
@ -105,7 +103,7 @@ local function worker(args)
function weather.forecast_update()
local cmd = string.format(forecast_call, city_id, units, lang, cnt, APPID)
async.request(cmd, function(f)
async(cmd, function(f)
local pos, err
weather_now, pos, err = json.decode(f, 1, nil)
@ -125,7 +123,7 @@ local function worker(args)
function weather.update()
local cmd = string.format(current_call, city_id, units, lang, APPID)
async.request(cmd, function(f)
async(cmd, function(f)
local pos, err, icon
weather_now, pos, err = json.decode(f, 1, nil)
@ -135,12 +133,9 @@ local function worker(args)
local sunrise = tonumber(weather_now["sys"]["sunrise"])
local sunset = tonumber(weather_now["sys"]["sunset"])
local icon = weather_now["weather"][1]["icon"]
local utc_m = string.gsub(read_pipe(string.format("date -u -d 'today 00:00:00' +'%%s'")), "\n", "")
local loc_m = string.gsub(read_pipe(string.format("date -d 'today 00:00:00' +'%%s'")), "\n", "")
loc_m = tonumber(loc_m)
utc_m = tonumber(utc_m)
offset = utc_offset()
local loc_m = os.time { year = os.date("%Y"), month = os.date("%m"), day = os.date("%d"), hour = 0 }
local offset = utc_offset()
local utc_m = loc_m + offset
-- if we are 1 day after the GMT, return 1 day back, and viceversa
if offset > 0 and loc_m >= utc_m then

2
wiki

@ -1 +1 @@
Subproject commit cf17caf2b889d58d4f00a47cd168f53ae85b6d9f
Subproject commit fd369119050a6674c7bb4ef3b2b1d6c6dbdecb83