This commit is contained in:
Jörg Thalheim 2014-01-01 13:35:13 +01:00
commit 080e28504a
15 changed files with 193 additions and 87 deletions

21
CHANGES
View File

@ -2,6 +2,27 @@
Full changelog is available online: Full changelog is available online:
http://git.sysphere.org/vicious/log/?showmsg=1 http://git.sysphere.org/vicious/log/?showmsg=1
--------------------------------------------------- ---------------------------------------------------
6e16a41 bat: fix broken battery remaining time (was always N/A)
bfbc1bd volume: get the normalized volume like alsamixer and DE's indicator
3ef0f11 Next release, tag 2.1.2
946271c bat: expose information on battery wear and tear
7626989 README: write a list of major contributors to the project
c51e13c init: stop allocating reg table functions with properties
52cbb64 Revert "init: emit timeout instead of forced update"
7961ca1 weather: add support for dew point
dc556e5 bat: Use a real minus sign for the charging status
f36997b README: explain wifi abbreviations linp and sign
71ea0f3 README: enable caching in vicious.widgets.cpu example
211d450 init: share timers when possible
75cd103 Revert "mpd: workaround command termination bug in mpd server v0.18"
a6a73f4 mpd: workaround command termination bug in mpd server v0.18
c795642 README: update awesome usage examples for v3.5
563cb6f pkg: revert to pacman as default Arch method, checkupdates optional
01b2302 pkg: use checkupdates on Arch Linux.
2641bf8 contrib: add Open Weather and ATi graphics widget types
0fd4fc5 mboxc: Fixed typo in setmetatable after ported to lua 5.2
052d19e README: explain vicious is a generic WM widget library
bb891d6 Next release, tag 2.1.1
fac688e wifi: add support for /usr/bin binary path fac688e wifi: add support for /usr/bin binary path
f7fdd90 README: usage examples are for awesome version 3.4 f7fdd90 README: usage examples are for awesome version 3.4
d63343e contrib: add buildbot monitoring widget d63343e contrib: add buildbot monitoring widget

40
README
View File

