Merge pull request #89 from vicious-widgets/async
Deprecate the use of io.popen in most widget types
This commit is contained in:
commit
a542c5dbe2
10
.luacheckrc
10
.luacheckrc
|
@ -3,7 +3,15 @@ std = "min"
|
|||
|
||||
-- Global objects defined by the C code
|
||||
read_globals = {
|
||||
"timer", -- deprecated, but used in older versions.
|
||||
"timer", -- deprecated, but used in older versions.
|
||||
}
|
||||
|
||||
-- Warnings to be ignored
|
||||
ignore = {
|
||||
"212", -- Unused argument.
|
||||
}
|
||||
|
||||
-- Not enforced, but preferable
|
||||
max_code_line_length = 80
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
19
Changes.md
19
Changes.md
|
@ -1,11 +1,14 @@
|
|||
# Changes in 2.4.0 (WIP)
|
||||
|
||||
IMPORTANT:
|
||||
|
||||
- `volume_linux` now uses 🔉 and 🔈 instead of ♫ and ♩ to show mute state.
|
||||
- `volume` now uses 🔉 and 🔈 instead of ♫ and ♩ to show mute state.
|
||||
This BREAKS backward compatibility if users substitute custom symbols
|
||||
from these default.
|
||||
|
||||
Added:
|
||||
|
||||
- [wifi_linux] Expose frequency and transmission power
|
||||
- `spawn` as a fallback for `awful.spawn` in case Vicious is used as
|
||||
a stand-alone library. This wrapper, however, does NOT provide the facilities
|
||||
to asynchronously spawn new processes. It also lacks a few features such as
|
||||
|
@ -16,10 +19,22 @@ Added:
|
|||
|
||||
Fixed:
|
||||
|
||||
- [volume_linux] Deprecate `io.popen`
|
||||
- Deprecate the use of `io.popen` in following widgets:
|
||||
* wifi_linux, wifiiw_linux, hwmontemp_linux, hddtemp_linux
|
||||
* bat_freebsd, mem_freebsd, net_freebsd, thermal_freebsd, uptime_freebsd,
|
||||
cpu_freebsd, cpufreq_freebsd, fanspeed_freebsd
|
||||
* bat_openbsd
|
||||
* volume, gmail, mdir, mpd, fs
|
||||
- [mpd] Lua 5.3 compatibility (for real this time); also correct a typo
|
||||
- [pkg,weather,contrib/btc] Allow function call without Awesome
|
||||
- [pkg] Use more updated front-ends for Debian/Ubuntu (apt) and Fedora (dnf)
|
||||
- [os] Splitted os_all into os_linux and os_bsd (and refactored to async)
|
||||
- Tweak `.luacheckrc` to suit functional style and soft-limit text width to 80
|
||||
|
||||
Removed:
|
||||
|
||||
- `helpers.sysctl` and `helpers.sysctl_table` were removed in favour of
|
||||
`helpers.sysctl_async`.
|
||||
|
||||
# Changes in 2.3.3
|
||||
|
||||
|
|
31
README.md
31
README.md
|
@ -154,6 +154,16 @@ Supported platforms: GNU/Linux (require `sysfs`), FreeBSD (require `acpiconf`),
|
|||
* `$4`: Wear level in percent
|
||||
* `$5`: Current (dis)charge rate in Watt
|
||||
|
||||
### vicious.contrib.cmus
|
||||
|
||||
Provides cmus player information using `cmus-remote`.
|
||||
|
||||
Supported platforms: platform independent.
|
||||
|
||||
* Argument: a table whose first field is the socket including host (or nil).
|
||||
* Returns a table with string keys: `${status}`, `${artist}`, `${title}`,
|
||||
`${duration}`, `${file}`, `${continue}`, `${shuffle}`, `${repeat}`.
|
||||
|
||||
### vicious.widgets.cpu
|
||||
|
||||
Provides CPU usage for all available CPUs/cores. Since this widget type give
|
||||
|
@ -218,12 +228,13 @@ Returns a table with string keys: `${sda total_s}`, `${sda total_kb}`,
|
|||
|
||||
### vicious.widget.fanspeed
|
||||
|
||||
Provides fanspeed information for specified fan.
|
||||
Provides fanspeed information for specified fans.
|
||||
|
||||
Supported platforms: FreeBSD.
|
||||
|
||||
* Argument: full `sysctl` string to entry, e.g. `"dev.acpi_ibm.0.fan_speed"`
|
||||
* Returns speed of specified fan in RPM, `-1` on error (probably wrong string)
|
||||
* Argument: full `sysctl` string to one or multiple entries, e.g.
|
||||
`"dev.acpi_ibm.0.fan_speed"`
|
||||
* Returns speed of specified fan in RPM, `"N/A"` on error (probably wrong string)
|
||||
|
||||
### vicious.widgets.fs
|
||||
|
||||
|
@ -236,6 +247,7 @@ Supported platforms: platform independent.
|
|||
* Returns a table with string keys, using mount points as a base, e.g.
|
||||
`${/ size_mb}`, `${/ size_gb}`, `${/ used_mb}`, `${/ used_gb}`, `${/ used_p}`,
|
||||
`${/ avail_mb}`, `${/ avail_gb}`, `${/ avail_p}`, `${/home size_mb}`, etc.
|
||||
mb and gb refer to mebibyte and gibibyte respectively.
|
||||
|
||||
### vicious.widgets.gmail
|
||||
|
||||
|
@ -514,8 +526,10 @@ Provides wireless information for a requested interface.
|
|||
Supported platforms: GNU/Linux.
|
||||
|
||||
* Argument: the network interface, e.g. `"wlan0"`
|
||||
* Returns a table with string keys: `${ssid}`, `${mode}`, `${chan}`, `${rate}`,
|
||||
`${link}`, `${linp}` (link quality in percent) and `${sign}` (signal level)
|
||||
* Returns a table with string keys: `${ssid}`, `${mode}`, `${chan}`,
|
||||
`${rate}` (Mb/s), `${freq}` (MHz), `${txpw}` (transmission power, in dBm),
|
||||
`${sign}` (signal level), `${link}` and `${linp}` (link quality
|
||||
per 70 and per cent)
|
||||
|
||||
### vicious.widgets.wifiiw
|
||||
|
||||
|
@ -525,10 +539,9 @@ vicious.widgets.wifi, but uses `iw` instead of `iwconfig`).
|
|||
Supported platforms: GNU/Linux.
|
||||
|
||||
* Argument: the network interface, e.g. `"wlan0"`
|
||||
* Returns a table with string keys: `${bssid}`, `${ssid}`, `${mode}`, `${chan}`, `${rate}`,
|
||||
`${freq}`, `${linp}` (link quality in percent), `${txpw}` (tx power) and
|
||||
`${sign}` (signal level)
|
||||
|
||||
* Returns a table with string keys: `${bssid}`, `${ssid}`, `${mode}`, `${chan}`,
|
||||
`${rate}` (Mb/s), `${freq}` (MHz), `${linp}` (link quality in percent),
|
||||
`${txpw}` (transmission power, in dBm) and `${sign}` (signal level, in dBm)
|
||||
|
||||
## <a name="custom-widget"></a>Custom widget types
|
||||
|
||||
|
|
|
@ -87,6 +87,8 @@ yellow - in progress.
|
|||
|
||||
### vicious.contrib.cmus
|
||||
|
||||
NOTE: This widget type has been promoted to `widgets`.
|
||||
|
||||
Provides cmus player information using `cmus-remote`.
|
||||
|
||||
Supported platforms: platform independent.
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
-----------------------------------------------------------
|
||||
-- Licensed under the GNU General Public License v2
|
||||
-- * (c) 2017, JuanKman94 <juan.carlos.menonita@gmail.com>
|
||||
-----------------------------------------------------------
|
||||
|
||||
-- {{{ Grab environment
|
||||
local tonumber = tonumber
|
||||
local io = { popen = io.popen }
|
||||
local setmetatable = setmetatable
|
||||
local string = { gmatch = string.gmatch, format = string.format }
|
||||
local helpers = require("vicious.helpers")
|
||||
-- }}}
|
||||
|
||||
-- Cmus: provides CMUS information
|
||||
-- vicious.widgets.cmus
|
||||
local cmus_all = {}
|
||||
|
||||
-- {{{ CMUS widget type
|
||||
local function worker(format, warg)
|
||||
local cmus_state = {
|
||||
["{duration}"] = 0,
|
||||
["{file}"] = "N/A",
|
||||
["{status}"] = "N/A",
|
||||
["{title}"] = "N/A",
|
||||
["{artist}"] = "N/A",
|
||||
["{continue}"] = "off",
|
||||
["{shuffle}"] = "off",
|
||||
["{repeat}"] = "off",
|
||||
}
|
||||
|
||||
-- Fallback to CMUS defaults
|
||||
local host = warg and (warg.host or warg[1]) or os.getenv("CMUS_SOCKET")
|
||||
|
||||
if not host then
|
||||
if os.getenv("XDG_RUNTIME_DIR") then
|
||||
host = os.getenv("XDG_RUNTIME_DIR") .. "/cmus-socket"
|
||||
else
|
||||
host = os.getenv("HOME") .. "/.config/cmus/socket"
|
||||
end
|
||||
end
|
||||
|
||||
-- Get data from CMUS server
|
||||
local f = io.popen("cmus-remote --query --server " .. helpers.shellquote(host))
|
||||
|
||||
for line in f:lines() do
|
||||
for module, value in string.gmatch(line, "([%w]+) (.*)$") do
|
||||
if module == "file" or module == "status" then
|
||||
cmus_state["{"..module.."}"] = value
|
||||
elseif module == "duration" then
|
||||
cmus_state["{"..module.."}"] = tonumber(value)
|
||||
else
|
||||
for k, v in string.gmatch(value, "([%w]+) (.*)$") do
|
||||
if module == "tag" then
|
||||
if k == "title" or k == "artist" then
|
||||
cmus_state["{"..k.."}"] = v
|
||||
end
|
||||
elseif module == "set" then
|
||||
if k == "continue" or k == "shuffle" or k == "repeat" then
|
||||
if v == "true" then
|
||||
cmus_state["{"..k.."}"] = "on"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
|
||||
return cmus_state
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(cmus_all, { __call = function(_, ...) return worker(...) end })
|
|
@ -0,0 +1 @@
|
|||
../widgets/cmus_all.lua
|
88
helpers.lua
88
helpers.lua
|
@ -19,10 +19,14 @@ local getmetatable = getmetatable
|
|||
local string = {
|
||||
upper = string.upper,
|
||||
lower = string.lower,
|
||||
format = string.format
|
||||
format = string.format,
|
||||
match = string.match,
|
||||
find = string.find,
|
||||
}
|
||||
local table = { concat = table.concat }
|
||||
local pcall = pcall
|
||||
local assert = assert
|
||||
local spawn = require("vicious.spawn")
|
||||
-- }}}
|
||||
|
||||
|
||||
|
@ -30,6 +34,12 @@ local assert = assert
|
|||
-- vicious.helpers
|
||||
local helpers = {}
|
||||
|
||||
-- {{{ Constants definitions
|
||||
local OS_UNSUPPORTED_ERR = "Vicious: platform not supported: %s"
|
||||
local NOT_FOUND_MSG = "module '%s' not found"
|
||||
local NOT_FOUND_ERR = [[
|
||||
Vicious: %s is not available for the current platform or does not exist]]
|
||||
-- }}}
|
||||
|
||||
-- {{{ Variable definitions
|
||||
local scroller = {}
|
||||
|
@ -52,8 +62,8 @@ end
|
|||
-- }}}
|
||||
|
||||
-- {{{ Loader of vicious modules
|
||||
function helpers.wrequire(table, key)
|
||||
local ret = rawget(table, key)
|
||||
function helpers.wrequire(collection, key)
|
||||
local ret = rawget(collection, key)
|
||||
|
||||
if ret then
|
||||
return ret
|
||||
|
@ -65,27 +75,26 @@ function helpers.wrequire(table, key)
|
|||
openbsd = { "openbsd", "bsd", "all" }
|
||||
}
|
||||
|
||||
local os = ostable[helpers.getos()]
|
||||
assert(os, "Vicious: platform not supported: " .. helpers.getos())
|
||||
local platform = ostable[helpers.getos()]
|
||||
assert(platform, OS_UNSUPPORTED_ERR:format(helpers.getos()))
|
||||
|
||||
for i = 1, #os do
|
||||
local name = table._NAME .. "." .. key .. "_" .. os[i]
|
||||
local basename = collection._NAME .. '.' .. key
|
||||
for i = 1, #platform do
|
||||
local name = basename .. '_' .. platform[i]
|
||||
local status, value = pcall(require, name)
|
||||
if status then
|
||||
ret = value
|
||||
break
|
||||
end
|
||||
local not_found_msg = "module '"..name.."' not found"
|
||||
|
||||
-- ugly but there is afaik no other way to check if a module exists
|
||||
if value:sub(1, #not_found_msg) ~= not_found_msg then
|
||||
-- module found, but different issue -> let's raise the real error
|
||||
require(name)
|
||||
-- This is ugly but AFAWK there is no other way to check for
|
||||
-- the type of error. If other error get caught, raise it.
|
||||
if value:find(NOT_FOUND_MSG:format(name), 1, true) == nil then
|
||||
require(name)
|
||||
end
|
||||
end
|
||||
|
||||
assert(ret, "Vicious: widget " .. table._NAME .. "." .. key .. " not available for current platform or does not exist")
|
||||
|
||||
assert(ret, NOT_FOUND_ERR:format(basename))
|
||||
return ret
|
||||
end
|
||||
-- }}}
|
||||
|
@ -106,8 +115,8 @@ end
|
|||
-- {{{ Expose path as a Lua table
|
||||
function helpers.pathtotable(dir)
|
||||
return setmetatable({ _path = dir },
|
||||
{ __index = function(table, index)
|
||||
local path = table._path .. '/' .. index
|
||||
{ __index = function(self, index)
|
||||
local path = self._path .. '/' .. index
|
||||
local f = io.open(path)
|
||||
if f then
|
||||
local s = f:read("*all")
|
||||
|
@ -116,7 +125,7 @@ function helpers.pathtotable(dir)
|
|||
return s
|
||||
else
|
||||
local o = { _path = path }
|
||||
setmetatable(o, getmetatable(table))
|
||||
setmetatable(o, getmetatable(self))
|
||||
return o
|
||||
end
|
||||
end
|
||||
|
@ -222,43 +231,28 @@ function helpers.scroll(text, maxlen, widget)
|
|||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Return result from one sysctl variable as string
|
||||
function helpers.sysctl(path)
|
||||
local fd = io.popen("sysctl -n " .. helpers.shellquote(path))
|
||||
-- {{{ Parse output of sysctl command calling the `parse` function
|
||||
function helpers.sysctl_async(path_table, parse)
|
||||
local ret = {}
|
||||
local path = {}
|
||||
|
||||
if not fd then
|
||||
return
|
||||
for i=1,#path_table do
|
||||
path[i] = helpers.shellquote(path_table[i])
|
||||
end
|
||||
|
||||
local ret = fd:read()
|
||||
path = table.concat(path, " ")
|
||||
|
||||
fd:close()
|
||||
|
||||
return ret
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Return result from multiple sysctl variables as table
|
||||
function helpers.sysctl_table(syspath)
|
||||
return setmetatable({ _path = syspath },
|
||||
{ __index = function(table, index)
|
||||
local path = "sysctl -n " .. helpers.shellquote(table._path .. "." .. index)
|
||||
local f = io.popen(path)
|
||||
if f then
|
||||
local s = f:read("*all")
|
||||
f:close()
|
||||
if select(2, s:gsub("\n", "\n")) > 1 then
|
||||
local o = { _path = path}
|
||||
setmetatable(o, getmetatable(table))
|
||||
return o
|
||||
else
|
||||
return s
|
||||
end
|
||||
spawn.with_line_callback("sysctl " .. path, {
|
||||
stdout = function(line)
|
||||
if not string.find(line, "sysctl: unknown oid") then
|
||||
local key, value = string.match(line, "(.+): (.+)")
|
||||
ret[key] = value
|
||||
end
|
||||
end
|
||||
end,
|
||||
output_done = function() parse(ret) end
|
||||
})
|
||||
end
|
||||
-- }}}
|
||||
-- }}}
|
||||
|
||||
return helpers
|
||||
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
-- {{{ Grab environment
|
||||
local setmetatable = setmetatable
|
||||
local tonumber = tonumber
|
||||
local io = { popen = io.popen }
|
||||
local math = { floor = math.floor }
|
||||
local helpers = require("vicious.helpers")
|
||||
local string = {
|
||||
gmatch = string.gmatch,
|
||||
match = string.match,
|
||||
format = string.format
|
||||
}
|
||||
|
||||
local helpers = require("vicious.helpers")
|
||||
local spawn = require("vicious.spawn")
|
||||
-- }}}
|
||||
|
||||
-- Battery: provides battery level of requested battery
|
||||
-- vicious.widgets.battery_freebsd
|
||||
local bat_freebsd = {}
|
||||
|
||||
local function worker(format, warg)
|
||||
local battery = warg or "batt"
|
||||
-- {{{ Battery widget type
|
||||
local function parse(stdout, stderr, exitreason, exitcode)
|
||||
local bat_info = {}
|
||||
local f = io.popen("acpiconf -i " .. helpers.shellquote(battery))
|
||||
for line in f:lines("*line") do
|
||||
for line in string.gmatch(stdout, "[^\n]+") do
|
||||
for key,value in string.gmatch(line, "(.+):%s+(.+)") do
|
||||
bat_info[key] = value
|
||||
end
|
||||
|
@ -25,25 +25,18 @@ local function worker(format, warg)
|
|||
|
||||
-- current state
|
||||
-- see: https://github.com/freebsd/freebsd/blob/master/usr.sbin/acpi/acpiconf/acpiconf.c
|
||||
local state
|
||||
if bat_info["State"] == "high" then
|
||||
state = "↯"
|
||||
elseif bat_info["State"] == "charging" then
|
||||
state = "+"
|
||||
elseif bat_info["State"] == "critical charging" then
|
||||
state = "+"
|
||||
elseif bat_info["State"] == "discharging" then
|
||||
state = "-"
|
||||
elseif bat_info["State"] == "critical discharging" then
|
||||
state = "!"
|
||||
elseif bat_info["State"] == "critical" then
|
||||
state = "!"
|
||||
else
|
||||
state = "N/A"
|
||||
end
|
||||
local battery_state = {
|
||||
["high"] = "↯",
|
||||
["charging"] = "+",
|
||||
["critical charging"] = "+",
|
||||
["discharging"] = "-",
|
||||
["critical discharging"] = "!",
|
||||
["critical"] = "!",
|
||||
}
|
||||
local state = battery_state[bat_info["State"]] or "N/A"
|
||||
|
||||
-- battery capacity in percent
|
||||
local percent = tonumber(string.match(bat_info["Remaining capacity"], "[%d]+"))
|
||||
local percent = tonumber(bat_info["Remaining capacity"]:match"[%d]+")
|
||||
|
||||
-- use remaining (charging or discharging) time calculated by acpiconf
|
||||
local time = bat_info["Remaining time"]
|
||||
|
@ -54,13 +47,13 @@ local function worker(format, warg)
|
|||
-- calculate wear level from (last full / design) capacity
|
||||
local wear = "N/A"
|
||||
if bat_info["Last full capacity"] and bat_info["Design capacity"] then
|
||||
local l_full = tonumber(string.match(bat_info["Last full capacity"], "[%d]+"))
|
||||
local design = tonumber(string.match(bat_info["Design capacity"], "[%d]+"))
|
||||
local l_full = tonumber(bat_info["Last full capacity"]:match"[%d]+")
|
||||
local design = tonumber(bat_info["Design capacity"]:match"[%d]+")
|
||||
wear = math.floor(l_full / design * 100)
|
||||
end
|
||||
|
||||
-- dis-/charging rate as presented by battery
|
||||
local rate = string.match(bat_info["Present rate"], "([%d]+)%smW")
|
||||
local rate = bat_info["Present rate"]:match"([%d]+)%smW"
|
||||
rate = string.format("%2.1f", tonumber(rate / 1000))
|
||||
|
||||
-- returns
|
||||
|
@ -72,4 +65,11 @@ local function worker(format, warg)
|
|||
return {state, percent, time, wear, rate}
|
||||
end
|
||||
|
||||
return setmetatable(bat_freebsd, { __call = function(_, ...) return worker(...) end })
|
||||
function bat_freebsd.async(format, warg, callback)
|
||||
local battery = warg or "batt"
|
||||
spawn.easy_async("acpiconf -i " .. helpers.shellquote(battery),
|
||||
function (...) callback(parse(...)) end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return helpers.setasyncall(bat_freebsd)
|
||||
|
|
|
@ -1,67 +1,85 @@
|
|||
-- bat_openbsd.lua - provide battery information on OpenBSD
|
||||
-- Copyright (C) 2019 Enric Morales
|
||||
-- Copyright (C) 2019 Nguyễn Gia Phong
|
||||
--
|
||||
-- This file is part of Vicious.
|
||||
--
|
||||
-- Vicious is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as
|
||||
-- published by the Free Software Foundation, either version 2 of the
|
||||
-- License, or (at your option) any later version.
|
||||
--
|
||||
-- Vicious is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU Affero General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Affero General Public License
|
||||
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
-- {{{ Grab environment
|
||||
local setmetatable = setmetatable
|
||||
local tonumber = tonumber
|
||||
local string = { format = string.format, gmatch = string.gmatch }
|
||||
local io = { popen = io.popen }
|
||||
local math = { floor = math.floor, modf = math.modf }
|
||||
|
||||
local helpers = require"vicious.helpers"
|
||||
local spawn = require"vicious.spawn"
|
||||
-- }}}
|
||||
|
||||
local bat_openbsd = {}
|
||||
local STATES = { [0] = "↯", -- not charging
|
||||
[1] = "-", -- discharging
|
||||
[2] = "!", -- critical
|
||||
[3] = "+", -- charging
|
||||
[4] = "N/A", -- unknown status
|
||||
[255] = "N/A" } -- unimplemented by the driver
|
||||
|
||||
local function worker(format, warg)
|
||||
local battery = warg or "bat0"
|
||||
local filter = string.format("hw.sensors.acpi%s", battery)
|
||||
local cmd = string.format("sysctl -a | grep '^%s'", filter)
|
||||
local proc = io.popen(cmd)
|
||||
return helpers.setasyncall{
|
||||
async = function (format, warg, callback)
|
||||
local filter = "hw.sensors.acpi" .. (warg or "bat0")
|
||||
local pattern = filter .. ".(%S+)=(%S+)"
|
||||
local bat_info = {}
|
||||
|
||||
local bat_info = {}
|
||||
for line in proc:lines("*l") do
|
||||
for key, value in string.gmatch(line, "(%S+)=(%S+)") do
|
||||
key = key:gsub(filter .. ".", "")
|
||||
bat_info[key] = value
|
||||
end
|
||||
end
|
||||
spawn.with_line_callback_with_shell(
|
||||
("sysctl -a | grep '^%s'"):format(filter),
|
||||
{ stdout = function (line)
|
||||
for key, value in line:gmatch(pattern) do
|
||||
bat_info[key] = value
|
||||
end
|
||||
end,
|
||||
output_done = function ()
|
||||
-- current state
|
||||
local state = STATES[tonumber(bat_info.raw0)]
|
||||
|
||||
-- current state
|
||||
local states = {[0] = "↯", -- not charging
|
||||
[1] = "-", -- discharging
|
||||
[2] = "!", -- critical
|
||||
[3] = "+", -- charging
|
||||
[4] = "N/A", -- unknown status
|
||||
[255] = "N/A"} -- unimplemented by the driver
|
||||
local state = states[tonumber(bat_info.raw0)]
|
||||
-- battery capacity in percent
|
||||
local percent = tonumber(
|
||||
bat_info.watthour3 / bat_info.watthour0 * 100)
|
||||
|
||||
-- battery capacity in percent
|
||||
local percent = tonumber(bat_info.watthour3 / bat_info.watthour0 * 100)
|
||||
local time
|
||||
if tonumber(bat_info.power0) < 1 then
|
||||
time = "∞"
|
||||
else
|
||||
local raw_time = bat_info.watthour3 / bat_info.power0
|
||||
local hours, hour_fraction = math.modf(raw_time)
|
||||
local minutes = math.floor(60 * hour_fraction)
|
||||
time = ("%d:%0.2d"):format(hours, minutes)
|
||||
end
|
||||
|
||||
local time
|
||||
if tonumber(bat_info.power0) < 1 then
|
||||
time = "∞"
|
||||
else
|
||||
local raw_time = bat_info.watthour3 / bat_info.power0
|
||||
local hours, hour_fraction = math.modf(raw_time)
|
||||
local minutes = math.floor(60 * hour_fraction)
|
||||
time = string.format("%d:%0.2d", hours, minutes)
|
||||
end
|
||||
-- calculate wear level from (last full / design) capacity
|
||||
local wear = "N/A"
|
||||
if bat_info.watthour0 and bat_info.watthour4 then
|
||||
local l_full = tonumber(bat_info.watthour0)
|
||||
local design = tonumber(bat_info.watthour4)
|
||||
wear = math.floor(l_full / design * 100)
|
||||
end
|
||||
|
||||
-- calculate wear level from (last full / design) capacity
|
||||
local wear = "N/A"
|
||||
if bat_info.watthour0 and bat_info.watthour4 then
|
||||
local l_full = tonumber(bat_info.watthour0)
|
||||
local design = tonumber(bat_info.watthour4)
|
||||
wear = math.floor(l_full / design * 100)
|
||||
end
|
||||
-- dis-/charging rate as presented by battery
|
||||
local rate = bat_info.power0
|
||||
|
||||
-- dis-/charging rate as presented by battery
|
||||
local rate = bat_info.power0
|
||||
|
||||
-- returns
|
||||
-- * state (high "↯", discharging "-", charging "+", N/A "⌁" }
|
||||
-- * remaining_capacity (percent)
|
||||
-- * remaining_time, by battery
|
||||
-- * wear level (percent)
|
||||
-- * present_rate (W)
|
||||
return {state, percent, time, wear, rate}
|
||||
end
|
||||
|
||||
return setmetatable(bat_openbsd, { __call = function(_, ...) return worker(...) end })
|
||||
-- Pass the following arguments to callback function:
|
||||
-- * battery state symbol (↯, -, !, + or N/A)
|
||||
-- * remaining_capacity (in percent)
|
||||
-- * remaining_time, by battery
|
||||
-- * wear level (in percent)
|
||||
-- * present_rate (in Watts)
|
||||
callback{state, percent, time, wear, rate}
|
||||
end })
|
||||
end }
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
-----------------------------------------------------------
|
||||
-- Licensed under the GNU General Public License v2
|
||||
-- * (c) 2017, JuanKman94 <juan.carlos.menonita@gmail.com>
|
||||
-----------------------------------------------------------
|
||||
|
||||
-- {{{ Grab environment
|
||||
local type = type
|
||||
local tonumber = tonumber
|
||||
local os = { getenv = os.getenv }
|
||||
|
||||
local helpers = require"vicious.helpers"
|
||||
local spawn = require"vicious.spawn"
|
||||
-- }}}
|
||||
|
||||
local CMUS_SOCKET = helpers.shellquote(os.getenv"CMUS_SOCKET")
|
||||
|
||||
-- Cmus: provides CMUS information
|
||||
-- vicious.widgets.cmus
|
||||
return helpers.setasyncall{
|
||||
async = function (format, warg, callback)
|
||||
local server = ""
|
||||
if type(warg) == "table" then
|
||||
server = " --server " .. helpers.shellquote(warg.host or warg[1])
|
||||
elseif CMUS_SOCKET ~= nil then
|
||||
server = " --server " .. CMUS_SOCKET
|
||||
end
|
||||
|
||||
local cmus_state = { ["{duration}"] = 0, ["{file}"] = "N/A",
|
||||
["{status}"] = "N/A", ["{title}"] = "N/A",
|
||||
["{artist}"] = "N/A", ["{continue}"] = "off",
|
||||
["{shuffle}"] = "off", ["{repeat}"] = "off" }
|
||||
|
||||
spawn.with_line_callback("cmus-remote --query" .. server, {
|
||||
stdout = function (line)
|
||||
for module, value in line:gmatch"([%w]+) (.*)$" do
|
||||
if module == "file" or module == "status" then
|
||||
cmus_state["{"..module.."}"] = value
|
||||
elseif module == "duration" then
|
||||
cmus_state["{"..module.."}"] = tonumber(value)
|
||||
else
|
||||
local k, v = value:gmatch("([%w]+) (.*)$")()
|
||||
if module == "tag" then
|
||||
cmus_state["{"..k.."}"] = v
|
||||
elseif module == "set" and v == "true" then
|
||||
cmus_state["{"..k.."}"] = "on"
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
output_done = function () callback(cmus_state) end })
|
||||
end }
|
|
@ -1,9 +1,8 @@
|
|||
-- {{{ Grab environment
|
||||
local helpers = require("vicious.helpers")
|
||||
local tonumber = tonumber
|
||||
local setmetatable = setmetatable
|
||||
local math = { floor = math.floor }
|
||||
local string = { gmatch = string.gmatch }
|
||||
|
||||
local helpers = require("vicious.helpers")
|
||||
-- }}}
|
||||
|
||||
|
||||
|
@ -16,54 +15,57 @@ local cpu_total = {}
|
|||
local cpu_idle = {}
|
||||
|
||||
-- {{{ CPU widget type
|
||||
local function worker(format)
|
||||
local cp_times = helpers.sysctl("kern.cp_times")
|
||||
function cpu_freebsd.async(format, warg, callback)
|
||||
local matches = {}
|
||||
local tmp_total = {}
|
||||
local tmp_idle = {}
|
||||
local tmp_usage = {}
|
||||
|
||||
-- Read input data
|
||||
for v in string.gmatch(cp_times, "([%d]+)") do
|
||||
table.insert(matches, v)
|
||||
end
|
||||
helpers.sysctl_async({ "kern.cp_times" }, function(ret)
|
||||
-- Read input data
|
||||
for v in string.gmatch(ret["kern.cp_times"], "([%d]+)") do
|
||||
table.insert(matches, v)
|
||||
end
|
||||
|
||||
-- Set first value of function tables
|
||||
if #cpu_total == 0 then -- check for empty table
|
||||
-- Set first value of function tables
|
||||
if #cpu_total == 0 then -- check for empty table
|
||||
for i = 1, #matches / 5 + 1 do
|
||||
cpu_total[i] = 0
|
||||
cpu_idle[i] = 0
|
||||
end
|
||||
end
|
||||
for i = 1, #matches / 5 + 1 do
|
||||
cpu_total[i] = 0
|
||||
cpu_idle[i] = 0
|
||||
tmp_total[i] = 0
|
||||
tmp_idle[i] = 0
|
||||
tmp_usage[i] = 0
|
||||
end
|
||||
end
|
||||
for i = 1, #matches / 5 + 1 do
|
||||
tmp_total[i] = 0
|
||||
tmp_idle[i] = 0
|
||||
tmp_usage[i] = 0
|
||||
end
|
||||
|
||||
-- CPU usage
|
||||
for i, v in ipairs(matches) do
|
||||
local index = math.floor((i-1) / 5) + 2 -- current cpu
|
||||
-- CPU usage
|
||||
for i, v in ipairs(matches) do
|
||||
local index = math.floor((i-1) / 5) + 2 -- current cpu
|
||||
|
||||
tmp_total[1] = tmp_total[1] + v
|
||||
tmp_total[index] = tmp_total[index] + v
|
||||
tmp_total[1] = tmp_total[1] + v
|
||||
tmp_total[index] = tmp_total[index] + v
|
||||
|
||||
if (i-1) % 5 == 4 then
|
||||
tmp_idle[1] = tmp_idle[1] + v
|
||||
tmp_idle[index] = tmp_idle[index] + v
|
||||
if (i-1) % 5 == 4 then
|
||||
tmp_idle[1] = tmp_idle[1] + v
|
||||
tmp_idle[index] = tmp_idle[index] + v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, #tmp_usage do
|
||||
tmp_usage[i] = tmp_total[i] - cpu_total[i]
|
||||
tmp_usage[i] = math.floor((tmp_usage[i] - (tmp_idle[i] - cpu_idle[i])) / tmp_usage[i] * 100)
|
||||
end
|
||||
for i = 1, #tmp_usage do
|
||||
tmp_usage[i] = tmp_total[i] - cpu_total[i]
|
||||
tmp_usage[i] = math.floor(
|
||||
(tmp_usage[i] - (tmp_idle[i] - cpu_idle[i]))
|
||||
/ tmp_usage[i] * 100)
|
||||
end
|
||||
|
||||
cpu_total = tmp_total
|
||||
cpu_idle = tmp_idle
|
||||
cpu_total = tmp_total
|
||||
cpu_idle = tmp_idle
|
||||
|
||||
return tmp_usage
|
||||
return callback(tmp_usage)
|
||||
end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(cpu_freebsd, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(cpu_freebsd)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
-- {{{ Grab environment
|
||||
local tonumber = tonumber
|
||||
local setmetatable = setmetatable
|
||||
local helpers = require("vicious.helpers")
|
||||
-- }}}
|
||||
|
||||
|
@ -11,24 +10,31 @@ local cpufreq_freebsd = {}
|
|||
|
||||
|
||||
-- {{{ CPU frequency widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
function cpufreq_freebsd.async(format, warg, callback)
|
||||
if not warg then return callback({}) end
|
||||
|
||||
-- Default frequency and voltage values
|
||||
local freqv = {
|
||||
["mhz"] = "N/A", ["ghz"] = "N/A",
|
||||
["v"] = "N/A", ["mv"] = "N/A",
|
||||
["governor"] = "N/A",
|
||||
}
|
||||
|
||||
local freq = tonumber(helpers.sysctl("dev.cpu." .. warg .. ".freq"))
|
||||
helpers.sysctl_async(
|
||||
{ "dev.cpu." .. warg .. ".freq" },
|
||||
function (ret)
|
||||
freqv.mhz = tonumber(ret["dev.cpu." .. warg .. ".freq"])
|
||||
freqv.ghz = freqv.mhz / 1000
|
||||
|
||||
freqv.mhz = freq
|
||||
freqv.ghz = freq / 1000
|
||||
|
||||
local governor = "N/A"
|
||||
|
||||
return {freqv.mhz, freqv.ghz, freqv.mv, freqv.v, governor}
|
||||
return callback({
|
||||
freqv.mhz,
|
||||
freqv.ghz,
|
||||
freqv.mv,
|
||||
freqv.v,
|
||||
freqv.governor
|
||||
})
|
||||
end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(cpufreq_freebsd, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(cpufreq_freebsd)
|
||||
|
|
|
@ -1,28 +1,37 @@
|
|||
-- {{{ Grab environment
|
||||
local setmetatable = setmetatable
|
||||
local helpers = require("vicious.helpers")
|
||||
local tonumber = tonumber
|
||||
local type = type
|
||||
|
||||
local helpers = require("vicious.helpers")
|
||||
-- }}}
|
||||
|
||||
|
||||
-- fanspeed: provides speed level of main fan
|
||||
-- fanspeed: provides speed level of fans
|
||||
-- vicious.widgets.fanspeed
|
||||
--
|
||||
-- expects one (1) full sysctl string to entry
|
||||
-- expects one or multiple full sysctl strings to entry
|
||||
-- e.g.: "dev.acpi_ibm.0.fan_speed"
|
||||
|
||||
local fanspeed_freebsd = {}
|
||||
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
-- {{{ fanspeed widget type
|
||||
function fanspeed_freebsd.async(format, warg, callback)
|
||||
if not warg then return callback({}) end
|
||||
if type(warg) ~= "table" then warg = { warg } end
|
||||
|
||||
local fanspeed = helpers.sysctl(warg)
|
||||
helpers.sysctl_async(warg, function(ret)
|
||||
local fanspeed = {}
|
||||
|
||||
if not fanspeed then
|
||||
-- use negative fanspeed to indicate error
|
||||
return {-1}
|
||||
else
|
||||
return {tonumber(fanspeed)}
|
||||
end
|
||||
for i=1,#warg do
|
||||
if ret[warg[i]] ~= nil then
|
||||
fanspeed[i] = tonumber(ret[warg[i]])
|
||||
else
|
||||
fanspeed[i] = "N/A"
|
||||
end
|
||||
end
|
||||
|
||||
callback(fanspeed)
|
||||
end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(fanspeed_freebsd, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(fanspeed_freebsd)
|
||||
|
|
|
@ -6,50 +6,34 @@
|
|||
|
||||
-- {{{ Grab environment
|
||||
local tonumber = tonumber
|
||||
local io = { popen = io.popen }
|
||||
local setmetatable = setmetatable
|
||||
local string = { match = string.match }
|
||||
local helpers = require("vicious.helpers")
|
||||
|
||||
local helpers = require"vicious.helpers"
|
||||
local spawn = require"vicious.spawn"
|
||||
-- }}}
|
||||
|
||||
-- Mebibyte and gibibyte respectively, because backward compatibility
|
||||
local UNIT = { mb = 1024, gb = 1024^2 }
|
||||
|
||||
-- FS: provides file system disk space usage
|
||||
-- vicious.widgets.fs
|
||||
local fs_all = {}
|
||||
return helpers.setasyncall{
|
||||
async = function(format, warg, callback)
|
||||
local fs_info = {} -- Get data from df
|
||||
spawn.with_line_callback_with_shell(
|
||||
warg and "LC_ALL=C df -kP" or "LC_ALL=C df -klP",
|
||||
{ stdout = function (line)
|
||||
-- (1024-blocks) (Used) (Available) (Capacity)% (Mounted on)
|
||||
local s, u, a, p, m = line:match(
|
||||
"^.-%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%%%s+([%p%w]+)")
|
||||
|
||||
if u and m then -- Handle 1st line and broken regexp
|
||||
helpers.uformat(fs_info, m .. " size", s, UNIT)
|
||||
helpers.uformat(fs_info, m .. " used", u, UNIT)
|
||||
helpers.uformat(fs_info, m .. " avail", a, UNIT)
|
||||
|
||||
-- Variable definitions
|
||||
local unit = { ["mb"] = 1024, ["gb"] = 1024^2 }
|
||||
|
||||
-- {{{ Filesystem widget type
|
||||
local function worker(format, warg)
|
||||
local cmd = "LC_ALL=C df -kP"
|
||||
if not warg then
|
||||
-- List only local filesystems by default
|
||||
cmd = cmd .. " -l"
|
||||
end
|
||||
|
||||
local fs_info = {} -- Get data from df
|
||||
local f = io.popen(cmd)
|
||||
|
||||
for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount)
|
||||
local s = string.match(line, "^.-[%s]([%d]+)")
|
||||
local u,a,p = string.match(line, "([%d]+)[%D]+([%d]+)[%D]+([%d]+)%%")
|
||||
local m = string.match(line, "%%[%s]+([%p%w]+)")
|
||||
|
||||
if u and m then -- Handle 1st line and broken regexp
|
||||
helpers.uformat(fs_info, m .. " size", s, unit)
|
||||
helpers.uformat(fs_info, m .. " used", u, unit)
|
||||
helpers.uformat(fs_info, m .. " avail", a, unit)
|
||||
|
||||
fs_info["{" .. m .. " used_p}"] = tonumber(p)
|
||||
fs_info["{" .. m .. " avail_p}"] = 100 - tonumber(p)
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
|
||||
return fs_info
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(fs_all, { __call = function(_, ...) return worker(...) end })
|
||||
fs_info["{" .. m .. " used_p}"] = tonumber(p)
|
||||
fs_info["{" .. m .. " avail_p}"] = 100 - tonumber(p)
|
||||
end
|
||||
end,
|
||||
output_done = function () callback(fs_info) end })
|
||||
end }
|
||||
|
|
|
@ -6,12 +6,10 @@
|
|||
-- {{{ Grab environment
|
||||
local type = type
|
||||
local tonumber = tonumber
|
||||
local io = { popen = io.popen }
|
||||
local setmetatable = setmetatable
|
||||
local string = { match = string.match }
|
||||
|
||||
local helpers = require("vicious.helpers")
|
||||
local string = {
|
||||
match = string.match
|
||||
}
|
||||
local spawn = require("vicious.spawn")
|
||||
-- }}}
|
||||
|
||||
|
||||
|
@ -19,59 +17,33 @@ local string = {
|
|||
-- vicious.widgets.gmail
|
||||
local gmail_all = {}
|
||||
|
||||
|
||||
-- {{{ Variable definitions
|
||||
local rss = {
|
||||
inbox = "https://mail.google.com/mail/feed/atom",
|
||||
unread = "https://mail.google.com/mail/feed/atom/unread",
|
||||
--labelname = "https://mail.google.com/mail/feed/atom/labelname",
|
||||
}
|
||||
|
||||
-- Default is just Inbox
|
||||
local feed = rss.inbox
|
||||
local mail = {
|
||||
["{count}"] = 0,
|
||||
["{subject}"] = "N/A"
|
||||
}
|
||||
-- }}}
|
||||
|
||||
|
||||
-- {{{ Gmail widget type
|
||||
local function worker(format, warg)
|
||||
-- Get info from the Gmail atom feed
|
||||
local f = io.popen("curl --connect-timeout 1 -m 3 -fsn " .. helpers.shellquote(feed))
|
||||
|
||||
-- Could be huge don't read it all at once, info we are after is at the top
|
||||
local xml = f:read(2000)
|
||||
|
||||
if xml == nil then
|
||||
return mail
|
||||
end
|
||||
|
||||
mail["{count}"] = -- Count comes before messages and matches at least 0
|
||||
tonumber(string.match(xml, "<fullcount>([%d]+)</fullcount>")) or mail["{count}"]
|
||||
local function parse(warg, stdout, stderr, exitreason, exitcode)
|
||||
local count = -- Count comes before messages and matches at least 0
|
||||
tonumber(string.match(stdout, "<fullcount>([%d]+)</fullcount>")) or 0
|
||||
|
||||
-- Find subject tag
|
||||
local title = string.match(xml, "<entry>.-<title>(.-)</title>")
|
||||
local title = string.match(stdout, "<entry>.-<title>(.-)</title>") or "N/A"
|
||||
|
||||
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}"] = title
|
||||
-- Check if we should scroll, or maybe truncate
|
||||
if type(warg) == "number" then
|
||||
title = helpers.truncate(title, warg)
|
||||
elseif type(warg) == "table" then
|
||||
title = helpers.scroll(title, warg[1], warg[2])
|
||||
end
|
||||
|
||||
f:close()
|
||||
return { ["{count}"] = count, ["{subject}"] = title }
|
||||
end
|
||||
|
||||
return mail
|
||||
function gmail_all.async(format, warg, callback)
|
||||
-- Get info from the Gmail atom feed using curl --netrc.
|
||||
-- With username 'user' and password 'pass'
|
||||
-- $HOME/.netrc should look similar to:
|
||||
-- machine mail.google.com login user password pass
|
||||
-- BE AWARE THAT MAKING THESE SETTINGS IS A SECURITY RISK!
|
||||
spawn.easy_async("curl -fsn https://mail.google.com/mail/feed/atom",
|
||||
function (...) callback(parse(warg, ...)) end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(gmail_all, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(gmail_all)
|
||||
|
|
|
@ -5,36 +5,24 @@
|
|||
|
||||
-- {{{ Grab environment
|
||||
local tonumber = tonumber
|
||||
local io = { popen = io.popen }
|
||||
local setmetatable = setmetatable
|
||||
local string = { gmatch = string.gmatch }
|
||||
local helpers = require("vicious.helpers")
|
||||
|
||||
local helpers = require"vicious.helpers"
|
||||
local spawn = require"vicious.spawn"
|
||||
-- }}}
|
||||
|
||||
|
||||
-- Hddtemp: provides hard drive temperatures using the hddtemp daemon
|
||||
-- vicious.widgets.hddtemp
|
||||
local hddtemp_linux = {}
|
||||
|
||||
|
||||
-- {{{ HDD Temperature widget type
|
||||
local function worker(format, warg)
|
||||
-- Fallback to default hddtemp port
|
||||
if warg == nil then warg = 7634 end
|
||||
|
||||
local hdd_temp = {} -- Get info from the hddtemp daemon
|
||||
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 d, t in string.gmatch(line, "|([%/%a%d]+)|.-|([%d]+)|[CF]+|") do
|
||||
hdd_temp["{"..d.."}"] = tonumber(t)
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
|
||||
return hdd_temp
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(hddtemp_linux, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall{
|
||||
async = function(format, warg, callback)
|
||||
if warg == nil then warg = 7634 end -- fallback to default hddtemp port
|
||||
local hdd_temp = {} -- get info from the hddtemp daemon
|
||||
spawn.with_line_callback_with_shell(
|
||||
"echo | curl -fs telnet://127.0.0.1:" .. warg,
|
||||
{ stdout = function (line)
|
||||
for d, t in line:gmatch"|([%/%w]+)|.-|(%d+)|[CF]|" do
|
||||
hdd_temp["{"..d.."}"] = tonumber(t)
|
||||
end
|
||||
end,
|
||||
output_done = function () callback(hdd_temp) end })
|
||||
end }
|
||||
|
|
|
@ -4,57 +4,37 @@
|
|||
----------------------------------------------------------------
|
||||
|
||||
-- environment
|
||||
local io = { popen = io.popen, open = io.open }
|
||||
local assert = assert
|
||||
local setmetatable = setmetatable
|
||||
local type = type
|
||||
local tonumber = tonumber
|
||||
local io = { open = io.open }
|
||||
|
||||
-- sysfs prefix for hwmon devices
|
||||
local sys_hwmon = "/sys/class/hwmon/"
|
||||
-- cache table for hwmon device names
|
||||
local paths = {}
|
||||
|
||||
-- transparently caching hwmon device name lookup
|
||||
function name_to_path(name)
|
||||
if paths[name] then return paths[name] end
|
||||
|
||||
for sensor in io.popen("ls -1 " .. sys_hwmon):lines() do
|
||||
local path = sys_hwmon .. sensor
|
||||
local f = assert(io.open(path .. "/name", "r"))
|
||||
local sname = f:read("*line")
|
||||
f:close()
|
||||
if sname == name then
|
||||
paths[name] = path
|
||||
return path
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
local helpers = require"vicious.helpers"
|
||||
local spawn = require"vicious.spawn"
|
||||
|
||||
-- hwmontemp: provides name-indexed temps from /sys/class/hwmon
|
||||
-- vicious.widgets.hwmontemp
|
||||
local hwmontemp_linux = {}
|
||||
|
||||
function worker(format, warg)
|
||||
assert(type(warg) == "table", "invalid hwmontemp argument: must be a table")
|
||||
name = warg[1]
|
||||
|
||||
if not warg[2] then
|
||||
input = 1
|
||||
else
|
||||
input = warg[2]
|
||||
end
|
||||
|
||||
local sensor = name_to_path(name)
|
||||
if not sensor then return { "N/A" } end
|
||||
|
||||
local f = assert(io.open(("%s/temp%d_input"):format(sensor, input), "r"))
|
||||
local temp = f:read("*line")
|
||||
f:close()
|
||||
|
||||
return { temp / 1000 }
|
||||
end
|
||||
|
||||
return setmetatable(hwmontemp_linux, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall{
|
||||
async = function (format, warg, callback)
|
||||
if type(warg) ~= "table" or type(warg[1]) ~= "string" then
|
||||
return callback{}
|
||||
end
|
||||
local input = warg[2]
|
||||
if type(input) == "number" then
|
||||
input = ("temp%d_input"):format(input)
|
||||
else
|
||||
input = "temp1_input"
|
||||
end
|
||||
|
||||
spawn.easy_async_with_shell(
|
||||
"grep " .. warg[1] .. " -wl /sys/class/hwmon/*/name",
|
||||
function (stdout, stderr, exitreason, exitcode)
|
||||
if exitreason == "exit" and exitcode == 0 then
|
||||
local f = io.open(stdout:gsub("name%s+", input), "r")
|
||||
callback{ tonumber(f:read"*line") / 1000 }
|
||||
f:close()
|
||||
else
|
||||
callback{}
|
||||
end
|
||||
end)
|
||||
end }
|
||||
-- vim: ts=4:sw=4:expandtab
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
---------------------------------------------------
|
||||
|
||||
-- {{{ Grab environment
|
||||
local io = { popen = io.popen }
|
||||
local setmetatable = setmetatable
|
||||
local helpers = require("vicious.helpers")
|
||||
local type = type
|
||||
|
||||
local helpers = require"vicious.helpers"
|
||||
local spawn = require"vicious.spawn"
|
||||
-- }}}
|
||||
|
||||
|
||||
|
@ -17,27 +18,25 @@ local mdir_all = {}
|
|||
|
||||
|
||||
-- {{{ Maildir widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
|
||||
-- Initialize counters
|
||||
local count = { new = 0, cur = 0 }
|
||||
|
||||
for i=1, #warg do
|
||||
quoted_path = helpers.shellquote(warg[i])
|
||||
-- Recursively find new messages
|
||||
local f = io.popen("find "..quoted_path.." -type f -wholename '*/new/*'")
|
||||
for line in f:lines() do count.new = count.new + 1 end
|
||||
f:close()
|
||||
|
||||
-- Recursively find "old" messages lacking the Seen flag
|
||||
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
|
||||
f:close()
|
||||
function mdir_all.async(format, warg, callback)
|
||||
if type(warg) ~= "table" then return callback{} end
|
||||
local starting_points = ""
|
||||
for _,dir in ipairs(warg) do
|
||||
starting_points = starting_points .. " " .. helpers.shellquote(dir)
|
||||
end
|
||||
if starting_points == "" then return callback{ 0, 0 } end
|
||||
|
||||
return {count.new, count.cur}
|
||||
local new, cur = 0, 0
|
||||
spawn.with_line_callback(
|
||||
"find" .. starting_points .. " -type f -regex '.*/cur/.*2,[^S]*$';",
|
||||
{ stdout = function (filename) cur = cur + 1 end,
|
||||
output_done = function ()
|
||||
spawn.with_line_callback(
|
||||
"find" .. starting_points .. " -type f -path '*/new/*';",
|
||||
{ stdout = function (filename) new = new + 1 end,
|
||||
output_done = function () callback{ new, cur } end })
|
||||
end })
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(mdir_all, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(mdir_all)
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
-- {{{ Grab environment
|
||||
local tonumber = tonumber
|
||||
local setmetatable = setmetatable
|
||||
local math = { floor = math.floor }
|
||||
local io = { popen = io.popen }
|
||||
local string = {
|
||||
match = string.match,
|
||||
gmatch = string.gmatch,
|
||||
find = string.find
|
||||
}
|
||||
|
||||
local helpers = require("vicious.helpers")
|
||||
local spawn = require("vicious.spawn")
|
||||
-- }}}
|
||||
|
||||
-- Mem: provides RAM and Swap usage statistics
|
||||
|
@ -12,74 +17,103 @@ local mem_freebsd = {}
|
|||
|
||||
|
||||
-- {{{ Memory widget type
|
||||
local function worker(format)
|
||||
local pagesize = tonumber(helpers.sysctl("hw.pagesize"))
|
||||
local vm_stats = helpers.sysctl_table("vm.stats.vm")
|
||||
local _mem = { buf = {}, total = nil }
|
||||
function mem_freebsd.async(format, warg, callback)
|
||||
helpers.sysctl_async({ "hw.pagesize",
|
||||
"vm.stats.vm",
|
||||
"vm.swap_total",
|
||||
"vm.swap_enabled" },
|
||||
function(ret)
|
||||
|
||||
-- Get memory space in bytes
|
||||
_mem.total = tonumber(vm_stats.v_page_count) * pagesize
|
||||
_mem.buf.free = tonumber(vm_stats.v_free_count) * pagesize
|
||||
_mem.buf.laundry = tonumber(vm_stats.v_laundry_count) * pagesize
|
||||
_mem.buf.cache = tonumber(vm_stats.v_cache_count) * pagesize
|
||||
_mem.buf.wired = tonumber(vm_stats.v_wire_count) * pagesize
|
||||
local pgsz = tonumber(ret["hw.pagesize"])
|
||||
local _mem = { buf = {}, total = nil }
|
||||
|
||||
-- Rework into megabytes
|
||||
_mem.total = math.floor(_mem.total/1048576)
|
||||
_mem.buf.free = math.floor(_mem.buf.free/1048576)
|
||||
_mem.buf.laundry = math.floor(_mem.buf.laundry/1048576)
|
||||
_mem.buf.cache = math.floor(_mem.buf.cache/1048576)
|
||||
_mem.buf.wired = math.floor(_mem.buf.wired/1048576)
|
||||
-- Get memory space in bytes
|
||||
_mem.total = tonumber(ret["vm.stats.vm.v_page_count"]) * pgsz
|
||||
_mem.buf.free = tonumber(ret["vm.stats.vm.v_free_count"]) * pgsz
|
||||
_mem.buf.laundry = tonumber(ret["vm.stats.vm.v_laundry_count"]) * pgsz
|
||||
_mem.buf.cache = tonumber(ret["vm.stats.vm.v_cache_count"]) * pgsz
|
||||
_mem.buf.wired = tonumber(ret["vm.stats.vm.v_wire_count"]) * pgsz
|
||||
|
||||
-- Calculate memory percentage
|
||||
_mem.free = _mem.buf.free + _mem.buf.cache
|
||||
-- used memory basically consists of active+inactive+wired
|
||||
_mem.inuse = _mem.total - _mem.free
|
||||
_mem.notfreeable = _mem.inuse - _mem.buf.laundry
|
||||
_mem.wire = _mem.buf.wired
|
||||
-- Rework into megabytes
|
||||
_mem.total = math.floor(_mem.total/1048576)
|
||||
_mem.buf.free = math.floor(_mem.buf.free/1048576)
|
||||
_mem.buf.laundry = math.floor(_mem.buf.laundry/1048576)
|
||||
_mem.buf.cache = math.floor(_mem.buf.cache/1048576)
|
||||
_mem.buf.wired = math.floor(_mem.buf.wired/1048576)
|
||||
|
||||
_mem.usep = math.floor(_mem.inuse / _mem.total * 100)
|
||||
_mem.wirep = math.floor(_mem.wire / _mem.total * 100)
|
||||
_mem.notfreeablep = math.floor(_mem.notfreeable / _mem.total * 100)
|
||||
-- Calculate memory percentage
|
||||
_mem.free = _mem.buf.free + _mem.buf.cache
|
||||
-- used memory basically consists of active+inactive+wired
|
||||
_mem.inuse = _mem.total - _mem.free
|
||||
_mem.notfreeable = _mem.inuse - _mem.buf.laundry
|
||||
_mem.wire = _mem.buf.wired
|
||||
|
||||
-- Get swap states
|
||||
local vm_swap_total = tonumber(helpers.sysctl("vm.swap_total"))
|
||||
local vm_swap_enabled = tonumber(helpers.sysctl("vm.swap_enabled"))
|
||||
local _swp = { buf = {}, total = nil }
|
||||
_mem.usep = math.floor(_mem.inuse / _mem.total * 100)
|
||||
_mem.wirep = math.floor(_mem.wire / _mem.total * 100)
|
||||
_mem.notfreeablep = math.floor(_mem.notfreeable / _mem.total * 100)
|
||||
|
||||
if vm_swap_enabled == 1 and vm_swap_total > 0 then
|
||||
-- Initialise variables
|
||||
_swp.usep = 0
|
||||
_swp.inuse = 0
|
||||
_swp.total = 0
|
||||
_swp.buf.free = 0
|
||||
-- Get swap states
|
||||
local vm_swap_total = tonumber(ret["vm.swap_total"])
|
||||
local vm_swap_enabled = tonumber(ret["vm.swap_enabled"])
|
||||
local _swp = { buf = {}, total = nil }
|
||||
|
||||
-- Read output of swapinfo in Mbytes
|
||||
local f = io.popen("swapinfo -m")
|
||||
-- Skip first line (table header)
|
||||
f:read("*line")
|
||||
-- Read content and sum up
|
||||
for line in f:lines() do
|
||||
local ltotal, lused, lfree = string.match(line, "%s+([%d]+)%s+([%d]+)%s+([%d]+)")
|
||||
-- Add swap space in Mbytes
|
||||
_swp.total = _swp.total + tonumber(ltotal)
|
||||
_swp.inuse = _swp.inuse + tonumber(lused)
|
||||
_swp.buf.free = _swp.buf.free + tonumber(lfree)
|
||||
if vm_swap_enabled == 1 and vm_swap_total > 0 then
|
||||
-- Initialise variables
|
||||
_swp.usep = 0
|
||||
_swp.inuse = 0
|
||||
_swp.total = 0
|
||||
_swp.buf.free = 0
|
||||
|
||||
-- Read output of swapinfo in Mbytes (from async function call)
|
||||
-- Read content and sum up
|
||||
spawn.with_line_callback("swapinfo -m", {
|
||||
stdout = function(line)
|
||||
if not string.find(line, "Device") then
|
||||
local ltotal, lused, lfree = string.match(
|
||||
line, "%s+([%d]+)%s+([%d]+)%s+([%d]+)")
|
||||
-- Add swap space in Mbytes
|
||||
_swp.total = _swp.total + tonumber(ltotal)
|
||||
_swp.inuse = _swp.inuse + tonumber(lused)
|
||||
_swp.buf.free = _swp.buf.free + tonumber(lfree)
|
||||
end
|
||||
end,
|
||||
output_done = function()
|
||||
print(_swp.inuse, _swp.total)
|
||||
_swp.usep = math.floor(_swp.inuse / _swp.total * 100)
|
||||
callback({ _mem.usep,
|
||||
_mem.inuse,
|
||||
_mem.total,
|
||||
_mem.free,
|
||||
_swp.usep,
|
||||
_swp.inuse,
|
||||
_swp.total,
|
||||
_swp.buf.free,
|
||||
_mem.wirep,
|
||||
_mem.wire,
|
||||
_mem.notfreeablep,
|
||||
_mem.notfreeable })
|
||||
end
|
||||
})
|
||||
else
|
||||
_swp.usep = -1
|
||||
_swp.inuse = -1
|
||||
_swp.total = -1
|
||||
_swp.buf.free = -1
|
||||
callback({ _mem.usep,
|
||||
_mem.inuse,
|
||||
_mem.total,
|
||||
_mem.free,
|
||||
_swp.usep,
|
||||
_swp.inuse,
|
||||
_swp.total,
|
||||
_swp.buf.free,
|
||||
_mem.wirep,
|
||||
_mem.wire,
|
||||
_mem.notfreeablep,
|
||||
_mem.notfreeable })
|
||||
end
|
||||
f:close()
|
||||
|
||||
-- Calculate percentage
|
||||
_swp.usep = math.floor(_swp.inuse / _swp.total * 100)
|
||||
else
|
||||
_swp.usep = -1
|
||||
_swp.inuse = -1
|
||||
_swp.total = -1
|
||||
_swp.buf.free = -1
|
||||
end
|
||||
|
||||
return { _mem.usep, _mem.inuse, _mem.total, _mem.free,
|
||||
_swp.usep, _swp.inuse, _swp.total, _swp.buf.free,
|
||||
_mem.wirep, _mem.wire, _mem.notfreeablep, _mem.notfreeable }
|
||||
end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(mem_freebsd, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(mem_freebsd)
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
|
||||
-- {{{ Grab environment
|
||||
local tonumber = tonumber
|
||||
local io = { popen = io.popen }
|
||||
local setmetatable = setmetatable
|
||||
local string = { gmatch = string.gmatch }
|
||||
local helpers = require("vicious.helpers")
|
||||
local math = { floor = math.floor }
|
||||
local type = type
|
||||
|
||||
local helpers = require"vicious.helpers"
|
||||
local spawn = require"vicious.spawn"
|
||||
-- }}}
|
||||
|
||||
|
||||
|
@ -25,7 +25,7 @@ end
|
|||
-- }}}
|
||||
|
||||
-- {{{ Format playing progress
|
||||
function format_progress(elapsed, duration)
|
||||
local function format_progress(elapsed, duration)
|
||||
local em, es = math.floor(elapsed / 60), math.floor(elapsed % 60)
|
||||
local dm, ds = math.floor(duration / 60), math.floor(duration % 60)
|
||||
|
||||
|
@ -33,18 +33,22 @@ function format_progress(elapsed, duration)
|
|||
return ("%d:%02d"):format(em, es), ("%d:%02d"):format(dm, ds)
|
||||
elseif dm < 60 then
|
||||
return ("%02d:%02d"):format(em, es), ("%02d:%02d"):format(dm, ds)
|
||||
elseif dm < 600 then
|
||||
return ("%d:%02d:%02d"):format(math.floor(em / 60), math.floor(em % 60), es),
|
||||
("%d:%02d:%02d"):format(math.floor(dm / 60), math.floor(dm % 60), ds)
|
||||
end
|
||||
|
||||
local eh, dh = math.floor(em / 60), math.floor(dm / 60)
|
||||
em, dm = math.floor(em % 60), math.floor(dm % 60)
|
||||
if dm < 600 then
|
||||
return ("%d:%02d:%02d"):format(eh, em, es),
|
||||
("%d:%02d:%02d"):format(dh, dm, ds)
|
||||
else
|
||||
return ("%02d:%02d:%02d"):format(math.floor(em / 60), math.floor(em % 60), es),
|
||||
("%02d:%02d:%02d"):format(math.floor(dm / 60), math.floor(dm % 60), ds)
|
||||
return ("%02d:%02d:%02d"):format(eh, em, es),
|
||||
("%02d:%02d:%02d"):format(dh, dm, ds)
|
||||
end
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- {{{ Format playing progress (percentage)
|
||||
function format_progress_percentage(elapsed, duration)
|
||||
local function format_progress_percentage(elapsed, duration)
|
||||
if duration > 0 then
|
||||
local percentage = math.floor((elapsed / duration) * 100 + 0.5)
|
||||
return ("%d%%"):format(percentage)
|
||||
|
@ -55,7 +59,7 @@ end
|
|||
-- }}}
|
||||
|
||||
-- {{{ MPD widget type
|
||||
local function worker(format, warg)
|
||||
function mpd_all.async(format, warg, callback)
|
||||
-- Fallback values
|
||||
local mpd_state = {
|
||||
["{volume}"] = 0,
|
||||
|
@ -81,36 +85,34 @@ local function worker(format, warg)
|
|||
warg and (warg.port or warg[3]) or "6600")
|
||||
|
||||
-- Get data from MPD server
|
||||
local f = io.popen(query .. "|" .. connect)
|
||||
for line in f:lines() do
|
||||
for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
|
||||
local key = "{" .. k .. "}"
|
||||
if k == "volume" or k == "bitrate" or
|
||||
k == "elapsed" or k == "duration" then
|
||||
mpd_state[key] = v and tonumber(v)
|
||||
elseif k == "repeat" or k == "random" then
|
||||
mpd_state[key] = cbool(v)
|
||||
elseif k == "state" then
|
||||
mpd_state[key] = helpers.capitalize(v)
|
||||
elseif k == "Artist" or k == "Title" or
|
||||
--k == "Name" or k == "file" or
|
||||
k == "Album" or k == "Genre" then
|
||||
mpd_state[key] = v
|
||||
spawn.with_line_callback_with_shell(query .. "|" .. connect, {
|
||||
stdout = function (line)
|
||||
for k, v in line:gmatch"([%w]+):[%s](.*)$" do
|
||||
local key = "{" .. k .. "}"
|
||||
if k == "volume" or k == "bitrate" or
|
||||
k == "elapsed" or k == "duration" then
|
||||
mpd_state[key] = v and tonumber(v)
|
||||
elseif k == "repeat" or k == "random" then
|
||||
mpd_state[key] = cbool(v)
|
||||
elseif k == "state" then
|
||||
mpd_state[key] = helpers.capitalize(v)
|
||||
elseif k == "Artist" or k == "Title" or
|
||||
--k == "Name" or k == "file" or
|
||||
k == "Album" or k == "Genre" then
|
||||
mpd_state[key] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
|
||||
-- Formatted elapsed and duration
|
||||
mpd_state["{Elapsed}"], mpd_state["{Duration}"] = format_progress(
|
||||
mpd_state["{elapsed}"], mpd_state["{duration}"])
|
||||
|
||||
-- Formatted playing progress percentage
|
||||
mpd_state["{Progress}"] = format_progress_percentage(
|
||||
mpd_state["{elapsed}"], mpd_state["{duration}"])
|
||||
|
||||
return mpd_state
|
||||
end,
|
||||
output_done = function ()
|
||||
-- Formatted elapsed and duration
|
||||
mpd_state["{Elapsed}"], mpd_state["{Duration}"] = format_progress(
|
||||
mpd_state["{elapsed}"], mpd_state["{duration}"])
|
||||
-- Formatted playing progress percentage
|
||||
mpd_state["{Progress}"] = format_progress_percentage(
|
||||
mpd_state["{elapsed}"], mpd_state["{duration}"])
|
||||
callback(mpd_state)
|
||||
end })
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(mpd_all, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(mpd_all)
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
-- {{{ Grab environment
|
||||
local tonumber = tonumber
|
||||
local os = { time = os.time }
|
||||
local setmetatable = setmetatable
|
||||
local string = {
|
||||
match = string.match,
|
||||
gmatch = string.gmatch
|
||||
}
|
||||
|
||||
local helpers = require("vicious.helpers")
|
||||
local io = { popen = io.popen }
|
||||
local string = { match = string.match }
|
||||
local spawn = require("vicious.spawn")
|
||||
-- }}}
|
||||
|
||||
|
||||
|
@ -21,28 +24,25 @@ local unit = { ["b"] = 1, ["kb"] = 1024,
|
|||
}
|
||||
|
||||
-- {{{ Net widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
local function parse(stdout, stderr, exitreason, exitcode)
|
||||
|
||||
local args = {}
|
||||
local buffer = nil
|
||||
local f = io.popen("netstat -n -b -I " .. helpers.shellquote(warg))
|
||||
local now = os.time()
|
||||
|
||||
for line in f:lines() do
|
||||
|
||||
for line in string.gmatch(stdout, "[^\n]+") do
|
||||
if not (line:find("<Link") or line:find("Name")) then -- skipping missleading lines
|
||||
local split = { line:match(("([^%s]*)%s*"):rep(12)) }
|
||||
|
||||
if buffer == nil then
|
||||
buffer = { tonumber(split[8]), tonumber(split[11]) } -- recv (field 8) and send (field 11)
|
||||
else
|
||||
buffer = { buffer[1] + tonumber(split[8]), buffer[2] + tonumber(split[11]) }
|
||||
buffer = { buffer[1] + tonumber(split[8]),
|
||||
buffer[2] + tonumber(split[11]) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
f:close()
|
||||
|
||||
if buffer == nil then
|
||||
args["{carrier}"] = 0
|
||||
helpers.uformat(args, "rx", 0, unit)
|
||||
|
@ -67,7 +67,7 @@ local function worker(format, warg)
|
|||
helpers.uformat(args, "down", down, unit)
|
||||
helpers.uformat(args, "up", up, unit)
|
||||
end
|
||||
|
||||
|
||||
nets["time"] = now
|
||||
|
||||
-- Store totals
|
||||
|
@ -78,6 +78,12 @@ local function worker(format, warg)
|
|||
return args
|
||||
|
||||
end
|
||||
|
||||
function net_freebsd.async(format, warg, callback)
|
||||
if not warg then return callback{} end
|
||||
spawn.easy_async("netstat -n -b -I " .. helpers.shellquote(warg),
|
||||
function (...) callback(parse(...)) end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(net_freebsd, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(net_freebsd)
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
---------------------------------------------------
|
||||
-- Licensed under the GNU General Public License v2
|
||||
-- * (c) 2010, Adrian C. <anrxc@sysphere.org>
|
||||
---------------------------------------------------
|
||||
|
||||
-- {{{ Grab environment
|
||||
local los = { getenv = os.getenv }
|
||||
local string = { match = string.match }
|
||||
local helpers = require("vicious.helpers")
|
||||
local spawn = require("vicious.spawn")
|
||||
-- }}}
|
||||
|
||||
|
||||
-- OS: provides operating system information
|
||||
-- vicious.widgets.os
|
||||
local os_bsd = {}
|
||||
|
||||
|
||||
-- {{{ Operating system widget type
|
||||
local function parse(stdout, stderr, exitreason, exitcode)
|
||||
local system = {
|
||||
["ostype"] = "N/A",
|
||||
["hostname"] = "N/A",
|
||||
["osrelease"] = "N/A",
|
||||
["username"] = "N/A",
|
||||
["entropy"] = "N/A",
|
||||
["entropy_p"] = "N/A"
|
||||
}
|
||||
|
||||
-- BSD manual page: uname(1)
|
||||
system["ostype"], system["hostname"], system["osrelease"] =
|
||||
string.match(stdout, "([%w]+)[%s]([%w%p]+)[%s]([%w%p]+)")
|
||||
|
||||
-- Get user from the environment
|
||||
system["username"] = los.getenv("USER")
|
||||
|
||||
return {system["ostype"], system["osrelease"], system["username"],
|
||||
system["hostname"], system["entropy"], system["entropy_p"]}
|
||||
end
|
||||
|
||||
function os_bsd.async(format, warg, callback)
|
||||
spawn.easy_async("uname -snr",
|
||||
function (...) callback(parse(...)) end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return helpers.setasyncall(os_bsd)
|
|
@ -6,21 +6,18 @@
|
|||
-- {{{ Grab environment
|
||||
local pairs = pairs
|
||||
local tonumber = tonumber
|
||||
local io = { popen = io.popen }
|
||||
local math = { ceil = math.ceil }
|
||||
local los = { getenv = os.getenv }
|
||||
local setmetatable = setmetatable
|
||||
local helpers = require("vicious.helpers")
|
||||
local string = {
|
||||
gsub = string.gsub,
|
||||
match = string.match
|
||||
}
|
||||
local string = { gsub = string.gsub }
|
||||
|
||||
local helpers = require"vicious.helpers"
|
||||
-- }}}
|
||||
|
||||
|
||||
-- OS: provides operating system information
|
||||
-- vicious.widgets.os
|
||||
local os_all = {}
|
||||
local os_linux = {}
|
||||
|
||||
|
||||
-- {{{ Operating system widget type
|
||||
|
@ -36,22 +33,12 @@ local function worker(format)
|
|||
|
||||
-- Linux manual page: uname(2)
|
||||
local kernel = helpers.pathtotable("/proc/sys/kernel")
|
||||
for k, v in pairs(system) do
|
||||
for k, _ in pairs(system) do
|
||||
if kernel[k] then
|
||||
system[k] = string.gsub(kernel[k], "[%s]*$", "")
|
||||
end
|
||||
end
|
||||
|
||||
-- BSD manual page: uname(1)
|
||||
if system["ostype"] == "N/A" then
|
||||
local f = io.popen("uname -snr")
|
||||
local uname = f:read("*line")
|
||||
f:close()
|
||||
|
||||
system["ostype"], system["hostname"], system["osrelease"] =
|
||||
string.match(uname, "([%w]+)[%s]([%w%p]+)[%s]([%w%p]+)")
|
||||
end
|
||||
|
||||
-- Linux manual page: random(4)
|
||||
if kernel.random then
|
||||
-- Linux 2.6 default entropy pool is 4096-bits
|
||||
|
@ -70,4 +57,5 @@ local function worker(format)
|
|||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(os_all, { __call = function(_, ...) return worker(...) end })
|
||||
return setmetatable(os_linux,
|
||||
{ __call = function(_, ...) return worker(...) end })
|
|
@ -1,6 +1,7 @@
|
|||
-- {{{ Grab environment
|
||||
local setmetatable = setmetatable
|
||||
local string = { match = string.match }
|
||||
local type = type
|
||||
|
||||
local helpers = require("vicious.helpers")
|
||||
-- }}}
|
||||
|
||||
|
@ -9,26 +10,25 @@ local helpers = require("vicious.helpers")
|
|||
-- vicious.widgets.thermal
|
||||
local thermal_freebsd = {}
|
||||
|
||||
|
||||
-- {{{ Thermal widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
function thermal_freebsd.async(format, warg, callback)
|
||||
if not warg then return callback{} end
|
||||
if type(warg) ~= "table" then warg = { warg } end
|
||||
|
||||
local thermals = {}
|
||||
helpers.sysctl_async(warg, function(ret)
|
||||
local thermals = {}
|
||||
|
||||
for i=1, #warg do
|
||||
local output = helpers.sysctl(warg[i])
|
||||
|
||||
if not output then
|
||||
thermals[i] = -1
|
||||
else
|
||||
thermals[i] = string.match(output, "[%d]+")
|
||||
for i=1,#warg do
|
||||
if ret[warg[i]] ~= nil then
|
||||
thermals[i] = string.match(ret[warg[i]], "[%d]+")
|
||||
else
|
||||
thermals[i] = "N/A"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return thermals
|
||||
callback(thermals)
|
||||
end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(thermal_freebsd, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(thermal_freebsd)
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
-- {{{ Grab environment
|
||||
local tonumber = tonumber
|
||||
local setmetatable = setmetatable
|
||||
local math = { floor = math.floor }
|
||||
local string = { match = string.match }
|
||||
local helpers = require("vicious.helpers")
|
||||
local os = { time = os.time }
|
||||
|
||||
local helpers = require("vicious.helpers")
|
||||
-- }}}
|
||||
|
||||
|
||||
|
@ -14,17 +13,23 @@ local uptime_freebsd = {}
|
|||
|
||||
|
||||
-- {{{ Uptime widget type
|
||||
local function worker(format)
|
||||
local l1, l5, l15 = string.match(helpers.sysctl("vm.loadavg"), "{ ([%d]+%.[%d]+) ([%d]+%.[%d]+) ([%d]+%.[%d]+) }")
|
||||
local up_t = os.time() - tonumber(string.match(helpers.sysctl("kern.boottime"), "sec = ([%d]+)"))
|
||||
function uptime_freebsd.async(format, warg, callback)
|
||||
helpers.sysctl_async(
|
||||
{ "vm.loadavg", "kern.boottime" },
|
||||
function(ret)
|
||||
local l1, l5, l15 = ret["vm.loadavg"]:match(
|
||||
"{ ([%d]+%.[%d]+) ([%d]+%.[%d]+) ([%d]+%.[%d]+) }")
|
||||
local up_t = os.time() - tonumber(
|
||||
ret["kern.boottime"]:match"sec = ([%d]+)")
|
||||
|
||||
-- Get system uptime
|
||||
local up_d = math.floor(up_t / (3600 * 24))
|
||||
local up_h = math.floor((up_t % (3600 * 24)) / 3600)
|
||||
local up_m = math.floor(((up_t % (3600 * 24)) % 3600) / 60)
|
||||
-- Get system uptime
|
||||
local up_d = math.floor(up_t / (3600 * 24))
|
||||
local up_h = math.floor((up_t % (3600 * 24)) / 3600)
|
||||
local up_m = math.floor(((up_t % (3600 * 24)) % 3600) / 60)
|
||||
|
||||
return {up_d, up_h, up_m, l1, l5, l15}
|
||||
return callback({ up_d, up_h, up_m, l1, l5, l15 })
|
||||
end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(uptime_freebsd, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(uptime_freebsd)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
-- {{{ Grab environment
|
||||
local tonumber = tonumber
|
||||
local io = { popen = io.popen }
|
||||
local setmetatable = setmetatable
|
||||
local string = { match = string.match }
|
||||
local helpers = require("vicious.helpers")
|
||||
local spawn = require("vicious.spawn")
|
||||
-- }}}
|
||||
|
||||
|
||||
|
@ -13,26 +12,20 @@ local volume_freebsd = {}
|
|||
|
||||
|
||||
-- {{{ Volume widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
local STATE = { on = '🔉', off = '🔈' }
|
||||
|
||||
local mixer_state = { "♫", "♩" }
|
||||
|
||||
-- Get mixer control contents
|
||||
f = io.popen("mixer -s " .. helpers.shellquote(warg))
|
||||
local mixer = f:read()
|
||||
f:close()
|
||||
|
||||
-- Capture mixer control state: [5%] ... ... [on]
|
||||
local voll, volr = string.match(mixer, "([%d]+):([%d]+)$")
|
||||
|
||||
if voll == "0" and volr == "0" then
|
||||
return {0, 0, mixer_state[2]}
|
||||
else
|
||||
return {voll, volr, mixer_state[1]}
|
||||
end
|
||||
local function parse(stdout, stderr, exitreason, exitcode)
|
||||
-- Capture mixer control state, e.g. 42 : 42
|
||||
local voll, volr = string.match(stdout, "([%d]+):([%d]+)\n$")
|
||||
if voll == "0" and volr == "0" then return { 0, 0, STATE.off } end
|
||||
return { tonumber(voll), tonumber(volr), STATE.on }
|
||||
end
|
||||
|
||||
function volume_freebsd.async(format, warg, callback)
|
||||
if not warg then return callback{} end
|
||||
spawn.easy_async("mixer " .. helpers.shellquote(warg),
|
||||
function (...) callback(parse(...)) end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(volume_freebsd, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(volume_freebsd)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
---------------------------------------------------
|
||||
|
||||
-- {{{ Grab environment
|
||||
local type = type
|
||||
local tonumber = tonumber
|
||||
local string = { match = string.match }
|
||||
local table = { concat = table.concat }
|
||||
|
|
|
@ -4,89 +4,50 @@
|
|||
---------------------------------------------------
|
||||
|
||||
-- {{{ Grab environment
|
||||
local type = type
|
||||
local tonumber = tonumber
|
||||
local math = { ceil = math.ceil }
|
||||
local setmetatable = setmetatable
|
||||
local helpers = require("vicious.helpers")
|
||||
local io = {
|
||||
open = io.open,
|
||||
popen = io.popen
|
||||
}
|
||||
local string = {
|
||||
find = string.find,
|
||||
match = string.match
|
||||
}
|
||||
local math = { floor = math.floor }
|
||||
|
||||
local helpers = require"vicious.helpers"
|
||||
local spawn = require"vicious.spawn"
|
||||
-- }}}
|
||||
|
||||
|
||||
-- Wifi: provides wireless information for a requested interface
|
||||
-- Wifi: provides wireless information for a requested interface using iwconfig
|
||||
-- vicious.widgets.wifi
|
||||
local wifi_linux = {}
|
||||
|
||||
|
||||
-- {{{ Variable definitions
|
||||
local iwconfig = "iwconfig"
|
||||
local iwcpaths = { "/sbin", "/usr/sbin", "/usr/local/sbin", "/usr/bin" }
|
||||
-- }}}
|
||||
|
||||
|
||||
-- {{{ Wireless widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
|
||||
-- Default values
|
||||
local winfo = {
|
||||
["{ssid}"] = "N/A",
|
||||
["{mode}"] = "N/A",
|
||||
["{chan}"] = 0,
|
||||
["{rate}"] = 0,
|
||||
["{link}"] = 0,
|
||||
["{linp}"] = 0,
|
||||
["{sign}"] = 0
|
||||
}
|
||||
|
||||
-- Sbin paths aren't in user PATH, search for the binary
|
||||
if iwconfig == "iwconfig" then
|
||||
for _, p in ipairs(iwcpaths) do
|
||||
local f = io.open(p .. "/iwconfig", "rb")
|
||||
if f then
|
||||
iwconfig = p .. "/iwconfig"
|
||||
f:close()
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Get data from iwconfig where available
|
||||
local f = io.popen(iwconfig .." ".. helpers.shellquote(warg) .. " 2>&1")
|
||||
local iw = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- iwconfig wasn't found, isn't executable, or non-wireless interface
|
||||
if iw == nil or string.find(iw, "No such device") then
|
||||
return winfo
|
||||
end
|
||||
|
||||
-- Output differs from system to system, some stats can be
|
||||
-- separated by =, and not all drivers report all stats
|
||||
-- SSID can have almost anything in it
|
||||
winfo["{ssid}"] = string.match(iw, 'ESSID[=:]"(.-)"') or winfo["{ssid}"]
|
||||
winfo["{mode}"] = -- Modes are simple, but also match the "-" in Ad-Hoc
|
||||
string.match(iw, "Mode[=:]([%w%-]*)") or winfo["{mode}"]
|
||||
winfo["{chan}"] = -- Channels are plain digits
|
||||
tonumber(string.match(iw, "Channel[=:]([%d]+)") or winfo["{chan}"])
|
||||
winfo["{rate}"] = -- Bitrate can start with a space, we don't want to display Mb/s
|
||||
tonumber(string.match(iw, "Bit Rate[=:]([%s]?[%d%.]*)") or winfo["{rate}"])
|
||||
winfo["{link}"] = -- Link quality can contain a slash (32/70), match only the first number
|
||||
tonumber(string.match(iw, "Link Quality[=:]([%d]+)") or winfo["{link}"])
|
||||
winfo["{sign}"] = -- Signal level can be a negative value, don't display decibel notation
|
||||
tonumber(string.match(iw, "Signal level[=:]([%-]?[%d]+)") or winfo["{sign}"])
|
||||
|
||||
-- Link quality percentage if quality was available
|
||||
if winfo["{link}"] ~= 0 then winfo["{linp}"] = math.ceil(winfo["{link}"] / 0.7) end
|
||||
|
||||
local function parser(stdout, stderr, exitreason, exitcode)
|
||||
local winfo = {}
|
||||
-- Output differs from system to system, stats can be separated by
|
||||
-- either = or :. Some stats may not be supported by driver.
|
||||
-- SSID can have almost anything in it.
|
||||
winfo["{ssid}"] = stdout:match'ESSID[=:]"(.-)"' or "N/A"
|
||||
-- Modes are simple, but also match the "-" in Ad-Hoc
|
||||
winfo["{mode}"] = stdout:match"Mode[=:]([%w%-]+)" or "N/A"
|
||||
winfo["{chan}"] = tonumber(stdout:match"Channel[=:](%d+)" or 0)
|
||||
winfo["{rate}"] = -- Bitrate without unit (Mb/s)
|
||||
tonumber(stdout:match"Bit Rate[=:]%s?([%d%.]+)" or 0)
|
||||
winfo["{freq}"] = -- Frequency in MHz (is output always in GHz?)
|
||||
tonumber(stdout:match"Frequency[=:]%s?([%d%.]+)" or 0) * 1000
|
||||
winfo["{txpw}"] = -- Transmission power in dBm
|
||||
tonumber(stdout:match"Tx%-Power[=:](%d+)" or 0)
|
||||
winfo["{link}"] = -- Link quality over 70
|
||||
tonumber(stdout:match"Link Quality[=:](%d+)" or 0)
|
||||
winfo["{linp}"] = -- Link quality percentage if quality was available
|
||||
winfo["{link}"] ~= 0 and math.floor(winfo["{link}"]/0.7 + 0.5) or 0
|
||||
-- Signal level without unit (dBm), can be negative value
|
||||
winfo["{sign}"] = tonumber(stdout:match"Signal level[=:](%-?%d+)" or 0)
|
||||
return winfo
|
||||
end
|
||||
|
||||
function wifi_linux.async(format, warg, callback)
|
||||
if type(warg) ~= "string" then return callback{} end
|
||||
spawn.easy_async_with_shell(
|
||||
"PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin iwconfig " .. warg,
|
||||
function (...) callback(parser(...)) end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(wifi_linux, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(wifi_linux)
|
||||
|
|
|
@ -4,65 +4,58 @@
|
|||
---------------------------------------------------
|
||||
|
||||
-- {{{ Grab environment
|
||||
local type = type
|
||||
local tonumber = tonumber
|
||||
local setmetatable = setmetatable
|
||||
|
||||
local helpers = require("vicious.helpers")
|
||||
local io = {
|
||||
open = io.open,
|
||||
popen = io.popen
|
||||
}
|
||||
local string = {
|
||||
find = string.find,
|
||||
match = string.match
|
||||
}
|
||||
local spawn = require("vicious.spawn")
|
||||
-- }}}
|
||||
|
||||
|
||||
-- Wifiiw: provides wireless information for a requested interface using iw instead of deprecated iwconfig
|
||||
-- Wifiiw: provides wireless information for a requested interface
|
||||
-- using iw instead of deprecated iwconfig
|
||||
-- vicious.widgets.wifiiw
|
||||
local wifiiw_linux = {}
|
||||
|
||||
local LINK = "PATH=$PATH:/sbin/:/usr/sbin:/usr/local/sbin iw dev %s link"
|
||||
local INFO = "PATH=$PATH:/sbin/:/usr/sbin:/usr/local/sbin iw dev %s info"
|
||||
|
||||
-- {{{ Wireless widget type
|
||||
local function worker(format, warg)
|
||||
if not warg then return end
|
||||
|
||||
-- Default values
|
||||
function wifiiw_linux.async(format, warg, callback)
|
||||
if type(warg) ~= "string" then return callback{} end
|
||||
local winfo = {}
|
||||
|
||||
-- Get data from iw where available
|
||||
local f = io.popen("export PATH=$PATH:/sbin/:/usr/sbin:/usr/local/sbin;" ..
|
||||
"iw dev ".. helpers.shellquote(tostring(warg)) .. " link 2>&1;" ..
|
||||
"iw dev ".. helpers.shellquote(tostring(warg)) .. " info 2>&1")
|
||||
local iwresult = f:read("*all")
|
||||
f:close()
|
||||
|
||||
-- iw wasn't found, isn't executable, or non-wireless interface
|
||||
if iwresult == nil or string.find(iwresult, "No such device") then
|
||||
return winfo
|
||||
local function parse_link(stdout)
|
||||
winfo["{bssid}"] = stdout:match"Connected to ([%x:]*)" or "N/A"
|
||||
winfo["{ssid}"] = stdout:match"SSID: ([^\n]*)" or "N/A"
|
||||
winfo["{freq}"] = tonumber(stdout:match"freq: (%d+)" or 0)
|
||||
winfo["{sign}"] = -- Signal level can be negative; w/o unit (dBm)
|
||||
tonumber(stdout:match"signal: (%-?%d+)" or 0)
|
||||
winfo["{linp}"] = -- Link Quality (-100dBm->0%, -50dBm->100%)
|
||||
winfo["{sign}"] ~= 0 and 200 + winfo["{sign}"]*2 or 0
|
||||
winfo["{rate}"] = -- Transmission rate, without unit (Mb/s)
|
||||
tonumber(stdout:match"tx bitrate: ([%d%.]+)" or 0)
|
||||
end
|
||||
-- string match is simple in most cases, because iw uses a new line for every info
|
||||
winfo["{bssid}"] = -- BSSID has hex digits and colons
|
||||
string.match(iwresult, "Connected to ([%x:]*)") or "N/A"
|
||||
winfo["{ssid}"] = -- SSID can have almost anything in it until new line
|
||||
string.match(iwresult, "SSID: ([^\n]*)") or "N/A"
|
||||
winfo["{mode}"] = -- everything after 'type ' until new line
|
||||
string.match(iwresult, "type ([^\n]*)") or "N/A"
|
||||
winfo["{chan}"] = -- Channels are plain digits
|
||||
tonumber(string.match(iwresult, "channel ([%d]+)") or 0)
|
||||
winfo["{rate}"] = -- We don't want to display Mb/s
|
||||
tonumber(string.match(iwresult, "tx bitrate: ([%d%.]*)") or 0)
|
||||
winfo["{freq}"] = -- Frequency are plain digits
|
||||
tonumber(string.match(iwresult, "freq: ([%d]+)") or 0)
|
||||
winfo["{sign}"] = -- Signal level can be a negative value, don't display decibel notation
|
||||
tonumber(string.match(iwresult, "signal: (%-[%d]+)") or 0)
|
||||
winfo["{linp}"] = -- Link Quality using the Windows definition (-50dBm->100%, -100dBm->0%)
|
||||
(winfo["{sign}"] ~= 0 and 100 - ((winfo["{sign}"] * -2) - 100) or 0)
|
||||
winfo["{txpw}"] = -- TX Power can be a negative value, don't display decibel notation
|
||||
tonumber(string.match(iwresult, "txpower ([%-]?[%d]+)") or 0)
|
||||
|
||||
return winfo
|
||||
local function parse_info(stdout)
|
||||
winfo["{mode}"] = stdout:match"type ([^\n]*)" or "N/A"
|
||||
winfo["{chan}"] = tonumber(stdout:match"channel (%d+)" or 0)
|
||||
-- Transmission power, without unit (dBm)
|
||||
winfo["{txpw}"] = tonumber(stdout:match"txpower (%-?%d+)" or 0)
|
||||
end
|
||||
|
||||
spawn.easy_async_with_shell(
|
||||
LINK:format(warg),
|
||||
function (std_out, std_err, exit_reason, exit_code)
|
||||
parse_link(std_out)
|
||||
spawn.easy_async_with_shell(
|
||||
INFO:format(warg),
|
||||
function (stdout, stderr, exitreason, exitcode)
|
||||
parse_info(stdout)
|
||||
callback(winfo)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
-- }}}
|
||||
|
||||
return setmetatable(wifiiw_linux, { __call = function(_, ...) return worker(...) end })
|
||||
return helpers.setasyncall(wifiiw_linux)
|
||||
|
|
Loading…
Reference in New Issue