totally reworked widgets

This commit is contained in:
luke bonham 2013-09-10 23:02:11 +02:00 committed by copycat-killer
parent a2379fd555
commit 8d37b9a1e4
17 changed files with 415 additions and 739 deletions

View File

@ -10,7 +10,7 @@ Layouts, widgets and utilities for Awesome WM
:License: GNU-GPLv2_
:Source: https://github.com/copycat-killer/lain
Based on a port of awesome-vain_, this costantly evolving module provides new layouts, a set of widgets and utility functions in order to improve Awesome usability and
Successor of awesome-vain_, this costantly evolving module provides new layouts, a set of widgets and utility functions in order to improve Awesome usability and
configurability.
Read the wiki_ for all the info.

View File

@ -4,14 +4,12 @@
Licensed under GNU General Public License v2
* (c) 2013, Luke Bonham
* (c) 2010-2012, Peter Hofmann
* (c) 2010, Adrian C. <anrxc@sysphere.org>
--]]
local awful = require("awful")
local debug = require("debug")
local pairs = pairs
local rawget = rawget
local io = { open = io.open }
-- Lain helper functions for internal use
-- lain.helpers
@ -30,33 +28,6 @@ end
-- }}}
-- {{{
-- If lain.terminal is a string, e.g. "xterm", then "xterm -e " .. cmd is
-- run. But if lain.terminal is a function, then terminal(cmd) is run.
function helpers.run_in_terminal(cmd)
if type(terminal) == "function"
then
terminal(cmd)
elseif type(terminal) == "string"
then
awful.util.spawn(terminal .. ' -e ' .. cmd)
end
end
-- }}}
-- {{{ Format units to one decimal point
function helpers.uformat(array, key, value, unit)
for u, v in pairs(unit) do
array["{"..key.."_"..u.."}"] = string.format("%.1f", value/v)
end
return array
end
-- }}}
-- {{{ Read the first line of a file or return nil.
function helpers.first_line(f)
@ -73,6 +44,21 @@ end
-- }}}
-- {{{ Timer maker
helpers.timer_table = {}
function helpers.newtimer(name, timeout, fun, nostart)
helpers.timer_table[name] = timer({ timeout = timeout })
helpers.timer_table[name]:connect_signal("timeout", fun)
helpers.timer_table[name]:start()
if not nostart then
helpers.timer_table[name]:emit_signal("timeout")
end
end
-- }}}
-- {{{ A map utility
helpers.map_table = {}

View File

@ -2,102 +2,65 @@
--[[
Licensed under GNU General Public License v2
* (c) 2013, Luke Bonham
* (c) 2010-2012, Peter Hofmann
* (c) 2010, Adrian C. <anrxc@sysphere.org>
* (c) 2013, Luke Bonham
* (c) 2010, Adrian C. <anrxc@sysphere.org>
--]]
local markup = require("lain.util.markup")
local run_in_terminal = require("lain.helpers").run_in_terminal
local newtimer = require("lain.helpers").newtimer
local awful = require("awful")
local beautiful = require("beautiful")
local wibox = require("wibox")
local io = io
local string = { format = string.format,
match = string.match }
local io = { popen = io.popen }
local string = { match = string.match }
local setmetatable = setmetatable
-- ALSA volume infos
-- nain.widgets.alsa
local alsa = {
volume = 0,
mute = false,
}
-- ALSA volume
-- lain.widgets.alsa
local alsa = {}
function worker(args)
local args = args or {}
local channel = args.channel or "Master"
local step = args.step or "1%"
local header = args.header or " Vol "
local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF"
local color = args.color or beautiful.fg_focus or "#FFFFFF"
local function worker(args)
local args = args or {}
local timeout = args.timeout or 5
local channel = args.channel or "Master"
local settings = args.settings or function() end
local myvolume = wibox.widget.textbox()
local myvolumeupdate = function()
widget = wibox.widget.textbox('')
function update()
local f = io.popen('amixer get ' .. channel)
local mixer = f:read("*all")
f:close()
local volume, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
volume = {}
if volume == nil
volume.level, volume.status = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
if volume.level == nil
then
alsa.volume = 0
else
alsa.volume = volume
volume.level = 0
volume.status = "off"
end
if mute == nil or mute == 'on'
if volume.status == ""
then
alsa.mute = true
mute = ''
else
alsa.mute = false
mute = 'M'
if volume.level == 0
then
volume.status = "off"
else
volume.status = "on"
end
end
local ret = markup(color, string.format("%d%s", volume, mute))
myvolume:set_markup(markup(header_color, header) .. ret .. " ")
settings()
end
local myvolumetimer = timer({ timeout = 5 })
myvolumetimer:connect_signal("timeout", myvolumeupdate)
myvolumetimer:start()
myvolumetimer:emit_signal("timeout")
newtimer("alsa", timeout, update)
myvolume:buttons(awful.util.table.join(
awful.button({}, 1,
function()
run_in_terminal('alsamixer')
end),
awful.button({}, 3,
function()
awful.util.spawn('amixer sset ' .. channel ' toggle')
end),
output = { widget = widget, notify = update }
awful.button({}, 4,
function()
awful.util.spawn('amixer sset ' .. channel .. ' ' .. step '+')
myvolumeupdate()
end),
awful.button({}, 5,
function()
awful.util.spawn('amixer sset ' .. channel .. ' ' .. step '-')
myvolumeupdate()
end)
))
alsa.widget = myvolume
alsa.channel = channel
alsa.step = step
alsa.notify = myvolumeupdate
return setmetatable(alsa, { __index = alsa.widget })
return setmetatable(output, { __index = output.widget })
end
return setmetatable(alsa, { __call = function(_, ...) return worker(...) end })

View File

@ -6,6 +6,8 @@
* (c) 2013, Rman
--]]
local newtimer = require("lain.helpers").newtimer
local awful = require("awful")
local beautiful = require("beautiful")
local naughty = require("naughty")
@ -32,12 +34,14 @@ local alsabar =
unmute = "#A4CE8A"
},
terminal = terminal or "xterm",
mixer = terminal .. " -e alsamixer",
notifications =
{
font = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")),
font_size = "11",
color = beautiful.fg_focus,
bar_size = 18 -- Awesome default
},
@ -49,9 +53,9 @@ function alsabar:notify()
local preset =
{
title = "", text = "",
timeout = 3,
timeout = 15,
font = alsabar.notifications.font .. " " .. alsabar.notifications.font_size,
fg = beautiful.fg_focus
fg = alsabar.notifications.color
}
if alsabar._muted then
@ -72,7 +76,7 @@ function alsabar:notify()
end
end
function worker(args)
local function worker(args)
local args = args or {}
local width = args.width or 63
local height = args.heigth or 1
@ -85,6 +89,7 @@ function worker(args)
alsabar.notifications = args.notifications or alsabar.notifications
alsabar.bar = awful.widget.progressbar()
alsabar.bar:set_background_color(alsabar.colors.background)
alsabar.bar:set_color(alsabar.colors.unmute)
alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
@ -97,18 +102,18 @@ function worker(args)
alsabar.bar:set_vertical(true)
end
local myvolumebarupdate = function()
function update()
-- Get mixer control contents
local f = io.popen("amixer get " .. alsabar.channel)
local mixer = f:read("*all")
f:close()
-- Capture mixer control state: [5%] ... ... [on]
local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
-- Handle mixers without data
local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
if volu == nil then
volu = 0
mute = "off"
volu = 0
mute = "off"
end
alsabar._current_level = tonumber(volu) / 100
@ -126,10 +131,7 @@ function worker(args)
end
end
local myvolumebartimer = timer({ timeout = 5 })
myvolumebartimer:connect_signal("timeout", myvolumebarupdate)
myvolumebartimer:start()
myvolumebartimer:emit_signal("timeout")
newtimer("alsabar", 5, update)
alsabar.bar:buttons (awful.util.table.join (
awful.button ({}, 1, function()
@ -151,14 +153,15 @@ function worker(args)
end)
))
return { widget = alsabar.bar,
channel = alsabar.channel,
step = alsabar.step,
notify = function()
myvolumebarupdate()
alsabar.notify()
end
}
return {
widget = alsabar.bar,
channel = alsabar.channel,
step = alsabar.step,
notify = function()
update()
alsabar.notify()
end
}
end
return setmetatable(alsabar, { __call = function(_, ...) return worker(...) end })