@ -159,11 +159,12 @@ vicious.widgets.uptime
for 5 minutes and 6th for 15 minutes for 5 minutes and 6th for 15 minutes
vicious.widgets.bat vicious.widgets.bat
- provides state, charge, and remaining time for a requested battery - provides state, charge, remaining time and wear for a requested
battery
- takes battery ID as an argument, i.e. "BAT0" - takes battery ID as an argument, i.e. "BAT0"
- returns 1st value as state of requested battery, 2nd as charge - returns 1st value as state of requested battery, 2nd as charge
level in percent and 3rd as remaining (charging or discharging) level in percent, 3rd as remaining (charging or discharging)
time time and 4th as the wear level in percent
vicious.widgets.mem vicious.widgets.mem
- provides RAM and Swap usage statistics - provides RAM and Swap usage statistics
@ -218,13 +219,15 @@ vicious.widgets.wifi
- provides wireless information for a requested interface - provides wireless information for a requested interface
- takes the network interface as an argument, i.e. "wlan0" - takes the network interface as an argument, i.e. "wlan0"
- returns a table with string keys: {ssid}, {mode}, {chan}, {rate}, - returns a table with string keys: {ssid}, {mode}, {chan}, {rate},
{link}, {linp} and {sign} {link}, {linp} (link quality in percent) and {sign} (signal level)
vicious.widgets.mbox vicious.widgets.mbox
- provides the subject of last e-mail in a mbox file - provides the subject of last e-mail in a mbox file
- takes the full path to the mbox as an argument, or a table with - takes the full path to the mbox as an argument, or a table with
1st field as path, 2nd as maximum lenght and 3rd (optional) as 1st field as path, 2nd as maximum length and 3rd (optional) as
widget name - if 3rd field is present scrolling will be used widget name - if 3rd field is present scrolling will be used (note: the
path will be escaped so special variables like ~ will not work, use
os.getenv("HOME").."mail" instead to access environment variables)
- returns 1st value as the subject of the last e-mail - returns 1st value as the subject of the last e-mail
vicious.widgets.mboxc vicious.widgets.mboxc
@ -243,11 +246,14 @@ vicious.widgets.mdir
vicious.widgets.gmail vicious.widgets.gmail
- provides count of new and subject of last e-mail on Gmail - provides count of new and subject of last e-mail on Gmail
- takes an (optional) argument, if it's a number subject will be - takes an (optional) argument, if it's a number subject will be
truncated, if a table, with 1st field as maximum lenght and 2nd truncated, if a table, with 1st field as maximum length and 2nd
the widget name (i.e. "gmailwidget"), scrolling will be used the widget name (i.e. "gmailwidget"), scrolling will be used
- keeps login information in the ~/.netrc file, example: - keeps login information in the ~/.netrc file, example:
machine mail.google.com login user password pass machine mail.google.com login user password pass
- returns a table with string keys: {count} and {subject} - returns a table with string keys: {count} and {subject}
- to be able to use this widget, make sure in your Gmail account
you disabled "two step verification" (https://support.google.com/accounts/answer/1064203)
and then "allowed access to your account for less secure apps" (https://www.google.com/settings/security/lesssecureapps)
vicious.widgets.org vicious.widgets.org
- provides agenda statistics for Emacs org-mode - provides agenda statistics for Emacs org-mode
@ -282,7 +288,8 @@ vicious.widgets.weather
- provides weather information for a requested station - provides weather information for a requested station
- takes the ICAO station code as an argument, i.e. "LDRI" - takes the ICAO station code as an argument, i.e. "LDRI"
- returns a table with string keys: {city}, {wind}, {windmph}, - returns a table with string keys: {city}, {wind}, {windmph},
{windkmh}, {sky}, {weather}, {tempf}, {tempc}, {humid}, {press} {windkmh}, {sky}, {weather}, {tempf}, {tempc}, {humid}, {dewf},
{dewc}, {press}
vicious.widgets.date vicious.widgets.date
- provides access to os.date, with optional time formatting provided - provides access to os.date, with optional time formatting provided
@ -308,10 +315,10 @@ holds widget types that were obsoleted or rewritten. Contrib widgets
will not be imported by init unless you explicitly enable it, or load will not be imported by init unless you explicitly enable it, or load
them in your rc.lua. them in your rc.lua.
Richard Kolkovich, a FreeBSD user, published his vicious-fbsd Rudi Siegel, a FreeBSD user, published his FreeBSD branch. If you are
branch. If you are also a BSD user you can find his work here: also a BSD user you can find his work here:
- http://git.sigil.org/vicious-fbsd/ - https://bitbucket.org/mutluyum/vicious_bsd/
Some users would like to avoid writing new modules. For them Vicious Some users would like to avoid writing new modules. For them Vicious
kept the old Wicked functionality, possibility to register their own kept the old Wicked functionality, possibility to register their own
@ -445,10 +452,12 @@ CPU usage widget
cpuwidget:set_background_color("#494B4F") cpuwidget:set_background_color("#494B4F")
cpuwidget:set_color({ type = "linear", from = { 0, 0 }, to = { 50, 0 }, cpuwidget:set_color({ type = "linear", from = { 0, 0 }, to = { 50, 0 },
stops = { { 0, "#FF5656" }, { 0.5, "#88A175" }, { 1, "#AECF96" }}) stops = { { 0, "#FF5656" }, { 0.5, "#88A175" }, { 1, "#AECF96" }})
vicious.cache(vicious.widgets.cpu)
vicious.register(cpuwidget, vicious.widgets.cpu, "$1", 3) vicious.register(cpuwidget, vicious.widgets.cpu, "$1", 3)
- updated every 3 seconds, feeds the graph with total usage - updated every 3 seconds, feeds the graph with total usage
percentage of all CPUs/cores percentage of all CPUs/cores and enable caching of this widget
type
Format functions Format functions
@ -565,9 +574,7 @@ Wicked written by:
Vicious written by: Vicious written by:
- Adrian C. (anrxc) <anrxc sysphere.org> - Adrian C. (anrxc) <anrxc sysphere.org>
Vicious contributors: Vicious major contributors:
- Michael Unterkalmsteiner <miciu gmx.de>
- Martin Striz <striz raynet.cz>
- Benedikt Sauer <filmor gmail.com> - Benedikt Sauer <filmor gmail.com>
- Greg D. <jabbas jabbas.pl> - Greg D. <jabbas jabbas.pl>
- Henning Glawe <glaweh debian.org> - Henning Glawe <glaweh debian.org>
@ -576,3 +583,6 @@ Vicious contributors:
- Hagen Schink <troja84 googlemail.com> - Hagen Schink <troja84 googlemail.com>
- Jörg Thalheim <jthalheim gmail.com> - Jörg Thalheim <jthalheim gmail.com>
- Arvydas Sidorenko <asido4 gmail.com> - Arvydas Sidorenko <asido4 gmail.com>
- Dodo The Last <dodo.the.last gmail.com>
- ...
- Consult git log for a complete list of contributors

View File

@ -76,6 +76,11 @@ vicious.contrib.openweather
- returns a table with string keys: {city}, {wind deg}, {wind aim}, - returns a table with string keys: {city}, {wind deg}, {wind aim},
{wind kmh}, {wind mps}, {sky}, {weather}, {temp c}, {humid}, {press} {wind kmh}, {wind mps}, {sky}, {weather}, {temp c}, {humid}, {press}
vicious.contrib.nvsmi
- provides (very basic) information about Nvidia GPU status from SMI
- takes optional card ID as an argument, i.e. "1", or defaults to ID 0
- returns 1st value as temperature of requested graphics device
vicious.contrib.ossvol vicious.contrib.ossvol
- -

42
contrib/nvsmi.lua Normal file
View File

@ -0,0 +1,42 @@
---------------------------------------------------
-- Licensed under the GNU General Public License v2
-- * (c) 2014, Adrian C. <anrxc@sysphere.org>
---------------------------------------------------
-- {{{ Grab environment
local tonumber = tonumber
local io = { popen = io.popen }
local setmetatable = setmetatable
local string = { match = string.match }
-- }}}
-- nvsmi: provides GPU information from nvidia SMI
-- vicious.contrib.nvsmi
local nvsmi = {}
-- {{{ GPU Information widget type
local function worker(format, warg)
-- Fallback to querying first device
if not warg then warg = "0" end
-- Get data from smi
-- * Todo: support more; MEMORY,UTILIZATION,ECC,POWER,CLOCK,COMPUTE,PIDS,PERFORMANCE
local f = io.popen("nvidia-smi -q -d TEMPERATURE -i " .. warg)
local smi = f:read("*all")
f:close()
-- Not installed
if smi == nil then return {0} end
-- Get temperature information
local _thermal = string.match(smi, "Gpu[%s]+:[%s]([%d]+)[%s]C")
-- Handle devices without data
if _thermal == nil then return {0} end
return {tonumber(_thermal)}
end
-- }}}
return setmetatable(nvsmi, { __call = function(_, ...) return worker(...) end })

View File

@ -18,7 +18,8 @@ local string = {
gmatch = string.gmatch gmatch = string.gmatch
} }
local math = { local math = {
floor = math.floor floor = math.floor,
ceil = math.ceil
} }
-- }}} -- }}}
@ -29,15 +30,19 @@ local pulse = {}
-- {{{ Helper function -- {{{ Helper function
local function pacmd(args) local function pacmd(args)
local f = io.popen("pacmd "..args) local f = io.popen("pacmd "..args)
local line = f:read("*all") if f == nil then
f:close() return nil
return line else
local line = f:read("*all")
f:close()
return line
end
end end
local function escape(text) local function escape(text)
local special_chars = { ["."] = "%.", ["-"] = "%-" } local special_chars = { ["."] = "%.", ["-"] = "%-" }
return text:gsub("[%.%-]", special_chars) return text:gsub("[%.%-]", special_chars)
end end
local cached_sinks = {} local cached_sinks = {}
@ -47,10 +52,11 @@ local function get_sink_name(sink)
local key = sink or 1 local key = sink or 1
-- Cache requests -- Cache requests
if not cached_sinks[key] then if not cached_sinks[key] then
local line = pacmd("list-sinks") local line = pacmd("list-sinks")
for s in string.gmatch(line, "name: <(.-)>") do if line == nil then return nil end
table.insert(cached_sinks, s) for s in string.gmatch(line, "name: <(.-)>") do
end table.insert(cached_sinks, s)
end
end end
return cached_sinks[key] return cached_sinks[key]
@ -66,10 +72,11 @@ local function worker(format, sink)
-- Get sink data -- Get sink data
local data = pacmd("dump") local data = pacmd("dump")
if sink == nil then return {0, "unknown"} end
-- If mute return 0 (not "Mute") so we don't break progressbars -- If mute return 0 (not "Mute") so we don't break progressbars
if string.find(data,"set%-sink%-mute "..escape(sink).." yes") then if string.find(data,"set%-sink%-mute "..escape(sink).." yes") then
return {0, "off"} return {0, "off"}
end end
local vol = tonumber(string.match(data, "set%-sink%-volume "..escape(sink).." (0x[%x]+)")) local vol = tonumber(string.match(data, "set%-sink%-volume "..escape(sink).." (0x[%x]+)"))
@ -93,6 +100,8 @@ function pulse.add(percent, sink)
if vol > 0x10000 then vol = 0x10000 end if vol > 0x10000 then vol = 0x10000 end
if vol < 0 then vol = 0 end if vol < 0 then vol = 0 end
vol = math.ceil(vol)
local cmd = string.format("pacmd set-sink-volume %s 0x%x >/dev/null", sink, vol) local cmd = string.format("pacmd set-sink-volume %s 0x%x >/dev/null", sink, vol)
return os.execute(cmd) return os.execute(cmd)
end end

View File

@ -96,6 +96,15 @@ function helpers.escape(text)
end end
-- }}} -- }}}
-- {{{ Escape a string for save usage on the command line
function helpers.shellquote(s)
if s == nil then return "" end
-- use single quotes, and put single quotes into double quotes
-- the string $'b is then quoted as '$'"'"'b'"'"'
return "'" .. s:gsub("'", "'\"'\"'") .. "'"
end
-- }}}
-- {{{ Capitalize a string -- {{{ Capitalize a string
function helpers.capitalize(text) function helpers.capitalize(text)
return text and text:gsub("([%w])([%w]*)", function(c, s) return text and text:gsub("([%w])([%w]*)", function(c, s)

View File

@ -10,7 +10,7 @@
local type = type local type = type
local pairs = pairs local pairs = pairs
local tonumber = tonumber local tonumber = tonumber
local capi = { timer = timer } local timer = (type(timer) == 'table' and timer or require("gears.timer"))
local os = { time = os.time } local os = { time = os.time }
local table = { local table = {
insert = table.insert, insert = table.insert,
@ -116,7 +116,7 @@ local function regregister(reg)
-- Start the timer -- Start the timer
if reg.timer > 0 then if reg.timer > 0 then
local tm = timers[reg.timer] and timers[reg.timer].timer local tm = timers[reg.timer] and timers[reg.timer].timer
tm = tm or capi.timer({ timeout = reg.timer }) tm = tm or timer({ timeout = reg.timer })
if tm.connect_signal then if tm.connect_signal then
tm:connect_signal("timeout", reg.update) tm:connect_signal("timeout", reg.update)
else else
@ -131,7 +131,7 @@ local function regregister(reg)
tm:start() tm:start()
end end
-- Initial update -- Initial update
tm:emit_signal("timeout") reg.update()
end end
reg.running = true reg.running = true
end end
@ -151,12 +151,11 @@ function vicious.register(widget, wtype, format, timer, warg)
timer = timer, timer = timer,
warg = warg, warg = warg,
widget = widget, widget = widget,
-- Update function
update = function ()
update(widget, reg)
end,
} }
-- Set functions
reg.update = function ()
update(widget, reg)
end
-- Default to 2s timer -- Default to 2s timer
if reg.timer == nil then if reg.timer == nil then

View File

@ -1,6 +1,7 @@
--------------------------------------------------- ---------------------------------------------------
-- Licensed under the GNU General Public License v2 -- Licensed under the GNU General Public License v2
-- * (c) 2010, Adrian C. <anrxc@sysphere.org> -- * (c) 2010, Adrian C. <anrxc@sysphere.org>
-- * (c) 2013, NormalRa <normalrawr@gmail.com>
--------------------------------------------------- ---------------------------------------------------
-- {{{ Grab environment -- {{{ Grab environment
@ -15,7 +16,7 @@ local math = {
-- }}} -- }}}
-- Bat: provides state, charge, and remaining time for a requested battery -- Bat: provides state, charge, remaining time, and wear for a requested battery
-- vicious.widgets.bat -- vicious.widgets.bat
local bat = {} local bat = {}
@ -30,12 +31,12 @@ local function worker(format, warg)
["Unknown\n"] = "", ["Unknown\n"] = "",
["Charged\n"] = "", ["Charged\n"] = "",
["Charging\n"] = "+", ["Charging\n"] = "+",
["Discharging\n"] = "-" ["Discharging\n"] = ""
} }
-- Check if the battery is present -- Check if the battery is present
if battery.present ~= "1\n" then if battery.present ~= "1\n" then
return {battery_state["Unknown\n"], 0, "N/A"} return {battery_state["Unknown\n"], 0, "N/A", 0}
end end
@ -45,14 +46,17 @@ local function worker(format, warg)
-- Get capacity information -- Get capacity information
if battery.charge_now then if battery.charge_now then
remaining, capacity = battery.charge_now, battery.charge_full remaining, capacity = battery.charge_now, battery.charge_full
capacity_design = battery.charge_full_design or capacity
elseif battery.energy_now then elseif battery.energy_now then
remaining, capacity = battery.energy_now, battery.energy_full remaining, capacity = battery.energy_now, battery.energy_full
capacity_design = battery.energy_full_design or capacity
else else
return {battery_state["Unknown\n"], 0, "N/A"} return {battery_state["Unknown\n"], 0, "N/A", 0}
end end
-- Calculate percentage (but work around broken BAT/ACPI implementations) -- Calculate capacity and wear percentage (but work around broken BAT/ACPI implementations)
local percent = math.min(math.floor(remaining / capacity * 100), 100) local percent = math.min(math.floor(remaining / capacity * 100), 100)
local wear = math.floor(100 - capacity / capacity_design * 100)
-- Get charge information -- Get charge information
@ -61,7 +65,7 @@ local function worker(format, warg)
elseif battery.power_now then elseif battery.power_now then
rate = tonumber(battery.power_now) rate = tonumber(battery.power_now)
else else
return {state, percent, "N/A"} return {state, percent, "N/A", wear}
end end
-- Calculate remaining (charging or discharging) time -- Calculate remaining (charging or discharging) time
@ -70,10 +74,10 @@ local function worker(format, warg)
if rate ~= nil and rate ~= 0 then if rate ~= nil and rate ~= 0 then
if state == "+" then if state == "+" then
timeleft = (tonumber(capacity) - tonumber(remaining)) / tonumber(rate) timeleft = (tonumber(capacity) - tonumber(remaining)) / tonumber(rate)
elseif state == "-" then elseif state == "" then
timeleft = tonumber(remaining) / tonumber(rate) timeleft = tonumber(remaining) / tonumber(rate)
else else
return {state, percent, time} return {state, percent, time, wear}
end end
-- Calculate time -- Calculate time
@ -83,7 +87,7 @@ local function worker(format, warg)
time = string.format("%02d:%02d", hoursleft, minutesleft) time = string.format("%02d:%02d", hoursleft, minutesleft)
end end
return {state, percent, time} return {state, percent, time, wear}
end end
-- }}} -- }}}

View File

@ -27,12 +27,12 @@ local function worker(format, warg)
if warg then warg = "" else warg = "-l" end if warg then warg = "" else warg = "-l" end
local fs_info = {} -- Get data from df local fs_info = {} -- Get data from df
local f = io.popen("LC_ALL=C df -kP " .. warg) local f = io.popen("LC_ALL=C df -kP " .. helpers.shellquote(warg))
for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount) for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount)
local s = string.match(line, "^.-[%s]([%d]+)") local s = string.match(line, "^.-[%s]([%d]+)")
local u,a,p = string.match(line, "([%d]+)[%D]+([%d]+)[%D]+([%d]+)%%") local u,a,p = string.match(line, "([%d]+)[%D]+([%d]+)[%D]+([%d]+)%%")
local m = string.match(line, "%%[%s]([%p%w]+)") local m = string.match(line, "%%[%s]+([%p%w]+)")
if u and m then -- Handle 1st line and broken regexp if u and m then -- Handle 1st line and broken regexp
helpers.uformat(fs_info, m .. " size", s, unit) helpers.uformat(fs_info, m .. " size", s, unit)