View File

@ -7,10 +7,9 @@
--]]
local markup = require("lain.util.markup")
local newtimer = require("lain.helpers").newtimer
local first_line = require("lain.helpers").first_line
local beautiful = require("beautiful")
local naughty = require("naughty")
local wibox = require("wibox")
@ -21,25 +20,24 @@ local setmetatable = setmetatable
-- Battery infos
-- lain.widgets.bat
local bat = {
status = "not present",
perc = "N/A",
time = "N/A",
}
local bat = { id = nil }
function worker(args)
local function worker(args)
local args = args or {}
local timeout = args.timeout or 30
local battery = args.battery or "BAT0"
local show_all = args.show_all or false
local refresh_timeout = args.refresh_timeout or 30
local header = args.header or " Bat "
local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF"
local color = args.color or beautiful.fg_focus or "#FFFFFF"
local shadow = args.shadow or false
local settings = args.settings or function() end
local mybattery = wibox.widget.textbox()
bat_now = {
status = "not present",
perc = "N/A",
time = "N/A",
watt = "N/A"
}
local mybatteryupdate = function()
widget = wibox.widget.textbox('')
function update()
local present = first_line("/sys/class/power_supply/"
.. battery
.. "/present")
@ -58,90 +56,62 @@ function worker(args)
local tot = first_line("/sys/class/power_supply/"
.. battery ..
"/energy_full")
bat.status = first_line("/sys/class/power_supply/"
bat_now.status = first_line("/sys/class/power_supply/"
.. battery ..
"/status")
local time_rat = 0
if bat.status == "Charging"
if bat_now.status == "Charging"
then
status = "(+)"
time_rat = (tot - rem) / rate
elseif bat.status == "Discharging"
elseif bat_now.status == "Discharging"
then
status = "(-)"
time_rat = rem / rate
else
status = "(.)"
end
local hrs = math.floor(time_rat)
local min = (time_rat - hrs) * 60
bat.time = string.format("%02d:%02d", hrs, min)
local amount = (rem / tot) * 100
if shadow
then
bat.perc = string.format("%d", amount)
else
bat.perc = string.format("%d%%", amount)
end
local watt = string.format("%.2fW", (rate * ratev) / 1e12)
if show_all
then
text = watt .. " " .. bat.perc .. " " .. bat.time .. " " .. bat.status
else
text = bat.perc
end
bat_now.time = string.format("%02d:%02d", hrs, min)
bat_now.perc = (rem / tot) * 100
bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12)
-- notifications for low and critical states
if amount <= 5
if bat_now.perc <= 5
then
naughty.notify{
bat.id = naughty.notify({
text = "shutdown imminent",
title = "battery nearly exhausted",
position = "top_right",
timeout = 15,
fg="#000000",
bg="#ffffff",
ontop = true
}
elseif amount <= 15
ontop = true,
replaces_id = bat.id
}).id
elseif bat.perc <= 15
then
old_id = naughty.notify{
bat.id = naughty.notify({
text = "plug the cable",
title = "battery low",
position = "top_right",
timeout = 5,
timeout = 15,
fg="#202020",
bg="#cdcdcd",
ontop = true
}
ontop = true,
replaces_id = bat.id
}).id
end
else
text = "none"
bat_now.perc = string.format("%d", bat_now.perc)
end
if shadow
then
mybattery:set_text('')
else
mybattery:set_markup(markup(header_color, header)
.. markup(color, text) .. " ")
end
settings()
end
local mybatterytimer = timer({ timeout = refresh_timeout })
mybatterytimer:connect_signal("timeout", mybatteryupdate)
mybatterytimer:start()
mybatterytimer:emit_signal("timeout")
newtimer("bat", timeout, update)
bat.widget = mybattery
return setmetatable(bat, { __index = bat.widget })
return widget
end
return setmetatable(bat, { __call = function(_, ...) return worker(...) end })

View File

@ -13,7 +13,7 @@ local beautiful = require("beautiful")
local naughty = require("naughty")
local io = io
local os = { date = os.date }
local os = { date = os.date }
local tonumber = tonumber
local setmetatable = setmetatable
@ -23,15 +23,6 @@ local setmetatable = setmetatable
local calendar = {}
local notification = nil
local function create(foreground, background)
calendar.offset = 0
calendar.icons_dir = icons_dir .. "cal/white/" -- default
calendar.notify_icon = nil
calendar.font_size = 12
calendar.bg = background or beautiful.bg_normal or "#FFFFFF"
calendar.fg = foreground or beautiful.fg_focus or "#FFFFFF"
end
function calendar:hide()
if notification ~= nil then
naughty.destroy(notification)
@ -59,7 +50,7 @@ function calendar:show(t_out, inc_offset)
end
calendar.offset = 0
calendar.notify_icon = calendar.icons_dir .. today .. ".png"
calendar.notify_icon = calendar.icons .. today .. ".png"
-- bg and fg inverted to highlight today
f = io.popen( init_t .. today ..
@ -106,13 +97,23 @@ function calendar:show(t_out, inc_offset)
notification = naughty.notify({ text = c_text,
icon = calendar.notify_icon,
position = calendar.position,
fg = calendar.fg,
bg = calendar.bg,
timeout = tims })
end
function calendar:attach(widget, foreground, background)
create(foreground, background)
function calendar:attach(widget, args)
local args = args or {}
calendar.icons = args.icons or icons_dir .. "cal/white/"
calendar.font_size = tonumber(args.font_size) or 12
calendar.fg = args.fg or beautiful.fg_normal or "#FFFFFF"
calendar.bg = args.bg or beautiful.bg_normal or "#FFFFFF"
calendar.position = args.position or "top_right"
calendar.offset = 0
calendar.notify_icon = nil
widget:connect_signal("mouse::enter", function () calendar:show() end)
widget:connect_signal("mouse::leave", function () calendar:hide() end)
widget:buttons(awful.util.table.join( awful.button({ }, 1, function ()

View File

@ -7,15 +7,15 @@
--]]
local markup = require("lain.util.markup")
local first_line = require("lain.helpers").first_line
local newtimer = require("lain.helpers").newtimer
local beautiful = require("beautiful")
local wibox = require("wibox")
local math = { ceil = math.ceil }
local string = { format = string.format,
gmatch = string.gmatch }
local tostring = tostring
local setmetatable = setmetatable
@ -26,17 +26,14 @@ local cpu = {
last_active = 0
}
function worker(args)
local args = args or {}
local refresh_timeout = args.refresh_timeout or 5
local header = args.header or " Cpu "
local header_color = args.header or beautiful.fg_normal or "#FFFFFF"
local color = args.color or beautiful.fg_focus or "#FFFFFF"
local footer = args.footer or "% "
local function worker(args)
local args = args or {}
local timeout = args.timeout or 5
local settings = args.settings or function() end
local w = wibox.widget.textbox()
widget = wibox.widget.textbox('')
local cpuusageupdate = function()
function update()
-- Read the amount of time the CPUs have spent performing
-- different kinds of work. Read the first line of /proc/stat
-- which is the sum of all CPUs.
@ -60,21 +57,19 @@ function worker(args)
-- Read current data and calculate relative values.
local dactive = active - cpu.last_active
local dtotal = total - cpu.last_total
local dta = math.ceil((dactive / dtotal) * 100)
w:set_markup(markup(header_color, header) .. markup(color, dta .. footer))
usage = tostring(math.ceil((dactive / dtotal) * 100))
settings()
-- Save current data for the next run.
cpu.last_active = active
cpu.last_total = total
end
local cpuusagetimer = timer({ timeout = refresh_timeout })
cpuusagetimer:connect_signal("timeout", cpuusageupdate)
cpuusagetimer:start()
cpuusagetimer:emit_signal("timeout")
newtimer("cpu", timeout, update)
return w
return widget
end
return setmetatable(cpu, { __call = function(_, ...) return worker(...) end })

View File

@ -8,7 +8,6 @@
--]]
local markup = require("lain.util.markup")
local helpers = require("lain.helpers")
local beautiful = require("beautiful")
@ -16,14 +15,16 @@ local wibox = require("wibox")
local naughty = require("naughty")
local io = io
local string = { match = string.match }
local pairs = pairs
local string = { match = string.match,
format = string.format }
local tonumber = tonumber
local setmetatable = setmetatable
-- File system disk space usage
-- lain.widgets.fs
local fs = {}
local fs = { notification_preset = {} }
local notification = nil
function fs:hide()
@ -41,38 +42,29 @@ function fs:show(t_out)
f:close()
notification = naughty.notify({
preset = fs.notification_preset,
text = ws,
timeout = t_out,
fg = fs.color,
timeout = t_out
})
end
-- Variable definitions
-- Units definitions
local unit = { ["mb"] = 1024, ["gb"] = 1024^2 }
local function worker(args)
local args = args or {}
local args = args or {}
local partition = args.partition or "/"
local refresh_timeout = args.refresh_timeout or 600
local header = args.header or " Hdd "
local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF"
fs.color = args.color or beautiful.fg_focus or "#FFFFFF"
local footer = args.footer or " "
local shadow = args.shadow or false
local timeout = args.timeout or 600
local settings = args.settings or function() end
local myfs = wibox.widget.textbox()
widget = wibox.widget.textbox('')
helpers.set_map("fs", false)
local fsupdate = function()
local fs_info = {} -- Get data from df
local f = io.popen("LC_ALL=C df -kP")
function update()
fs_info = {}
local function set_text()
local info = fs_info['{' .. partition .. ' used_p}']
myfs:set_markup(markup(header_color, header)
.. markup(fs.color, info .. footer))
end
local f = io.popen("LC_ALL=C df -kP")
for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount)
local s = string.match(line, "^.-[%s]([%d]+)")
@ -80,55 +72,57 @@ local function worker(args)
local m = string.match(line, "%%[%s]([%p%w]+)")
if u and m then -- Handle 1st line and broken regexp
helpers.uformat(fs_info, m .. " used", u, unit)
fs_info["{" .. m .. " used_p}"] = tonumber(p)
fs_info[m .. " size_mb"] = string.format("%.1f", tonumber(s) / unit["mb"])
fs_info[m .. " size_gb"] = string.format("%.1f", tonumber(s) / unit["gb"])
fs_info[m .. " used_p"] = tonumber(p)
fs_info[m .. " avail_p"] = 100 - tonumber(p)
end
end
f:close()
if shadow
-- chosen partition easy stuff
-- you can however check whatever partition else
used = fs_info[partition .. " used_p"]
available = fs_info[partition .. " avail_p"]
size_mb = fs_info[partition .. " size_mb"]
size_gb = fs_info[partition .. " size_gb"]
notification_preset = { fg = beautiful.fg_normal }
settings()
fs.notification_preset = notification_preset
if used >= 99 and not helpers.get_map("fs")
then
myfs:set_text('')
naughty.notify({
title = "warning",
text = partition .. " ran out!\nmake some room",
timeout = 8,
fg = "#000000",
bg = "#FFFFFF"
})
helpers.set_map("fs", true)
else
set_text()
end
local part = fs_info['{' .. partition .. ' used_p}']
if part >= 90 then
if part >= 99 and not helpers.get_map("fs") then
naughty.notify({ title = "warning",
text = partition .. " ran out!\n"
.. "make some room",
timeout = 8,
position = "top_right",
fg = beautiful.fg_urgent,
bg = beautiful.bg_urgent })
helpers.set_map("fs", true)
end
if shadow then set_text() end
helpers.set_map("fs", false)
end
end
local fstimer = timer({ timeout = refresh_timeout })
fstimer:connect_signal("timeout", fsupdate)
fstimer:start()
fstimer:emit_signal("timeout")
helpers.newtimer("fs " .. partition, timeout, update)
myfs:connect_signal('mouse::enter', function () fs:show(0) end)
myfs:connect_signal('mouse::leave', function () fs:hide() end)
widget:connect_signal('mouse::enter', function () fs:show(0) end)
widget:connect_signal('mouse::leave', function () fs:hide() end)
local fs_out =
{
widget = myfs,
output = {
widget = widget,
show = function(t_out)
fsupdate()
update()
fs:show(t_out)
end
}
return setmetatable(fs_out, { __index = fs_out.widget })
return setmetatable(output, { __index = output.widget })
end
return setmetatable(fs, { __call = function(_, ...) return worker(...) end })

View File

@ -6,160 +6,126 @@
--]]
local markup = require("lain.util.markup")
local helpers = require("lain.helpers")
local awful = require("awful")
local beautiful = require("beautiful")
local naughty = require("naughty")
local wibox = require("wibox")
local io = io
local io = { popen = io.popen }
local tonumber = tonumber
local string = string
local string = { len = string.len,
format = string.format }
local setmetatable = setmetatable
-- Mail imap check
-- Mail IMAP check
-- lain.widgets.imap
local imap = {}
local imap = { stored = nil }
function worker(args)
local args = args or {}
local args = args or {}
local server = args.server
local mail = args.mail
local server = args.server
local mail = args.mail
local password = args.password
local port = args.port or "993"
local refresh_timeout = args.refresh_timeout or 60
local header = args.header or "Mail "
local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF"
local color = args.color or beautiful.fg_focus or "#FFFFFF"
local mail_encoding = args.mail_encoding or nil
local maxlen = args.maxlen or 200
local app = args.app or "mutt"
local port = args.port or "993"
local timeout = args.timeout or 60
local encoding = args.encoding or nil
local maxlen = args.maxlen or 200
local is_plain = args.is_plain or false
local shadow = args.shadow or false
local settings = args.settings or function() end
local checkmail = helpers.scripts_dir .. "checkmail"
helpers.set_map(mail, true)
helpers.set_map(mail .. " count", "0")
local checkmail = helpers.scripts_dir .. "checkmail"
if not is_plain
then
local f = io.popen(password)
password = f:read("*all"):gsub("\n", ""):gsub("\r", "")
f:close()
if not imap.stored
then
local f = io.popen(password)
password = f:read("*all"):gsub("\n", ""):gsub("\r", "")
f:close()
imap.stored = password
else
password = imap.stored
end
end
local myimapcheck = wibox.widget.textbox()
widget = wibox.widget.textbox('')
local myimapcheckupdate = function()
function set_nomail()
if shadow
then
myimapcheck:set_text('')
else
myimapcheck:set_markup(markup(color, " no mail "))
end
end
function update()
to_execute = string.format("%s -s %s -u %s -p %s --port %s",
checkmail, server, mail, password, port)
conn = io.popen("ip link show")
check_conn = conn:read("*all")
conn:close()
if not check_conn:find("state UP") then
set_nomail()
return
end
to_execute = checkmail .. ' -s ' .. server ..
' -u ' .. mail .. ' -p ' .. password
.. ' --port ' .. port
if mail_encoding ~= nil
if encoding ~= nil
then
to_execute = to_execute .. ' --encoding '
.. mail_encoding
to_execute = string.format("%s --encoding %s",
to_execute, encoding)
end
f = io.popen(to_execute)
ws = f:read("*all")
f:close()
mailcount = "0"
if ws:find("No new messages") ~= nil
then
helpers.set_map(mail, true)
set_nomail()
elseif ws:find("CheckMailError: invalid credentials") ~= nil
then
helpers.set_map(mail, true)
myimapcheck:set_markup(" " .. markup(header_color, header) ..
markup(color, "invalid credentials "))
mailcount = "invalid credentials"
else
mailcount = ws:match("%d") or "?"
if helpers.get_map(mail .. " count") ~= mailcount and mailcount ~= "?"
mailcount = ws:match("%d") or "0"
if helpers.get_map(mail .. " count") ~= mailcount and mailcount ~= "0"
then
helpers.set_map(mail, true)
helpers.set_map(mail .. " count", mailcount)
end
end
myimapcheck:set_markup(" " .. markup(header_color, header) ..
markup(color, mailcount) .. " ")
notification_preset = {
icon = helpers.icons_dir .. "mail.png",
timeout = 8,
position = "top_left"
}
if helpers.get_map(mail)
settings()
if helpers.get_map(mail) and tonumber(mailcount) >= 1
then
notify_title = ws:match(mail .. " has %d new message.?")
ws = ws:gsub(notify_title, "", 1):gsub("\n", "", 2)
-- trying to remove useless infos
ws = ws:gsub("--Content.%S+.-\n", "")
ws = ws:gsub("--%d+.-\n", "")
if string.len(ws) > maxlen
then
if mailcount == "?"
-- May happens sometimes using keyrings or other password fetchers.
-- Since this should be automatically fixed in short times, we threat
-- this exception delaying the update to the next timeout.
then
set_nomail()
return
elseif tonumber(mailcount) >= 1
then
notify_title = ws:match(mail .. " has %d new message.?")
ws = ws:gsub(notify_title, "", 1):gsub("\n", "", 2)
ws = ws:gsub("--Content.%S+.-\n", "")
ws = ws:gsub("--%d+.-\n", "")
if string.len(ws) > maxlen
then
ws = ws:sub(1, maxlen) .. "[...]"
end
notify_title = notify_title:gsub("\n", "")
end
naughty.notify({ title = notify_title,
fg = color,
text = ws,
icon = beautiful.lain_mail_notify or
helpers.icons_dir .. "mail.png",
timeout = 8,
position = "top_left" })
helpers.set_map(mail, false)
ws = ws:sub(1, maxlen) .. "[...]"
end
notify_title = notify_title:gsub("\n", "")
naughty.notify({
preset = notification_preset,
title = notify_title,
text = ws
})
helpers.set_map(mail, false)
end
end
local myimapchecktimer = timer({ timeout = refresh_timeout })
myimapchecktimer:connect_signal("timeout", myimapcheckupdate)
myimapchecktimer:start()
myimapcheck:buttons(awful.util.table.join(
awful.button({}, 0,
helpers.newtimer(mail, timeout, update, true)
function()
helpers.run_in_terminal(app)
end)
))
return myimapcheck
return widget
end
return setmetatable(imap, { __call = function(_, ...) return worker(...) end })