View File

@ -10,7 +10,6 @@ local io = { popen = io.popen }
local setmetatable = setmetatable local setmetatable = setmetatable
local helpers = require("vicious.helpers") local helpers = require("vicious.helpers")
local string = { local string = {
find = string.find,
match = string.match match = string.match
} }
-- }}} -- }}}
@ -23,18 +22,9 @@ local gmail = {}
-- {{{ Variable definitions -- {{{ Variable definitions
local rss = { local rss = {
inbox = { inbox = "https://mail.google.com/mail/feed/atom",
"https://mail.google.com/mail/feed/atom", unread = "https://mail.google.com/mail/feed/atom/unread",
"Gmail %- Inbox" --labelname = "https://mail.google.com/mail/feed/atom/labelname",
},
unread = {
"https://mail.google.com/mail/feed/atom/unread",
"Gmail %- Label"
},
--labelname = {
-- "https://mail.google.com/mail/feed/atom/labelname",
-- "Gmail %- Label"
--},
} }
-- Default is just Inbox -- Default is just Inbox
@ -49,31 +39,35 @@ local mail = {
-- {{{ Gmail widget type -- {{{ Gmail widget type
local function worker(format, warg) local function worker(format, warg)
-- Get info from the Gmail atom feed -- Get info from the Gmail atom feed
local f = io.popen("curl --connect-timeout 1 -m 3 -fsn " .. feed[1]) local f = io.popen("curl --connect-timeout 1 -m 3 -fsn " .. feed)
-- Could be huge don't read it all at once, info we are after is at the top -- Could be huge don't read it all at once, info we are after is at the top
for line in f:lines() do local xml = f:read(2000)
mail["{count}"] = -- Count comes before messages and matches at least 0
tonumber(string.match(line, "<fullcount>([%d]+)</fullcount>")) or mail["{count}"]
-- Find subject tags if xml ~= nil then
local title = string.match(line, "<title>(.*)</title>") return mail
-- If the subject changed then break out of the loop
if title ~= nil and not string.find(title, feed[2]) then
-- Check if we should scroll, or maybe truncate
if warg then
if type(warg) == "table" then
title = helpers.scroll(title, warg[1], warg[2])
else
title = helpers.truncate(title, warg)
end
end
-- Spam sanitize the subject and store
mail["{subject}"] = helpers.escape(title)
break
end
end end
mail["{count}"] = -- Count comes before messages and matches at least 0
tonumber(string.match(xml, "<fullcount>([%d]+)</fullcount>")) or mail["{count}"]
-- Find subject tag
local title = string.match(xml, "<entry>.-<title>(.-)</title>")
if title ~= nil then
-- Check if we should scroll, or maybe truncate
if warg then
if type(warg) == "table" then
title = helpers.scroll(title, warg[1], warg[2])
else
title = helpers.truncate(title, warg)
end
end
-- Spam sanitize the subject and store
mail["{subject}"] = helpers.escape(title)
end
f:close() f:close()
return mail return mail

View File

@ -8,6 +8,7 @@ local tonumber = tonumber
local io = { popen = io.popen } local io = { popen = io.popen }
local setmetatable = setmetatable local setmetatable = setmetatable
local string = { gmatch = string.gmatch } local string = { gmatch = string.gmatch }
local helpers = require("vicious.helpers")
-- }}} -- }}}
@ -22,7 +23,8 @@ local function worker(format, warg)
if warg == nil then warg = 7634 end if warg == nil then warg = 7634 end
local hdd_temp = {} -- Get info from the hddtemp daemon local hdd_temp = {} -- Get info from the hddtemp daemon
local f = io.popen("echo | curl --connect-timeout 1 -fsm 3 telnet://127.0.0.1:"..warg) local quoted = helpers.shellquote(warg)
local f = io.popen("echo | curl --connect-timeout 1 -fsm 3 telnet://127.0.0.1:"..quoted)
for line in f:lines() do for line in f:lines() do
for d, t in string.gmatch(line, "|([%/%a%d]+)|.-|([%d]+)|[CF]+|") do for d, t in string.gmatch(line, "|([%/%a%d]+)|.-|([%d]+)|[CF]+|") do

View File

@ -7,6 +7,7 @@
-- {{{ Grab environment -- {{{ Grab environment
local io = { popen = io.popen } local io = { popen = io.popen }
local setmetatable = setmetatable local setmetatable = setmetatable
local helpers = require("vicious.helpers")
-- }}} -- }}}
@ -23,13 +24,14 @@ local function worker(format, warg)
local count = { new = 0, cur = 0 } local count = { new = 0, cur = 0 }
for i=1, #warg do for i=1, #warg do
quoted_path = helpers.shellquote(warg[i])
-- Recursively find new messages -- Recursively find new messages
local f = io.popen("find '"..warg[i].."' -type f -wholename '*/new/*'") local f = io.popen("find "..quoted_path.." -type f -wholename '*/new/*'")
for line in f:lines() do count.new = count.new + 1 end for line in f:lines() do count.new = count.new + 1 end
f:close() f:close()
-- Recursively find "old" messages lacking the Seen flag -- Recursively find "old" messages lacking the Seen flag
local f = io.popen("find '"..warg[i].."' -type f -regex '.*/cur/.*2,[^S]*$'") local f = io.popen("find "..quoted_path.." -type f -regex '.*/cur/.*2,[^S]*$'")
for line in f:lines() do count.cur = count.cur + 1 end for line in f:lines() do count.cur = count.cur + 1 end
f:close() f:close()
end end

View File

@ -8,6 +8,7 @@ local tonumber = tonumber
local io = { popen = io.popen } local io = { popen = io.popen }
local setmetatable = setmetatable local setmetatable = setmetatable
local string = { match = string.match } local string = { match = string.match }
local helpers = require("vicious.helpers")
-- }}} -- }}}
@ -26,7 +27,7 @@ local function worker(format, warg)
} }
-- Get mixer control contents -- Get mixer control contents
local f = io.popen("amixer get " .. warg) local f = io.popen("amixer -M get " .. helpers.shellquote(warg))
local mixer = f:read("*all") local mixer = f:read("*all")
f:close() f:close()