View File

@ -15,10 +15,6 @@
local wrequire = require("lain.helpers").wrequire
local setmetatable = setmetatable
local widgets =
{
_NAME = "lain.widgets",
terminal = "xterm" -- X default
}
local widgets = { _NAME = "lain.widgets" }
return setmetatable(widgets, { __index = wrequire })

View File

@ -7,11 +7,8 @@
--]]
local markup = require("lain.util.markup")
local run_in_terminal = require("lain.helpers").run_in_terminal
local newtimer = require("lain.helpers").newtimer
local awful = require("awful")
local beautiful = require("beautiful")
local wibox = require("wibox")
local io = io
@ -28,25 +25,20 @@ local setmetatable = setmetatable
local maildir = {}
function worker(args)
local args = args or {}
local mailpath = args.mailpath or os.getenv("HOME") .. "/Mail"
local args = args or {}
local timeout = args.timeout or 60
local mailpath = args.mailpath or os.getenv("HOME") .. "/Mail"
local ignore_boxes = args.ignore_boxes or {}
local refresh_timeout = args.refresh_timeout or 60
local header = args.header or " Mail "
local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF"
local color_newmail = args.color_newmail or beautiful.fg_focus or "#FFFFFF"
local color_nomail = args.color_nomail or beautiful.fg_normal or "#FFFFFF"
local app = args.app or "mutt"
local shadow = args.shadow or false
local settings = args.settings or function() end
local mymailcheck = wibox.widget.textbox()
local mymailcheckupdate = function()
widget = wibox.widget.textbox('')
function update()
-- Find pathes to mailboxes.
local p = io.popen("find " .. mailpath ..
" -mindepth 1 -maxdepth 1 -type d" ..
" -not -name .git")
local boxes = {}
local line = ""
repeat
line = p:read("*l")
if line ~= nil
@ -73,7 +65,8 @@ function worker(args)
table.sort(boxes)
local newmail = ""
newmail = "no mail"
local count = 0
for box, number in pairs(boxes)
do
@ -91,39 +84,12 @@ function worker(args)
end
end
if count == 1 then
-- it will be only executed once
for box, number in pairs(boxes)
do -- it's useless to show only INBOX(x)
if box == "INBOX" then newmail = number end
end
end
if newmail == ""
then
if shadow
then
mymailcheck:set_text('')
else
myimapcheck:set_markup(markup(color_nomail, " no mail "))
end
else
myimapcheck:set_markup(" " .. markup(header_color, header) ..
markup(color_newmail, newmail) .. " ")
end
settings()
end
local mymailchecktimer = timer({ timeout = refresh_timeout })
mymailchecktimer:connect_signal("timeout", mymailcheckupdate)
mymailchecktimer:start()
mymailcheck:buttons(awful.util.table.join(
awful.button({}, 0,
function()
run_in_terminal(app)
end)
))
newtimer(mailpath, timeout, update, true)
return mymailcheck
return widget
end
return setmetatable(maildir, { __call = function(_, ...) return worker(...) end })

View File

@ -9,10 +9,8 @@
--]]
local markup = require("lain.util.markup")
local run_in_terminal = require("lain.helpers").run_in_terminal
local newtimer = require("lain.helpers").newtimer
local beautiful = require("beautiful")
local wibox = require("wibox")
local io = { lines = io.lines }
@ -28,19 +26,14 @@ local setmetatable = setmetatable
local mem = {}
function worker(args)
local args = args or {}
local refresh_timeout = args.refresh_timeout or 10
local show_swap = args.show_swap or false
local show_total = args.show_total or false
local header = args.header or " Mem "
local header_color = args.header or beautiful.fg_normal or "#FFFFFF"
local color = args.color or beautiful.fg_focus or "#FFFFFF"
local footer = args.footer or "MB "
local args = args or {}
local timeout = args.timeout or 3
local settings = args.settings or function() end
local widg = wibox.widget.textbox()
widget = wibox.widget.textbox('')
local upd = function()
local mem = {}
function update()
mem = {}
for line in io.lines("/proc/meminfo")
do
for k, v in string.gmatch(line, "([%a]+):[%s]+([%d]+).+")
@ -58,30 +51,12 @@ function worker(args)
used = mem.total - (mem.free + mem.buf + mem.cache)
swapused = mem.swap - mem.swapf
if show_total
then
local fmt = "%" .. string.len(mem.total) .. ".0f/%.0f"
widg:set_markup(markup(header_color, header) ..
markup(color, string.format(fmt, used, mem.total) .. footer))
else
widg:set_markup(markup(header_color, header) ..
markup(color, used .. footer))
end
if show_swap
then
widg:set_markup(widg._layout.text .. ' ('
.. string.format('%.0f '.. footer, swapused)
.. ')')
end
settings()
end
local tmr = timer({ timeout = refresh_timeout })
tmr:connect_signal("timeout", upd)
tmr:start()
tmr:emit_signal("timeout")
newtimer("mem", timeout, update)
return widg
return widget
end
return setmetatable(mem, { __call = function(_, ...) return worker(...) end })