View File

@ -28,6 +28,8 @@ local _weather = {
["{weather}"] = "N/A", ["{weather}"] = "N/A",
["{tempf}"] = "N/A", ["{tempf}"] = "N/A",
["{tempc}"] = "N/A", ["{tempc}"] = "N/A",
["{dewf}"] = "N/A",
["{dewc}"] = "N/A",
["{humid}"] = "N/A", ["{humid}"] = "N/A",
["{press}"] = "N/A" ["{press}"] = "N/A"
} }
@ -38,8 +40,8 @@ local function worker(format, warg)
-- Get weather forceast by the station ICAO code, from: -- Get weather forceast by the station ICAO code, from:
-- * US National Oceanic and Atmospheric Administration -- * US National Oceanic and Atmospheric Administration
local noaa = "http://weather.noaa.gov/pub/data/observations/metar/decoded/" local url = "http://weather.noaa.gov/pub/data/observations/metar/decoded/"..warg
local f = io.popen("curl --connect-timeout 1 -fsm 3 "..noaa..warg..".TXT") local f = io.popen("curl --connect-timeout 1 -fsm 3 "..helpers.shellquote(url)..".TXT")
local ws = f:read("*all") local ws = f:read("*all")
f:close() f:close()
@ -58,6 +60,8 @@ local function worker(format, warg)
string.match(ws, "Weather:[%s](.-)[%c]") or _weather["{weather}"] string.match(ws, "Weather:[%s](.-)[%c]") or _weather["{weather}"]
_weather["{tempf}"] = -- Temperature in fahrenheit _weather["{tempf}"] = -- Temperature in fahrenheit
string.match(ws, "Temperature:[%s]([%-]?[%d%.]+).*[%c]") or _weather["{tempf}"] string.match(ws, "Temperature:[%s]([%-]?[%d%.]+).*[%c]") or _weather["{tempf}"]
_weather["{dewf}"] = -- Dew Point in fahrenheit
string.match(ws, "Dew[%s]Point:[%s]([%-]?[%d%.]+).*[%c]") or _weather["{dewf}"]
_weather["{humid}"] = -- Relative humidity in percent _weather["{humid}"] = -- Relative humidity in percent
string.match(ws, "Relative[%s]Humidity:[%s]([%d]+)%%") or _weather["{humid}"] string.match(ws, "Relative[%s]Humidity:[%s]([%d]+)%%") or _weather["{humid}"]
_weather["{press}"] = -- Pressure in hPa _weather["{press}"] = -- Pressure in hPa
@ -71,6 +75,10 @@ local function worker(format, warg)
if _weather["{tempf}"] ~= "N/A" then if _weather["{tempf}"] ~= "N/A" then
_weather["{tempf}"] = tonumber(_weather["{tempf}"]) _weather["{tempf}"] = tonumber(_weather["{tempf}"])
_weather["{tempc}"] = math.ceil((_weather["{tempf}"] - 32) * 5/9) _weather["{tempc}"] = math.ceil((_weather["{tempf}"] - 32) * 5/9)
end -- Dew Point in °C if °F was available
if _weather["{dewf}"] ~= "N/A" then
_weather["{dewf}"] = tonumber(_weather["{dewf}"])
_weather["{dewc}"] = math.ceil((_weather["{dewf}"] - 32) * 5/9)
end -- Capitalize some stats so they don't look so out of place end -- Capitalize some stats so they don't look so out of place
if _weather["{sky}"] ~= "N/A" then if _weather["{sky}"] ~= "N/A" then
_weather["{sky}"] = helpers.capitalize(_weather["{sky}"]) _weather["{sky}"] = helpers.capitalize(_weather["{sky}"])

View File

@ -58,7 +58,7 @@ local function worker(format, warg)
end end
-- Get data from iwconfig where available -- Get data from iwconfig where available
local f = io.popen(iwconfig .." ".. warg .. " 2>&1") local f = io.popen(iwconfig .." ".. helpers.shellquote(warg) .. " 2>&1")
local iw = f:read("*all") local iw = f:read("*all")
f:close() f:close()