View File

@ -7,10 +7,9 @@
--]]
local markup = require("lain.util.markup")
local helpers = require("lain.helpers")
local awful = require("awful")
local util = require("awful.util")
local beautiful = require("beautiful")
local naughty = require("naughty")
local wibox = require("wibox")
@ -27,111 +26,87 @@ local setmetatable = setmetatable
local mpd = { id = nil }
function worker(args)
local args = args or {}
local password = args.password or ""
local host = args.host or "127.0.0.1"
local port = args.port or "6600"
local args = args or {}
local timeout = args.timeout or 1
local password = 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"
local refresh_timeout = args.refresh_timeout or 1
local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF"
local color = args.color or beautiful.fg_focus or "#FFFFFF"
local spr = args.spr or " "
local footer = args.footer or ""
local app = args.app or "ncmpcpp"
local shadow = args.shadow or false
local settings = args.settings or function() end
local mpdcover = helpers.scripts_dir .. "mpdcover"
local mpdh = "telnet://"..host..":"..port
local echo = "echo 'password "..password.."\nstatus\ncurrentsong\nclose'"
local mpdh = "telnet://" .. host .. ":" .. port
local echo = "echo 'password " .. password .. "\nstatus\ncurrentsong\nclose'"
local mympd = wibox.widget.textbox()
widget = wibox.widget.textbox('')
helpers.set_map("current mpd track", nil)
local mympdupdate = function()
local function set_nompd()
if shadow
then
mympd:set_text('')
else
mympd:set_markup(markup(header_color, "mpd ") .. markup(color , "off") .. footer)
end
end
local mpd_state = {
["{state}"] = "N/A",
["{file}"] = "N/A",
["{Artist}"] = "N/A",
["{Title}"] = "N/A",
["{Album}"] = "N/A",
["{Date}"] = "N/A"
function update()
mpd_now = {
state = "N/A",
file = "N/A",
artist = "N/A",
title = "N/A",
album = "N/A",
date = "N/A"
}
-- Get data from MPD server
local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh)
for line in f:lines() do
for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
if k == "state" then mpd_state["{"..k.."}"] = v
elseif k == "file" then mpd_state["{"..k.."}"] = v
elseif k == "Artist" then mpd_state["{"..k.."}"] = awful.util.escape(v)
elseif k == "Title" then mpd_state["{"..k.."}"] = awful.util.escape(v)
elseif k == "Album" then mpd_state["{"..k.."}"] = awful.util.escape(v)
elseif k == "Date" then mpd_state["{"..k.."}"] = awful.util.escape(v)
if k == "state" then mpd_now.state = v
elseif k == "file" then mpd_now.file = v
elseif k == "Artist" then mpd_now.artist = util.escape(v)
elseif k == "Title" then mpd_now.title = util.escape(v)
elseif k == "Album" then mpd_now.album = util.escape(v)
elseif k == "Date" then mpd_now.date = util.escape(v)
end
end
end
f:close()
if mpd_state["{state}"] == "play"
notification_preset = {
title = "Now playing",
text = mpd_now.artist .. " (" ..
mpd_now.album .. ") - " ..
mpd_now.date .. "\n" ..
mpd_now.title,
fg = beautiful.fg_normal or "#FFFFFF",
bg = beautiful.bg_normal or "#000000",
timeout = 6
}
settings()
if mpd_now.state == "play"
then
if mpd_state["{Title}"] ~= helpers.get_map("current mpd track")
if mpd_now.title ~= helpers.get_map("current mpd track")
then
helpers.set_map("current mpd track", mpd_state["{Title}"])
helpers.set_map("current mpd track", mpd_now.title)
os.execute(mpdcover .. " '" .. music_dir .. "' '"
.. mpd_state["{file}"] .. "'")
.. mpd_now.file .. "'")
mpd.id = naughty.notify({
title = "Now playing",
text = mpd_state["{Artist}"] .. " (" ..
mpd_state["{Album}"] .. ") - " ..
mpd_state["{Date}"] .. "\n" ..
mpd_state["{Title}"],
preset = notification_preset,
icon = "/tmp/mpdcover.png",
fg = color,
timeout = 6,
replaces_id = mpd.id
}).id
end
mympd:set_markup(markup(header_color, mpd_state["{Artist}"])
.. spr ..
markup(color, mpd_state["{Title}"]) .. footer)
elseif mpd_state["{state}"] == "pause"
elseif mpd_now.state ~= "pause"
then
mympd:set_markup(markup(header_color, "mpd")
.. spr ..
markup(color, "paused") .. footer)
else
helpers.set_map("current mpd track", nil)
set_nompd()
end
end
local mympdtimer = timer({ timeout = refresh_timeout })
mympdtimer:connect_signal("timeout", mympdupdate)
mympdtimer:start()
mympdtimer:emit_signal("timeout")
helpers.newtimer("mpd", timeout, update)
mympd:buttons(awful.util.table.join(
awful.button({}, 0,
function()
helpers.run_in_terminal(app)
end)
))
output = { widget = widget, notify = update }
local mpd_out = { widget = mympd, notify = mympdupdate }
return setmetatable(mpd_out, { __index = mpd_out.widget })
return setmetatable(output, { __index = output.widget })
end
return setmetatable(mpd, { __call = function(_, ...) return worker(...) end })

View File

@ -7,33 +7,24 @@
--]]
local markup = require("lain.util.markup")
local helpers = require("lain.helpers")
local awful = require("awful")
local beautiful = require("beautiful")
local notify_fg = require("beautiful").fg_focus
local naughty = require("naughty")
local wibox = require("wibox")
local io = io
local tostring = tostring
local string = { format = string.format }
local string = { format = string.format,
gsub = string.gsub }
local setmetatable = setmetatable
-- Network infos
-- lain.widgets.net
local net = {
send = "0",
recv = "0",
last_t = {},
last_r = {}
}
net.units = {
["b"] = 1,
["kb"] = 1024,
["mb"] = 1024^2,
["gb"] = 1024^3
last_t = 0,
last_r = 0
}
function net.get_device()
@ -51,103 +42,61 @@ end
function worker(args)
local args = args or {}
local iface = args.iface or net.get_device()
local delta = args.refresh_timeout or 2
local units = args.units or net.units["kb"]
local spr = args.spr or " "
local header = args.header or iface
local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF"
local color_up = args.color_up or beautiful.fg_focus or "#FFFFFF"
local color_down = args.color_down or beautiful.fg_focus or "#FFFFFF"
local app = args.app or "sudo wifi-menu"
local units = args.units or 1024 --kb
local timeout = args.timeout or 2
local settings = args.settings or function() end
widget = wibox.widget.textbox('')
helpers.set_map(iface, true)
helpers.set_map("carrier", 0)
local mynet = wibox.widget.textbox()
function update()
if iface == "" then iface = net.get_device() end
local mynetupdate = function()
if iface == "" then
iface = net.get_device()
header = iface
end
local carrier = helpers.first_line('/sys/class/net/' .. iface ..
'/carrier') or ""
local state = helpers.first_line('/sys/class/net/' .. iface ..
'/operstate')
carrier = helpers.first_line('/sys/class/net/' .. iface ..
'/carrier') or "0"
state = helpers.first_line('/sys/class/net/' .. iface ..
'/operstate') or "down"
local now_t = helpers.first_line('/sys/class/net/' .. iface ..
'/statistics/tx_bytes')
'/statistics/tx_bytes') or 0
local now_r = helpers.first_line('/sys/class/net/' .. iface ..
'/statistics/rx_bytes')
local text = '<span color="' .. header_color .. '">' .. header .. '</span> '
'/statistics/rx_bytes') or 0
sent = tostring((now_t - net.last_t) / timeout / units)
sent = string.gsub(string.format('%.1f', sent), ",", ".")
received = tostring((now_r - net.last_r) / timeout / units)
received = string.gsub(string.format('%.1f', received), ",", ".")
settings()
net.last_t = now_t
net.last_r = now_r
if carrier ~= "1"
then
if helpers.get_map(iface)
then
n_title = iface
if n_title == "" then
n_title = "network"
header = "Net"
end
naughty.notify({ title = n_title, text = "no carrier",
timeout = 7,
position = "top_left",
icon = beautiful.lain_no_net_notify or
helpers.icons_dir .. "no_net.png",
fg = beautiful.fg_focus or "#FFFFFF" })
mynet:set_markup(markup(header_color, header) .. markup(color_up, " Off"))
if n_title == "" then n_title = "network" end
naughty.notify({
title = n_title,
text = "no carrier",
timeout = 7,
position = "top_left",
icon = helpers.icons_dir .. "no_net.png",
fg = notify_fg or "#FFFFFF"
})
helpers.set_map(iface, false)
end
return
else
helpers.set_map(iface, true)
end
if state == 'down' or not now_t or not now_r
then
mynet:set_markup(' ' .. text .. '-' .. ' ')
return
end
if net.last_t[iface] and net.last_t[iface]
then
net.send = tostring((now_t - net.last_t[iface]) / delta / units)
net.recv = tostring((now_r - net.last_r[iface]) / delta / units)
text = text
.. '<span color="' .. color_up .. '">'
.. string.format('%.1f', net.send)
.. '</span>'
.. spr
.. '<span color="' .. color_down .. '">'
.. string.format('%.1f', net.recv)
.. '</span>'
mynet:set_markup(' ' .. text .. ' ')
else
mynet:set_markup(' ' .. text .. '-' .. ' ')
end
net.last_t[iface] = now_t
net.last_r[iface] = now_r
end
local mynettimer = timer({ timeout = delta })
mynettimer:connect_signal("timeout", mynetupdate)
mynettimer:start()
mynettimer:emit_signal("timeout")
helpers.newtimer(iface, timeout, update)
mynet:buttons(awful.util.table.join(
awful.button({}, 0, function()
helpers.run_in_terminal(app)
mynetupdate()
end)))
net.widget = mynet
return setmetatable(net, { __index = net.widget })
return widget
end
return setmetatable(net, { __call = function(_, ...) return worker(...) end })

View File

@ -7,11 +7,8 @@
--]]
local markup = require("lain.util.markup")
local helpers = require("lain.helpers")
local newtimer = require("lain.helpers").newtimer
local awful = require("awful")
local beautiful = require("beautiful")
local wibox = require("wibox")
local io = io
@ -26,45 +23,24 @@ local sysload = {}
function worker(args)
local args = args or {}
local refresh_timeout = args.refresh_timeout or 5
local show_all = args.show_all or false
local header = args.header or " Load "
local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF"
local color = args.color or beautiful.fg_focus or "#FFFFFF"
local app = args.app or "top"
local timeout = args.timeout or 5
local settings = args.settings or function() end
local mysysload = wibox.widget.textbox()
widget = wibox.widget.textbox('')
local mysysloadupdate = function()
function update()
local f = io.open("/proc/loadavg")
local ret = f:read("*all")
f:close()
a, b, c = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)")
if show_all
then
local a, b, c = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)")
mysysload:set_text(string.format("%s %s %s", a, b, c))
else
local a = string.match(ret, "([^%s]+) ")
mysysload:set_text(string.format("%s", a))
end
mysysload:set_markup(markup(header_color, header) ..
markup(color, mysysload._layout.text .. " "))
settings()
end
local mysysloadtimer = timer({ timeout = refresh_timeout })
mysysloadtimer:connect_signal("timeout", mysysloadupdate)
mysysloadtimer:start()
mysysloadtimer:emit_signal("timeout")
newtimer("sysload", timeout, update)
mysysload:buttons(awful.util.table.join(
awful.button({}, 0,
function()
helpers.run_in_terminal(app)
end)
))
return mysysload
return widget
end
return setmetatable(sysload, { __call = function(_, ...) return worker(...) end })

View File

@ -6,9 +6,8 @@
--]]
local markup = require("lain.util.markup")
local newtimer = require("lain.helpers").newtimer
local beautiful = require("beautiful")
local wibox = require("wibox")
local io = io
@ -21,32 +20,22 @@ local setmetatable = setmetatable
local temp = {}
function worker(args)
local args = args or {}
local refresh_timeout = args.refresh_timeout or 5
local header = args.header or " Temp "
local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF"
local color = args.color or beautiful.fg_focus or header_color
local footer = args.footer or "C "
local args = args or {}
local timeout = args.timeout or 5
local settings = args.settings or function() end
local mytemp = wibox.widget.textbox()
widget = wibox.widget.textbox('')
local mytempupdate = function()
function update()
local f = io.open("/sys/class/thermal/thermal_zone0/temp")
local ret = f:read("*all")
coretemp_now = tonumber(f:read("*all")) / 1000
f:close()
ret = tonumber(ret) / 1000
mytemp:set_markup(markup(header_color, header) ..
markup(color, ret .. footer))
settings()
end
local mytemptimer = timer({ timeout = refresh_timeout })
mytemptimer:connect_signal("timeout", mytempupdate)
mytemptimer:start()
mytemptimer:emit_signal("timeout")
newtimer("coretemp", timeout, update)
return mytemp
return widget
end
return setmetatable(temp, { __call = function(_, ...) return worker(...) end })

View File

@ -6,9 +6,8 @@
--]]
local markup = require("lain.util.markup")
local newtimer = require("lain.helpers").newtimer
local beautiful = require("beautiful")
local naughty = require("naughty")
local wibox = require("wibox")
@ -28,10 +27,9 @@ local setmetatable = setmetatable
-- lain.widgets.yawn
local yawn =
{
units = "",
forecast = "",
icon = wibox.widget.imagebox(),
widget = wibox.widget.textbox()
icon = wibox.widget.imagebox(),
widget = wibox.widget.textbox(''),
notification_preset = {}
}
local project_path = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]]
@ -44,33 +42,32 @@ local weather_data = nil
local notification = nil
local city_id = nil
local sky = nil
local settings = {}
local update_timer = nil
local function fetch_weather(args)
local toshow = args.toshow or "forecast"
local settings = function() end
local function fetch_weather()
local url = api_url .. units_set .. city_id
local f = io.popen("curl --connect-timeout 1 -fsm 2 '"
.. url .. "'" )
local text = f:read("*all")
f:close()
-- handle no suitable icon found
yawn.icon:set_image(icon_path .. "na.png")
-- In case of no connection or invalid city ID
-- widgets won't display
if text == "" or text:match("City not found")
then
sky = icon_path .. "na.png"
yawn.icon:set_image(sky)
if text == "" then
weather_data = "Service not available at the moment."
return "N/A"
yawn.widget:set_text("N/A")
else
weather_data = "City not found!\n" ..
"Are you sure " .. city_id ..
" is your Yahoo city ID?"
return "?"
yawn.widget:set_text("?")
end
return
end
-- Processing raw data
@ -88,8 +85,8 @@ local function fetch_weather(args)
-- Getting info for text widget
local now = weather_data:sub(weather_data:find("Now:")+5,
weather_data:find("\n")-1)
local forecast = now:sub(1, now:find(",")-1)
local units = now:sub(now:find(",")+2, -2)
forecast = now:sub(1, now:find(",")-1)
units = now:sub(now:find(",")+2, -2)
-- Day/Night icon change
local hour = tonumber(os.date("%H"))
@ -110,14 +107,6 @@ local function fetch_weather(args)
sky = sky .. forecast:gsub(" ", ""):gsub("/", "") .. ".png"
-- In case there's no defined icon for current forecast
f = io.popen(sky)
if f == nil then
sky = icon_path .. "na.png"
else
f:close()
end
-- Localization
local f = io.open(localizations_path .. language, "r")
if language:find("en_") == nil and f ~= nil
@ -132,21 +121,18 @@ local function fetch_weather(args)
end
-- Finally setting infos
both = weather_data:match(": %S+.-\n"):gsub(": ", "")
yawn.icon:set_image(sky)
widget = wibox.widget.textbox()
forecast = weather_data:match(": %S+.-,"):gsub(": ", ""):gsub(",", "\n")
units = units:gsub(" ", "")
notification_preset = {}
-- anche notification preset, con fg, bg e position
yawn.forecast = markup(yawn.color, " " .. markup.font(beautiful.font, forecast) .. " ")
yawn.units = markup(yawn.color, " " .. markup.font(beautiful.font, units))
yawn.icon:set_image(sky)
settings()
if toshow == "forecast" then
return yawn.forecast
elseif toshow == "units" then
return yawn.units
else
return both
end
yawn.widget = widget
yawn.notification_preset = notification_preset
end
function yawn.hide()
@ -159,41 +145,29 @@ end
function yawn.show(t_out)
if yawn.widget._layout.text == "?"
then
if update_timer ~= nil
then
update_timer:emit_signal("timeout")
else
fetch_weather(settings)
end
fetch_weather(settings)
end
yawn.hide()
notification = naughty.notify({
preset = yawn.notification_preset,
text = weather_data,
icon = sky,
timeout = t_out,
fg = yawn.color
timeout = t_out
})
end
function yawn.register(id, args)
local args = args or {}
settings = args
yawn.color = args.color or beautiful.fg_normal or "#FFFFFF"
local args = args or {}
local timeout = args.timeout or 600
settings = args.settings or function() end
if args.u == "f" then units_set = '?u=f&w=' end
city_id = id
update_timer = timer({ timeout = 600 }) -- 10 mins
update_timer:connect_signal("timeout", function()
yawn.widget:set_markup(fetch_weather(settings))
end)
update_timer:start()
update_timer:emit_signal("timeout")
newtimer("yawn", timeout, fetch_weather)
yawn.icon:connect_signal("mouse::enter", function()
yawn.show(0)
@ -202,7 +176,7 @@ function yawn.register(id, args)
yawn.hide()
end)
return yawn
return { icon = yawn.icon, widget = yawn.widget }
end
function yawn.attach(widget, id, args)
@ -217,6 +191,4 @@ function yawn.attach(widget, id, args)
end)
end
-- }}}
return setmetatable(yawn, { __call = function(_, ...) return yawn.register(...) end })