Large update to configs

This commit is contained in:
natemaia 2018-05-18 20:36:34 -07:00
parent 5252fc5cd3
commit 7ddcb2d563
65 changed files with 1596 additions and 1633 deletions

View File

@ -1,44 +1,44 @@
<?xml encoding="UTF-8" version="1.0"?> <?xml encoding="UTF-8" version="1.0"?>
<actions> <actions>
<action> <action>
<icon>utilities-terminal</icon> <icon>utilities-terminal</icon>
<name>Open in Terminal</name> <name>Open in Terminal</name>
<unique-id>1499240572835265-1</unique-id> <unique-id>1499240572835265-1</unique-id>
<command>exo-open --launch TerminalEmulator %f</command> <command>exo-open --launch TerminalEmulator %f</command>
<description></description> <description>Open terminal emulator in current directory</description>
<patterns>*</patterns> <patterns>*</patterns>
<startup-notify/> <startup-notify/>
<directories/> <directories/>
</action> </action>
<action> <action>
<icon>document-open</icon> <icon>document-open</icon>
<name>Open as Root</name> <name>Open as Root</name>
<unique-id>1498523394840843-5</unique-id> <unique-id>1498523394840843-5</unique-id>
<command>gksu thunar %f</command> <command>pkexec thunar %f</command>
<description></description> <description>Open a root instance of thunar</description>
<patterns>*</patterns> <patterns>*</patterns>
<directories/> <directories/>
</action> </action>
<action> <action>
<icon>archive-extract</icon> <icon>archive-extract</icon>
<name>Extract Here</name> <name>Extract</name>
<unique-id>1500573442438340-2</unique-id> <unique-id>1500573442438340-2</unique-id>
<command>file-roller -h %N</command> <command>file-roller -h %N</command>
<description></description> <description>Extract selected archive</description>
<patterns>*</patterns> <patterns>*</patterns>
<startup-notify/> <startup-notify/>
<other-files/> <other-files/>
</action> </action>
<action> <action>
<icon>archive-insert</icon> <icon>archive-insert</icon>
<name>Archive</name> <name>Archive</name>
<unique-id>1500573639456321-3</unique-id> <unique-id>1500573639456321-3</unique-id>
<command>file-roller -d %F</command> <command>file-roller -d %F</command>
<description>Archive selected items</description> <description>Archive selected items</description>
<patterns>*</patterns> <patterns>*</patterns>
<directories/> <directories/>
<image-files/> <image-files/>
<other-files/> <other-files/>
<text-files/> <text-files/>
</action> </action>
</actions> </actions>

View File

@ -92,9 +92,9 @@ function lookup_icon(arg)
end end
end end
-- lowest priority fallbacks -- lowest priority fallbacks
table.insert(icon_path, '/usr/share/pixmaps/') table.insert(icon_path, '/usr/share/pixmaps/')
table.insert(icon_path, '/usr/share/icons/') table.insert(icon_path, '/usr/share/icons/')
table.insert(icon_path, '/usr/share/app-install/icons/') table.insert(icon_path, '/usr/share/app-install/icons/')
for i, directory in ipairs(icon_path) do for i, directory in ipairs(icon_path) do
if (arg.icon:find('.+%.png') or arg.icon:find('.+%.xpm')) and file_exists(directory .. arg.icon) then if (arg.icon:find('.+%.png') or arg.icon:find('.+%.xpm')) and file_exists(directory .. arg.icon) then

View File

@ -9,9 +9,9 @@ local io = { open = io.open }
local setmetatable = setmetatable local setmetatable = setmetatable
local helpers = require("vicious.helpers") local helpers = require("vicious.helpers")
local string = { local string = {
sub = string.sub, sub = string.sub,
match = string.match, match = string.match,
gmatch = string.gmatch gmatch = string.gmatch
} }
-- }}} -- }}}
@ -23,56 +23,56 @@ local ati = {}
-- {{{ Define variables -- {{{ Define variables
local _units = { clock = { ["khz"] = 1, ["mhz"] = 1000 }, local _units = { clock = { ["khz"] = 1, ["mhz"] = 1000 },
voltage = { ["v"] = 1, ["mv"] = 1000 } } voltage = { ["v"] = 1, ["mv"] = 1000 } }
local _reps = { local _reps = {
["sclk"] = { name = "engine_clock", units = _units.clock, mul = 10 }, ["sclk"] = { name = "engine_clock", units = _units.clock, mul = 10 },
["mclk"] = { name = "memory_clock", units = _units.clock, mul = 10 }, ["mclk"] = { name = "memory_clock", units = _units.clock, mul = 10 },
["vddc"] = { name = "voltage", units = _units.voltage }, ["vddc"] = { name = "voltage", units = _units.voltage },
["voltage"] = { name = "voltage", units = _units.voltage }, ["voltage"] = { name = "voltage", units = _units.voltage },
["current engine clock"] = { name = "engine_clock", units = _units.clock }, ["current engine clock"] = { name = "engine_clock", units = _units.clock },
["current memory clock"] = { name = "memory_clock", units = _units.clock } ["current memory clock"] = { name = "memory_clock", units = _units.clock }
} }
-- }}} -- }}}
-- {{{ ATI widget type -- {{{ ATI widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
local pm = helpers.pathtotable("/sys/class/drm/"..warg.."/device") local pm = helpers.pathtotable("/sys/class/drm/"..warg.."/device")
local _data = {} local _data = {}
-- Get power info -- Get power info
_data["{method}"] = _data["{method}"] =
pm.power_method and string.sub(pm.power_method, 1, -2) or "N/A" pm.power_method and string.sub(pm.power_method, 1, -2) or "N/A"
_data["{dpm_state}"] = _data["{dpm_state}"] =
pm.power_dpm_state and string.sub(pm.power_dpm_state, 1, -2) or "N/A" pm.power_dpm_state and string.sub(pm.power_dpm_state, 1, -2) or "N/A"
_data["{dpm_perf_level}"] = _data["{dpm_perf_level}"] =
pm.power_dpm_force_performance_level and pm.power_dpm_force_performance_level and
string.sub(pm.power_dpm_force_performance_level, 1, -2) or "N/A" string.sub(pm.power_dpm_force_performance_level, 1, -2) or "N/A"
_data["{profile}"] = _data["{profile}"] =
pm.power_profile and string.sub(pm.power_profile, 1, -2) or "N/A" pm.power_profile and string.sub(pm.power_profile, 1, -2) or "N/A"
local f = io.open("/sys/kernel/debug/dri/64/radeon_pm_info", "r") local f = io.open("/sys/kernel/debug/dri/64/radeon_pm_info", "r")
if f then -- Get ATI info from the debug filesystem if f then -- Get ATI info from the debug filesystem
for line in f:lines() do for line in f:lines() do
for k, unit in string.gmatch(line, "(%a+[%a%s]*):[%s]+([%d]+)") do for k, unit in string.gmatch(line, "(%a+[%a%s]*):[%s]+([%d]+)") do
unit = tonumber(unit) unit = tonumber(unit)
_data["{dpm_power_level}"] = -- DPM active? _data["{dpm_power_level}"] = -- DPM active?
tonumber(string.match(line, "power level ([%d])")) or "N/A" tonumber(string.match(line, "power level ([%d])")) or "N/A"
if _reps[k] then if _reps[k] then
for u, v in pairs(_reps[k].units) do for u, v in pairs(_reps[k].units) do
_data["{".._reps[k].name.." "..u.."}"] = _data["{".._reps[k].name.." "..u.."}"] =
(unit * (_reps[k].mul or 1)) / v (unit * (_reps[k].mul or 1)) / v
end end
end
end
end end
end f:close()
end end
f:close()
end
return _data return _data
end end
-- }}} -- }}}

View File

@ -19,33 +19,33 @@ local batacpi = {}
-- {{{ Battery widget type -- {{{ Battery widget type
local function worker(format) local function worker(format)
local battery_info = {} local battery_info = {}
local battery_state = { local battery_state = {
["full"] = "", ["full"] = "",
["unknown"] = "", ["unknown"] = "",
["charged"] = "", ["charged"] = "",
["charging"] = "+", ["charging"] = "+",
["discharging"] = "-" ["discharging"] = "-"
} }
-- Get data from acpitool -- Get data from acpitool
local f = io.popen("acpitool -b") local f = io.popen("acpitool -b")
for line in f:lines() do for line in f:lines() do
-- Check if the battery is present -- Check if the battery is present
if string.match(line, "^[%s]+Battery.*") then if string.match(line, "^[%s]+Battery.*") then
-- Store state and charge information -- Store state and charge information
table.insert(battery_info, (battery_state[string.match(line, "([%a]*),") or "unknown"])) table.insert(battery_info, (battery_state[string.match(line, "([%a]*),") or "unknown"]))
table.insert(battery_info, (tonumber(string.match(line, "([%d]?[%d]?[%d])%.")) or 0)) table.insert(battery_info, (tonumber(string.match(line, "([%d]?[%d]?[%d])%.")) or 0))
-- Store remaining time information -- Store remaining time information
table.insert(battery_info, (string.match(line, "%%,%s(.*)") or "N/A")) table.insert(battery_info, (string.match(line, "%%,%s(.*)") or "N/A"))
else else
return {battery_state["unknown"], 0, "N/A"} return {battery_state["unknown"], 0, "N/A"}
end
end end
end f:close()
f:close()
return battery_info return battery_info
end end
-- }}} -- }}}

View File

@ -8,13 +8,13 @@ local tonumber = tonumber
local io = { open = io.open } local io = { open = io.open }
local setmetatable = setmetatable local setmetatable = setmetatable
local math = { local math = {
min = math.min, min = math.min,
floor = math.floor floor = math.floor
} }
local string = { local string = {
find = string.find, find = string.find,
match = string.match, match = string.match,
format = string.format format = string.format
} }
-- }}} -- }}}
@ -26,53 +26,53 @@ local batpmu = {}
-- {{{ Battery widget type -- {{{ Battery widget type
local function worker(format, batid) local function worker(format, batid)
local battery_state = { local battery_state = {
["full"] = "", ["full"] = "",
["unknown"] = "", ["unknown"] = "",
["00000013"] = "+", ["00000013"] = "+",
["00000011"] = "-" ["00000011"] = "-"
} }
-- Get /proc/pmu/battery* state -- Get /proc/pmu/battery* state
local f = io.open("/proc/pmu/" .. batid) local f = io.open("/proc/pmu/" .. batid)
-- Handler for incompetent users -- Handler for incompetent users
if not f then return {battery_state["unknown"], 0, "N/A"} end if not f then return {battery_state["unknown"], 0, "N/A"} end
local statefile = f:read("*all") local statefile = f:read("*all")
f:close() f:close()
-- Get /proc/pmu/info data -- Get /proc/pmu/info data
local f = io.open("/proc/pmu/info") local f = io.open("/proc/pmu/info")
local infofile = f:read("*all") local infofile = f:read("*all")
f:close() f:close()
-- Check if the battery is present -- Check if the battery is present
if infofile == nil or string.find(infofile, "Battery count[%s]+:[%s]0") then if infofile == nil or string.find(infofile, "Battery count[%s]+:[%s]0") then
return {battery_state["unknown"], 0, "N/A"} return {battery_state["unknown"], 0, "N/A"}
end end
-- Get capacity and charge information -- Get capacity and charge information
local capacity = string.match(statefile, "max_charge[%s]+:[%s]([%d]+).*") local capacity = string.match(statefile, "max_charge[%s]+:[%s]([%d]+).*")
local remaining = string.match(statefile, "charge[%s]+:[%s]([%d]+).*") local remaining = string.match(statefile, "charge[%s]+:[%s]([%d]+).*")
-- Calculate percentage -- Calculate percentage
local percent = math.min(math.floor(remaining / capacity * 100), 100) local percent = math.min(math.floor(remaining / capacity * 100), 100)
-- Get timer information -- Get timer information
local timer = string.match(statefile, "time rem%.[%s]+:[%s]([%d]+).*") local timer = string.match(statefile, "time rem%.[%s]+:[%s]([%d]+).*")
if timer == "0" then return {battery_state["full"], percent, "N/A"} end if timer == "0" then return {battery_state["full"], percent, "N/A"} end
-- Get state information -- Get state information
local state = string.match(statefile, "flags[%s]+:[%s]([%d]+).*") local state = string.match(statefile, "flags[%s]+:[%s]([%d]+).*")
local state = battery_state[state] or battery_state["unknown"] local state = battery_state[state] or battery_state["unknown"]
-- Calculate remaining (charging or discharging) time -- Calculate remaining (charging or discharging) time
local hoursleft = math.floor(tonumber(timer) / 3600) local hoursleft = math.floor(tonumber(timer) / 3600)
local minutesleft = math.floor((tonumber(timer) / 60) % 60) local minutesleft = math.floor((tonumber(timer) / 60) % 60)
local time = string.format("%02d:%02d", hoursleft, minutesleft) local time = string.format("%02d:%02d", hoursleft, minutesleft)
return {state, percent, time} return {state, percent, time}
end end
-- }}} -- }}}

View File

@ -8,13 +8,13 @@ local tonumber = tonumber
local io = { open = io.open } local io = { open = io.open }
local setmetatable = setmetatable local setmetatable = setmetatable
local math = { local math = {
min = math.min, min = math.min,
floor = math.floor floor = math.floor
} }
local string = { local string = {
find = string.find, find = string.find,
match = string.match, match = string.match,
format = string.format format = string.format
} }
-- }}} -- }}}
@ -26,60 +26,60 @@ local batproc = {}
-- {{{ Battery widget type -- {{{ Battery widget type
local function worker(format, batid) local function worker(format, batid)
local battery_state = { local battery_state = {
["full"] = "", ["full"] = "",
["unknown"] = "", ["unknown"] = "",
["charged"] = "", ["charged"] = "",
["charging"] = "+", ["charging"] = "+",
["discharging"] = "-" ["discharging"] = "-"
} }
-- Get /proc/acpi/battery info -- Get /proc/acpi/battery info
local f = io.open("/proc/acpi/battery/"..batid.."/info") local f = io.open("/proc/acpi/battery/"..batid.."/info")
-- Handler for incompetent users -- Handler for incompetent users
if not f then return {battery_state["unknown"], 0, "N/A"} end if not f then return {battery_state["unknown"], 0, "N/A"} end
local infofile = f:read("*all") local infofile = f:read("*all")
f:close() f:close()
-- Check if the battery is present -- Check if the battery is present
if infofile == nil or string.find(infofile, "present:[%s]+no") then if infofile == nil or string.find(infofile, "present:[%s]+no") then
return {battery_state["unknown"], 0, "N/A"} return {battery_state["unknown"], 0, "N/A"}
end end
-- Get capacity information -- Get capacity information
local capacity = string.match(infofile, "last full capacity:[%s]+([%d]+).*") local capacity = string.match(infofile, "last full capacity:[%s]+([%d]+).*")
-- Get /proc/acpi/battery state -- Get /proc/acpi/battery state
local f = io.open("/proc/acpi/battery/"..batid.."/state") local f = io.open("/proc/acpi/battery/"..batid.."/state")
local statefile = f:read("*all") local statefile = f:read("*all")
f:close() f:close()
-- Get state information -- Get state information
local state = string.match(statefile, "charging state:[%s]+([%a]+).*") local state = string.match(statefile, "charging state:[%s]+([%a]+).*")
local state = battery_state[state] or battery_state["unknown"] local state = battery_state[state] or battery_state["unknown"]
-- Get charge information -- Get charge information
local rate = string.match(statefile, "present rate:[%s]+([%d]+).*") local rate = string.match(statefile, "present rate:[%s]+([%d]+).*")
local remaining = string.match(statefile, "remaining capacity:[%s]+([%d]+).*") local remaining = string.match(statefile, "remaining capacity:[%s]+([%d]+).*")
-- Calculate percentage (but work around broken BAT/ACPI implementations) -- Calculate 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)
-- Calculate remaining (charging or discharging) time -- Calculate remaining (charging or discharging) time
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, "N/A"} return {state, percent, "N/A"}
end end
local hoursleft = math.floor(timeleft) local hoursleft = math.floor(timeleft)
local minutesleft = math.floor((timeleft - hoursleft) * 60 ) local minutesleft = math.floor((timeleft - hoursleft) * 60 )
local time = string.format("%02d:%02d", hoursleft, minutesleft) local time = string.format("%02d:%02d", hoursleft, minutesleft)
return {state, percent, time} return {state, percent, time}
end end
-- }}} -- }}}

View File

@ -25,48 +25,48 @@ local unit = { ["s"] = 1, ["kb"] = 2, ["mb"] = 2048 }
-- {{{ Disk I/O widget type -- {{{ Disk I/O widget type
local function worker(format, disk) local function worker(format, disk)
if not disk then return end if not disk then return end
local disk_lines = { [disk] = {} } local disk_lines = { [disk] = {} }
local disk_stats = helpers.pathtotable("/sys/block/" .. disk) local disk_stats = helpers.pathtotable("/sys/block/" .. disk)
if disk_stats.stat then if disk_stats.stat then
local match = string.gmatch(disk_stats.stat, "[%s]+([%d]+)") local match = string.gmatch(disk_stats.stat, "[%s]+([%d]+)")
for i = 1, 11 do -- Store disk stats for i = 1, 11 do -- Store disk stats
table.insert(disk_lines[disk], match()) table.insert(disk_lines[disk], match())
end
end end
end
-- Ensure tables are initialized correctly -- Ensure tables are initialized correctly
local diff_total = { [disk] = {} } local diff_total = { [disk] = {} }
if not disk_total[disk] then if not disk_total[disk] then
disk_usage[disk] = {} disk_usage[disk] = {}
disk_total[disk] = {} disk_total[disk] = {}
while #disk_total[disk] < #disk_lines[disk] do while #disk_total[disk] < #disk_lines[disk] do
table.insert(disk_total[disk], 0) table.insert(disk_total[disk], 0)
end
end end
end
for i, v in ipairs(disk_lines[disk]) do for i, v in ipairs(disk_lines[disk]) do
-- Diskstats are absolute, substract our last reading -- Diskstats are absolute, substract our last reading
diff_total[disk][i] = v - disk_total[disk][i] diff_total[disk][i] = v - disk_total[disk][i]
-- Store totals -- Store totals
disk_total[disk][i] = v disk_total[disk][i] = v
end end
-- Calculate and store I/O -- Calculate and store I/O
helpers.uformat(disk_usage[disk], "read", diff_total[disk][3], unit) helpers.uformat(disk_usage[disk], "read", diff_total[disk][3], unit)
helpers.uformat(disk_usage[disk], "write", diff_total[disk][7], unit) helpers.uformat(disk_usage[disk], "write", diff_total[disk][7], unit)
helpers.uformat(disk_usage[disk], "total", diff_total[disk][7] + diff_total[disk][3], unit) helpers.uformat(disk_usage[disk], "total", diff_total[disk][7] + diff_total[disk][3], unit)
-- Store I/O scheduler -- Store I/O scheduler
if disk_stats.queue and disk_stats.queue.scheduler then if disk_stats.queue and disk_stats.queue.scheduler then
disk_usage[disk]["{sched}"] = string.gmatch(disk_stats.queue.scheduler, "%[([%a]+)%]") disk_usage[disk]["{sched}"] = string.gmatch(disk_stats.queue.scheduler, "%[([%a]+)%]")
end end
return disk_usage[disk] return disk_usage[disk]
end end
-- }}} -- }}}

View File

@ -20,29 +20,29 @@ local mpc = {}
-- {{{ MPC widget type -- {{{ MPC widget type
local function worker(format, warg) local function worker(format, warg)
-- Get data from mpd -- Get data from mpd
local f = io.popen("mpc") local f = io.popen("mpc")
local np = f:read("*line") local np = f:read("*line")
f:close() f:close()
-- Not installed, -- Not installed,
if np == nil or -- off or stoppped. if np == nil or -- off or stoppped.
(string.find(np, "MPD_HOST") or string.find(np, "volume:")) (string.find(np, "MPD_HOST") or string.find(np, "volume:"))
then then
return {"Stopped"} return {"Stopped"}
end end
-- Check if we should scroll, or maybe truncate -- Check if we should scroll, or maybe truncate
if warg then if warg then
if type(warg) == "table" then if type(warg) == "table" then
np = helpers.scroll(np, warg[1], warg[2]) np = helpers.scroll(np, warg[1], warg[2])
else else
np = helpers.truncate(np, warg) np = helpers.truncate(np, warg)
end
end
return {helpers.escape(np)}
end end
end -- }}}
return {helpers.escape(np)} return setmetatable(mpc, { __call = function(_, ...) return worker(...) end })
end
-- }}}
return setmetatable(mpc, { __call = function(_, ...) return worker(...) end })

View File

@ -25,114 +25,114 @@ local net = {}
local nets = {} local nets = {}
-- Variable definitions -- Variable definitions
local unit = { ["b"] = 1, ["kb"] = 1024, local unit = { ["b"] = 1, ["kb"] = 1024,
["mb"] = 1024^2, ["gb"] = 1024^3 ["mb"] = 1024^2, ["gb"] = 1024^3
} }
-- {{{ Net widget type -- {{{ Net widget type
local function worker(format, tignorelist) local function worker(format, tignorelist)
local args = {} local args = {}
local tignore = {} local tignore = {}
local total_rx = 0 local total_rx = 0
local total_tx = 0 local total_tx = 0
local any_up = 0 local any_up = 0
if not tignorelist then if not tignorelist then
tignorelist = {"lo", "wmaster0"} tignorelist = {"lo", "wmaster0"}
end end
for k, i in pairs(tignorelist) do for k, i in pairs(tignorelist) do
tignore[i] = true tignore[i] = true
end
-- Get NET stats
for line in io.lines("/proc/net/dev") do
-- Match wmaster0 as well as rt0 (multiple leading spaces)
local name = string.match(line, "^[%s]?[%s]?[%s]?[%s]?([%w]+):")
if name ~= nil then
-- Received bytes, first value after the name
local recv = tonumber(string.match(line, ":[%s]*([%d]+)"))
-- Transmited bytes, 7 fields from end of the line
local send = tonumber(string.match(line,
"([%d]+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d$"))
if not tignore[name] then
total_rx = total_rx + recv
total_tx = total_tx + send
end
helpers.uformat(args, name .. " rx", recv, unit)
helpers.uformat(args, name .. " tx", send, unit)
if nets[name] == nil then
-- Default values on the first run
nets[name] = {}
helpers.uformat(args, name .. " down", 0, unit)
helpers.uformat(args, name .. " up", 0, unit)
args["{"..name.." carrier}"] = 0
nets[name].time = os.time()
else -- Net stats are absolute, substract our last reading
local interval = os.time() - nets[name].time > 0 and
os.time() - nets[name].time or 1
nets[name].time = os.time()
local down = (recv - nets[name][1]) / interval
local up = (send - nets[name][2]) / interval
helpers.uformat(args, name .. " down", down, unit)
helpers.uformat(args, name .. " up", up, unit)
-- Carrier detection
sysnet = helpers.pathtotable("/sys/class/net/" .. name)
if sysnet.carrier then
ccarrier = tonumber(sysnet.carrier)
args["{"..name.." carrier}"] = ccarrier
if ccarrier ~= 0 and not tignore[name] then
any_up = 1
end
else
args["{"..name.." carrier}"] = 0
end
end
-- Store totals
nets[name][1] = recv
nets[name][2] = send
end end
end
helpers.uformat(args, "total rx", total_rx, unit) -- Get NET stats
helpers.uformat(args, "total tx", total_tx, unit) for line in io.lines("/proc/net/dev") do
-- Match wmaster0 as well as rt0 (multiple leading spaces)
local name = string.match(line, "^[%s]?[%s]?[%s]?[%s]?([%w]+):")
if name ~= nil then
-- Received bytes, first value after the name
local recv = tonumber(string.match(line, ":[%s]*([%d]+)"))
-- Transmited bytes, 7 fields from end of the line
local send = tonumber(string.match(line,
"([%d]+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d$"))
if nets["total"] == nil then if not tignore[name] then
-- Default values on the first run total_rx = total_rx + recv
nets["total"] = {} total_tx = total_tx + send
end
helpers.uformat(args, "total down", 0, unit) helpers.uformat(args, name .. " rx", recv, unit)
helpers.uformat(args, "total up", 0, unit) helpers.uformat(args, name .. " tx", send, unit)
args["{total carrier}"] = 0
nets["total"].time = os.time() if nets[name] == nil then
else -- Net stats are absolute, substract our last reading -- Default values on the first run
local interval = os.time() - nets["total"].time > 0 and nets[name] = {}
os.time() - nets["total"].time or 1
nets["total"].time = os.time()
local down = (total_rx - nets["total"][1]) / interval helpers.uformat(args, name .. " down", 0, unit)
local up = (total_tx - nets["total"][2]) / interval helpers.uformat(args, name .. " up", 0, unit)
args["{"..name.." carrier}"] = 0
helpers.uformat(args, "total down", down, unit) nets[name].time = os.time()
helpers.uformat(args, "total up", up, unit) else -- Net stats are absolute, substract our last reading
args["{total carrier}"] = any_up local interval = os.time() - nets[name].time > 0 and
end os.time() - nets[name].time or 1
nets[name].time = os.time()
-- Store totals local down = (recv - nets[name][1]) / interval
nets["total"][1] = total_rx local up = (send - nets[name][2]) / interval
nets["total"][2] = total_tx
return args helpers.uformat(args, name .. " down", down, unit)
helpers.uformat(args, name .. " up", up, unit)
-- Carrier detection
sysnet = helpers.pathtotable("/sys/class/net/" .. name)
if sysnet.carrier then
ccarrier = tonumber(sysnet.carrier)
args["{"..name.." carrier}"] = ccarrier
if ccarrier ~= 0 and not tignore[name] then
any_up = 1
end
else
args["{"..name.." carrier}"] = 0
end
end
-- Store totals
nets[name][1] = recv
nets[name][2] = send
end
end
helpers.uformat(args, "total rx", total_rx, unit)
helpers.uformat(args, "total tx", total_tx, unit)
if nets["total"] == nil then
-- Default values on the first run
nets["total"] = {}
helpers.uformat(args, "total down", 0, unit)
helpers.uformat(args, "total up", 0, unit)
args["{total carrier}"] = 0
nets["total"].time = os.time()
else -- Net stats are absolute, substract our last reading
local interval = os.time() - nets["total"].time > 0 and
os.time() - nets["total"].time or 1
nets["total"].time = os.time()
local down = (total_rx - nets["total"][1]) / interval
local up = (total_tx - nets["total"][2]) / interval
helpers.uformat(args, "total down", down, unit)
helpers.uformat(args, "total up", up, unit)
args["{total carrier}"] = any_up
end
-- Store totals
nets["total"][1] = total_rx
nets["total"][2] = total_tx
return args
end end
-- }}} -- }}}

View File

@ -17,18 +17,18 @@ local netcfg = {}
-- {{{ Netcfg widget type -- {{{ Netcfg widget type
local function worker(format) local function worker(format)
-- Initialize counters -- Initialize counters
local profiles = {} local profiles = {}
local f = io.popen("ls -1 /var/run/network/profiles") local f = io.popen("ls -1 /var/run/network/profiles")
for line in f:lines() do for line in f:lines() do
if line ~= nil then if line ~= nil then
table.insert(profiles, line) table.insert(profiles, line)
end
end end
end f:close()
f:close()
return profiles return profiles
end end
-- }}} -- }}}

View File

@ -18,24 +18,24 @@ local nvsmi = {}
-- {{{ GPU Information widget type -- {{{ GPU Information widget type
local function worker(format, warg) local function worker(format, warg)
-- Fallback to querying first device -- Fallback to querying first device
if not warg then warg = "0" end if not warg then warg = "0" end
-- Get data from smi -- Get data from smi
-- * Todo: support more; MEMORY,UTILIZATION,ECC,POWER,CLOCK,COMPUTE,PIDS,PERFORMANCE -- * Todo: support more; MEMORY,UTILIZATION,ECC,POWER,CLOCK,COMPUTE,PIDS,PERFORMANCE
local f = io.popen("nvidia-smi -q -d TEMPERATURE -i " .. warg) local f = io.popen("nvidia-smi -q -d TEMPERATURE -i " .. warg)
local smi = f:read("*all") local smi = f:read("*all")
f:close() f:close()
-- Not installed -- Not installed
if smi == nil then return {0} end if smi == nil then return {0} end
-- Get temperature information -- Get temperature information
local _thermal = string.match(smi, "Gpu[%s]+:[%s]([%d]+)[%s]C") local _thermal = string.match(smi, "Gpu[%s]+:[%s]([%d]+)[%s]C")
-- Handle devices without data -- Handle devices without data
if _thermal == nil then return {0} end if _thermal == nil then return {0} end
return {tonumber(_thermal)} return {tonumber(_thermal)}
end end
-- }}} -- }}}

View File

@ -9,8 +9,8 @@ local io = { popen = io.popen }
local setmetatable = setmetatable local setmetatable = setmetatable
local string = { match = string.match } local string = { match = string.match }
local math = { local math = {
ceil = math.ceil, ceil = math.ceil,
floor = math.floor floor = math.floor
} }
-- }}} -- }}}
@ -23,71 +23,71 @@ local openweather = {}
-- Initialize function tables -- Initialize function tables
local _wdirs = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "N" } local _wdirs = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "N" }
local _wdata = { local _wdata = {
["{city}"] = "N/A", ["{city}"] = "N/A",
["{wind deg}"] = "N/A", ["{wind deg}"] = "N/A",
["{wind aim}"] = "N/A", ["{wind aim}"] = "N/A",
["{wind mps}"] = "N/A", ["{wind mps}"] = "N/A",
["{wind kmh}"] = "N/A", ["{wind kmh}"] = "N/A",
["{sky}"] = "N/A", ["{sky}"] = "N/A",
["{weather}"] = "N/A", ["{weather}"] = "N/A",
["{temp c}"] = "N/A", ["{temp c}"] = "N/A",
["{humid}"] = "N/A", ["{humid}"] = "N/A",
["{press}"] = "N/A" ["{press}"] = "N/A"
} }
-- {{{ Openweather widget type -- {{{ Openweather widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
-- Get weather forceast using the city ID code, from: -- Get weather forceast using the city ID code, from:
-- * OpenWeatherMap.org -- * OpenWeatherMap.org
local openweather = "http://api.openweathermap.org/data/2.5/weather?id="..warg.."&mode=json&units=metric" local openweather = "http://api.openweathermap.org/data/2.5/weather?id="..warg.."&mode=json&units=metric"
local f = io.popen("curl --connect-timeout 1 -fsm 3 '"..openweather.."'") local f = io.popen("curl --connect-timeout 1 -fsm 3 '"..openweather.."'")
local ws = f:read("*all") local ws = f:read("*all")
f:close() f:close()
-- Check if there was a timeout or a problem with the station -- Check if there was a timeout or a problem with the station
if ws == nil then return _wdata end if ws == nil then return _wdata end
_wdata["{city}"] = -- City name _wdata["{city}"] = -- City name
string.match(ws, '"name":"([%a%s%-]+)"') or _wdata["{city}"] string.match(ws, '"name":"([%a%s%-]+)"') or _wdata["{city}"]
_wdata["{wind deg}"] = -- Wind degrees _wdata["{wind deg}"] = -- Wind degrees
string.match(ws, '"deg":([%d]+)') or _wdata["{wind deg}"] string.match(ws, '"deg":([%d]+)') or _wdata["{wind deg}"]
_wdata["{wind mps}"] = -- Wind speed in meters per second _wdata["{wind mps}"] = -- Wind speed in meters per second
string.match(ws, '"speed":([%d%.]+)') or _wdata["{wind mps}"] string.match(ws, '"speed":([%d%.]+)') or _wdata["{wind mps}"]
_wdata["{sky}"] = -- Sky conditions _wdata["{sky}"] = -- Sky conditions
string.match(ws, '"main":"([%a]+)"') or _wdata["{sky}"] string.match(ws, '"main":"([%a]+)"') or _wdata["{sky}"]
_wdata["{weather}"] = -- Weather description _wdata["{weather}"] = -- Weather description
string.match(ws, '"description":"([%a%s]+)"') or _wdata["{weather}"] string.match(ws, '"description":"([%a%s]+)"') or _wdata["{weather}"]
_wdata["{temp c}"] = -- Temperature in celsius _wdata["{temp c}"] = -- Temperature in celsius
string.match(ws, '"temp":([%-]?[%d%.]+)') or _wdata["{temp c}"] string.match(ws, '"temp":([%-]?[%d%.]+)') or _wdata["{temp c}"]
_wdata["{humid}"] = -- Relative humidity in percent _wdata["{humid}"] = -- Relative humidity in percent
string.match(ws, '"humidity":([%d]+)') or _wdata["{humid}"] string.match(ws, '"humidity":([%d]+)') or _wdata["{humid}"]
_wdata["{press}"] = -- Pressure in hPa _wdata["{press}"] = -- Pressure in hPa
string.match(ws, '"pressure":([%d%.]+)') or _wdata["{press}"] string.match(ws, '"pressure":([%d%.]+)') or _wdata["{press}"]
-- Wind speed in km/h -- Wind speed in km/h
if _wdata["{wind mps}"] ~= "N/A" then if _wdata["{wind mps}"] ~= "N/A" then
_wdata["{wind mps}"] = math.floor(tonumber(_wdata["{wind mps}"]) + .5) _wdata["{wind mps}"] = math.floor(tonumber(_wdata["{wind mps}"]) + .5)
_wdata["{wind kmh}"] = math.ceil(_wdata["{wind mps}"] * 3.6) _wdata["{wind kmh}"] = math.ceil(_wdata["{wind mps}"] * 3.6)
end -- Temperature in °C end -- Temperature in °C
if _wdata["{temp c}"] ~= "N/A" then if _wdata["{temp c}"] ~= "N/A" then
_wdata["{temp c}"] = math.floor(tonumber(_wdata["{temp c}"]) + .5) _wdata["{temp c}"] = math.floor(tonumber(_wdata["{temp c}"]) + .5)
end -- Calculate wind direction end -- Calculate wind direction
if _wdata["{wind deg}"] ~= "N/A" then if _wdata["{wind deg}"] ~= "N/A" then
_wdata["{wind deg}"] = tonumber(_wdata["{wind deg}"]) _wdata["{wind deg}"] = tonumber(_wdata["{wind deg}"])
-- Lua tables start at [1] -- Lua tables start at [1]
if (_wdata["{wind deg}"] / 45)%1 == 0 then if (_wdata["{wind deg}"] / 45)%1 == 0 then
_wdata["{wind aim}"] = _wdirs[_wdata["{wind deg}"] / 45 + 1] _wdata["{wind aim}"] = _wdirs[_wdata["{wind deg}"] / 45 + 1]
else else
_wdata["{wind aim}"] = _wdata["{wind aim}"] =
_wdirs[math.ceil(_wdata["{wind deg}"] / 45) + 1].. _wdirs[math.ceil(_wdata["{wind deg}"] / 45) + 1]..
_wdirs[math.floor(_wdata["{wind deg}"] / 45) + 1] _wdirs[math.floor(_wdata["{wind deg}"] / 45) + 1]
end
end end
end
return _wdata return _wdata
end end
-- }}} -- }}}

View File

@ -18,36 +18,36 @@ local ossvol = {}
-- {{{ Volume widget type -- {{{ Volume widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
local mixer_state = { local mixer_state = {
["on"] = "", -- "", ["on"] = "", -- "",
["off"] = "" -- "M" ["off"] = "" -- "M"
} }
-- Get mixer control contents -- Get mixer control contents
local f = io.popen("ossmix -c") local f = io.popen("ossmix -c")
local mixer = f:read("*all") local mixer = f:read("*all")
f:close() f:close()
-- Capture mixer control state -- Capture mixer control state
local volu = tonumber(string.match(mixer, warg .. "[%s]([%d%.]+)"))/0.25 local volu = tonumber(string.match(mixer, warg .. "[%s]([%d%.]+)"))/0.25
local mute = string.match(mixer, "vol%.mute[%s]([%a]+)") local mute = string.match(mixer, "vol%.mute[%s]([%a]+)")
-- Handle mixers without data -- Handle mixers without data
if volu == nil then if volu == nil then
return {0, mixer_state["off"]} return {0, mixer_state["off"]}
end end
-- Handle mixers without mute -- Handle mixers without mute
if mute == "OFF" and volu == "0" if mute == "OFF" and volu == "0"
-- Handle mixers that are muted -- Handle mixers that are muted
or mute == "ON" then or mute == "ON" then
mute = mixer_state["off"] mute = mixer_state["off"]
else else
mute = mixer_state["on"] mute = mixer_state["on"]
end end
return {volu, mute} return {volu, mute}
end end
-- }}} -- }}}

View File

@ -25,30 +25,30 @@ local pop = {}
-- {{{ POP3 count widget type -- {{{ POP3 count widget type
local function worker(format, warg) local function worker(format, warg)
if not sock_avail or (not warg or #warg ~= 4) then if not sock_avail or (not warg or #warg ~= 4) then
return {"N/A"} return {"N/A"}
end end
local host, port = warg[1], tonumber(warg[2]) local host, port = warg[1], tonumber(warg[2])
local user, pass = warg[3], warg[4] local user, pass = warg[3], warg[4]
local client = socket.tcp() local client = socket.tcp()
client:settimeout(3) client:settimeout(3)
client:connect(host, port) client:connect(host, port)
client:receive("*l") client:receive("*l")
client:send("USER " .. user .. "\r\n") client:send("USER " .. user .. "\r\n")
client:receive("*l") client:receive("*l")
client:send("PASS " .. pass .. "\r\n") client:send("PASS " .. pass .. "\r\n")
client:receive("*l") client:receive("*l")
client:send("STAT" .. "\r\n") client:send("STAT" .. "\r\n")
local response = client:receive("*l") local response = client:receive("*l")
client:close() client:close()
if response:find("%+OK") then if response:find("%+OK") then
response = response:match("%+OK (%d+)") response = response:match("%+OK (%d+)")
end end
return {response} return {response}
end end
-- }}} -- }}}

View File

@ -20,48 +20,48 @@ local rss = {}
-- {{{ RSS widget type -- {{{ RSS widget type
local function worker(format, input) local function worker(format, input)
-- input: * feed - feed url -- input: * feed - feed url
-- * object - entity to look for (typically: 'item') -- * object - entity to look for (typically: 'item')
-- * fields - fields to read (example: 'link', 'title', 'description') -- * fields - fields to read (example: 'link', 'title', 'description')
-- output: * count - number of entities found -- output: * count - number of entities found
-- * one table for each field, containing wanted values -- * one table for each field, containing wanted values
local feed = input.feed local feed = input.feed
local object = input.object local object = input.object
local fields = input.fields local fields = input.fields
-- Initialise tables -- Initialise tables
local out = {} local out = {}
for _, v in pairs(fields) do
out[v] = {}
end
-- Initialise variables
local ob = nil
local i,j,k = 1, 1, 0
local curl = "curl -A 'Mozilla/4.0' -fsm 5 --connect-timeout 3 "
-- Get the feed
local f = io.popen(curl .. '"' .. feed .. '"')
local feed = f:read("*all")
f:close()
while true do
i, j, ob = feed.find(feed, "<" .. object .. ">(.-)</" .. object .. ">", i)
if not ob then break end
for _, v in pairs(fields) do for _, v in pairs(fields) do
out[v][k] = ob:match("<" .. v .. ">(.*)</" .. v .. ">") out[v] = {}
end end
k = k+1 -- Initialise variables
i = j+1 local ob = nil
end local i,j,k = 1, 1, 0
local curl = "curl -A 'Mozilla/4.0' -fsm 5 --connect-timeout 3 "
-- Update the entity count -- Get the feed
out.count = k local f = io.popen(curl .. '"' .. feed .. '"')
local feed = f:read("*all")
f:close()
return out while true do
i, j, ob = feed.find(feed, "<" .. object .. ">(.-)</" .. object .. ">", i)
if not ob then break end
for _, v in pairs(fields) do
out[v][k] = ob:match("<" .. v .. ">(.*)</" .. v .. ">")
end
k = k+1
i = j+1
end
-- Update the entity count
out.count = k
return out
end end
-- }}} -- }}}

View File

@ -16,8 +16,8 @@ local io = { open = io.open }
local setmetatable = setmetatable local setmetatable = setmetatable
local getmetatable = getmetatable local getmetatable = getmetatable
local string = { local string = {
upper = string.upper, upper = string.upper,
format = string.format format = string.format
} }
-- }}} -- }}}
@ -34,126 +34,126 @@ local scroller = {}
-- {{{ Helper functions -- {{{ Helper functions
-- {{{ Loader of vicious modules -- {{{ Loader of vicious modules
function helpers.wrequire(table, key) function helpers.wrequire(table, key)
local module = rawget(table, key) local module = rawget(table, key)
return module or require(table._NAME .. "." .. key) return module or require(table._NAME .. "." .. key)
end end
-- }}} -- }}}
-- {{{ Expose path as a Lua table -- {{{ Expose path as a Lua table
function helpers.pathtotable(dir) function helpers.pathtotable(dir)
return setmetatable({ _path = dir }, return setmetatable({ _path = dir },
{ __index = function(table, index) { __index = function(table, index)
local path = table._path .. '/' .. index local path = table._path .. '/' .. index
local f = io.open(path) local f = io.open(path)
if f then if f then
local s = f:read("*all") local s = f:read("*all")
f:close() f:close()
if s then if s then
return s return s
else else
local o = { _path = path } local o = { _path = path }
setmetatable(o, getmetatable(table)) setmetatable(o, getmetatable(table))
return o return o
end end
end end
end end
}) })
end end
-- }}} -- }}}
-- {{{ Format a string with args -- {{{ Format a string with args
function helpers.format(format, args) function helpers.format(format, args)
for var, val in pairs(args) do for var, val in pairs(args) do
format = format:gsub("$" .. (tonumber(var) and var or format = format:gsub("$" .. (tonumber(var) and var or
var:gsub("[-+?*]", function(i) return "%"..i end)), var:gsub("[-+?*]", function(i) return "%"..i end)),
val) val)
end end
return format return format
end end
-- }}} -- }}}
-- {{{ Format units to one decimal point -- {{{ Format units to one decimal point
function helpers.uformat(array, key, value, unit) function helpers.uformat(array, key, value, unit)
for u, v in pairs(unit) do for u, v in pairs(unit) do
array["{"..key.."_"..u.."}"] = string.format("%.1f", value/v) array["{"..key.."_"..u.."}"] = string.format("%.1f", value/v)
end end
return array return array
end end
-- }}} -- }}}
-- {{{ Escape a string -- {{{ Escape a string
function helpers.escape(text) function helpers.escape(text)
local xml_entities = { local xml_entities = {
["\""] = "&quot;", ["\""] = "&quot;",
["&"] = "&amp;", ["&"] = "&amp;",
["'"] = "&apos;", ["'"] = "&apos;",
["<"] = "&lt;", ["<"] = "&lt;",
[">"] = "&gt;" [">"] = "&gt;"
} }
return text and text:gsub("[\"&'<>]", xml_entities) return text and text:gsub("[\"&'<>]", xml_entities)
end end
-- }}} -- }}}
-- {{{ Escape a string for save usage on the command line -- {{{ Escape a string for save usage on the command line
function helpers.shellquote(s) function helpers.shellquote(s)
if s == nil then return "" end if s == nil then return "" end
-- use single quotes, and put single quotes into double quotes -- use single quotes, and put single quotes into double quotes
-- the string $'b is then quoted as '$'"'"'b'"'"' -- the string $'b is then quoted as '$'"'"'b'"'"'
return "'" .. s:gsub("'", "'\"'\"'") .. "'" return "'" .. s:gsub("'", "'\"'\"'") .. "'"
end 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)
return string.upper(c) .. s return string.upper(c) .. s
end) end)
end end
-- }}} -- }}}
-- {{{ Truncate a string -- {{{ Truncate a string
function helpers.truncate(text, maxlen) function helpers.truncate(text, maxlen)
local txtlen = text:len() local txtlen = text:len()
if txtlen > maxlen then if txtlen > maxlen then
text = text:sub(1, maxlen - 3) .. "..." text = text:sub(1, maxlen - 3) .. "..."
end end
return text return text
end end
-- }}} -- }}}
-- {{{ Scroll through a string -- {{{ Scroll through a string
function helpers.scroll(text, maxlen, widget) function helpers.scroll(text, maxlen, widget)
if not scroller[widget] then if not scroller[widget] then
scroller[widget] = { i = 1, d = true } scroller[widget] = { i = 1, d = true }
end
local txtlen = text:len()
local state = scroller[widget]
if txtlen > maxlen then
if state.d then
text = text:sub(state.i, state.i + maxlen) .. "..."
state.i = state.i + 3
if maxlen + state.i >= txtlen then
state.d = false
end
else
text = "..." .. text:sub(state.i, state.i + maxlen)
state.i = state.i - 3
if state.i <= 1 then
state.d = true
end
end end
end
return text local txtlen = text:len()
local state = scroller[widget]
if txtlen > maxlen then
if state.d then
text = text:sub(state.i, state.i + maxlen) .. "..."
state.i = state.i + 3
if maxlen + state.i >= txtlen then
state.d = false
end
else
text = "..." .. text:sub(state.i, state.i + maxlen)
state.i = state.i - 3
if state.i <= 1 then
state.d = true
end
end
end
return text
end end
-- }}} -- }}}

View File

@ -13,8 +13,8 @@ local tonumber = tonumber
local timer = (type(timer) == 'table' and timer or require("gears.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,
remove = table.remove remove = table.remove
} }
local helpers = require("vicious.helpers") local helpers = require("vicious.helpers")
@ -34,108 +34,108 @@ local widget_cache = {}
-- {{{ Local functions -- {{{ Local functions
-- {{{ Update a widget -- {{{ Update a widget
local function update(widget, reg, disablecache) local function update(widget, reg, disablecache)
-- Check if there are any equal widgets -- Check if there are any equal widgets
if reg == nil then if reg == nil then
for w, i in pairs(registered) do for w, i in pairs(registered) do
if w == widget then if w == widget then
for _, r in pairs(i) do for _, r in pairs(i) do
update(w, r, disablecache) update(w, r, disablecache)
end
end
end end
end
return
end end
return local t = os.time()
end local data = {}
local t = os.time() -- Check for chached output newer than the last update
local data = {} if widget_cache[reg.wtype] ~= nil then
local c = widget_cache[reg.wtype]
-- Check for chached output newer than the last update if (c.time == nil or c.time <= t-reg.timer) or disablecache then
if widget_cache[reg.wtype] ~= nil then c.time, c.data = t, reg.wtype(reg.format, reg.warg)
local c = widget_cache[reg.wtype] end
if (c.time == nil or c.time <= t-reg.timer) or disablecache then data = c.data
c.time, c.data = t, reg.wtype(reg.format, reg.warg) else
data = reg.wtype and reg.wtype(reg.format, reg.warg)
end end
data = c.data if type(data) == "table" then
else if type(reg.format) == "string" then
data = reg.wtype and reg.wtype(reg.format, reg.warg) data = helpers.format(reg.format, data)
end elseif type(reg.format) == "function" then
data = reg.format(widget, data)
if type(data) == "table" then end
if type(reg.format) == "string" then
data = helpers.format(reg.format, data)
elseif type(reg.format) == "function" then
data = reg.format(widget, data)
end end
end
if widget.add_value ~= nil then if widget.add_value ~= nil then
widget:add_value(tonumber(data) and tonumber(data)/100) widget:add_value(tonumber(data) and tonumber(data)/100)
elseif widget.set_value ~= nil then elseif widget.set_value ~= nil then
widget:set_value(tonumber(data) and tonumber(data)/100) widget:set_value(tonumber(data) and tonumber(data)/100)
elseif widget.set_markup ~= nil then elseif widget.set_markup ~= nil then
widget:set_markup(data) widget:set_markup(data)
else else
widget.text = data widget.text = data
end end
return data return data
end end
-- }}} -- }}}
-- {{{ Register from reg object -- {{{ Register from reg object
local function regregister(reg) local function regregister(reg)
if not reg.running then if not reg.running then
if registered[reg.widget] == nil then if registered[reg.widget] == nil then
registered[reg.widget] = {} registered[reg.widget] = {}
table.insert(registered[reg.widget], reg) table.insert(registered[reg.widget], reg)
else else
local already = false local already = false
for w, i in pairs(registered) do for w, i in pairs(registered) do
if w == reg.widget then if w == reg.widget then
for _, v in pairs(i) do for _, v in pairs(i) do
if v == reg then if v == reg then
already = true already = true
break break
end
end
if already then
break
end
end
end end
end
if already then if not already then
break table.insert(registered[reg.widget], reg)
end end
end end
end
if not already then -- Start the timer
table.insert(registered[reg.widget], reg) if reg.timer > 0 then
end local tm = timers[reg.timer] and timers[reg.timer].timer
tm = tm or timer({ timeout = reg.timer })
if tm.connect_signal then
tm:connect_signal("timeout", reg.update)
else
tm:add_signal("timeout", reg.update)
end
if not timers[reg.timer] then
timers[reg.timer] = { timer = tm, refs = 1 }
else
timers[reg.timer].refs = timers[reg.timer].refs + 1
end
if not tm.started then
tm:start()
end
-- Initial update
reg.update()
end
reg.running = true
end end
-- Start the timer
if reg.timer > 0 then
local tm = timers[reg.timer] and timers[reg.timer].timer
tm = tm or timer({ timeout = reg.timer })
if tm.connect_signal then
tm:connect_signal("timeout", reg.update)
else
tm:add_signal("timeout", reg.update)
end
if not timers[reg.timer] then
timers[reg.timer] = { timer = tm, refs = 1 }
else
timers[reg.timer].refs = timers[reg.timer].refs + 1
end
if not tm.started then
tm:start()
end
-- Initial update
reg.update()
end
reg.running = true
end
end end
-- }}} -- }}}
-- }}} -- }}}
@ -144,120 +144,120 @@ end
-- {{{ Global functions -- {{{ Global functions
-- {{{ Register a widget -- {{{ Register a widget
function vicious.register(widget, wtype, format, timer, warg) function vicious.register(widget, wtype, format, timer, warg)
local widget = widget local widget = widget
local reg = { local reg = {
-- Set properties -- Set properties
wtype = wtype, wtype = wtype,
format = format, format = format,
timer = timer, timer = timer,
warg = warg, warg = warg,
widget = widget, widget = widget,
} }
-- Set functions -- Set functions
reg.update = function () reg.update = function ()
update(widget, reg) update(widget, reg)
end end
-- Default to 2s timer -- Default to 2s timer
if reg.timer == nil then if reg.timer == nil then
reg.timer = 2 reg.timer = 2
end end
-- Register a reg object -- Register a reg object
regregister(reg) regregister(reg)
-- Return a reg object for reuse -- Return a reg object for reuse
return reg return reg
end end
-- }}} -- }}}
-- {{{ Unregister a widget -- {{{ Unregister a widget
function vicious.unregister(widget, keep, reg) function vicious.unregister(widget, keep, reg)
if reg == nil then if reg == nil then
for w, i in pairs(registered) do for w, i in pairs(registered) do
if w == widget then if w == widget then
for _, v in pairs(i) do for _, v in pairs(i) do
reg = vicious.unregister(w, keep, v) reg = vicious.unregister(w, keep, v)
end
end
end end
end
return reg
end
if not keep then
for w, i in pairs(registered) do
if w == widget then
for k, v in pairs(i) do
if v == reg then
table.remove(registered[w], k)
end
end
end
end
end
if not reg.running then
return reg
end
-- Disconnect from timer
local tm = timers[reg.timer]
if tm.timer.disconnect_signal then
tm.timer:disconnect_signal("timeout", reg.update)
else
tm.timer:remove_signal("timeout", reg.update)
end
reg.running = false
-- Stop the timer
tm.refs = tm.refs - 1
if tm.refs == 0 and tm.timer.started then
tm.timer:stop()
end end
return reg return reg
end
if not keep then
for w, i in pairs(registered) do
if w == widget then
for k, v in pairs(i) do
if v == reg then
table.remove(registered[w], k)
end
end
end
end
end
if not reg.running then
return reg
end
-- Disconnect from timer
local tm = timers[reg.timer]
if tm.timer.disconnect_signal then
tm.timer:disconnect_signal("timeout", reg.update)
else
tm.timer:remove_signal("timeout", reg.update)
end
reg.running = false
-- Stop the timer
tm.refs = tm.refs - 1
if tm.refs == 0 and tm.timer.started then
tm.timer:stop()
end
return reg
end end
-- }}} -- }}}
-- {{{ Enable caching of a widget type -- {{{ Enable caching of a widget type
function vicious.cache(wtype) function vicious.cache(wtype)
if wtype ~= nil then if wtype ~= nil then
if widget_cache[wtype] == nil then if widget_cache[wtype] == nil then
widget_cache[wtype] = {} widget_cache[wtype] = {}
end
end end
end
end end
-- }}} -- }}}
-- {{{ Force update of widgets -- {{{ Force update of widgets
function vicious.force(wtable) function vicious.force(wtable)
if type(wtable) == "table" then if type(wtable) == "table" then
for _, w in pairs(wtable) do for _, w in pairs(wtable) do
update(w, nil, true) update(w, nil, true)
end
end end
end
end end
-- }}} -- }}}
-- {{{ Suspend all widgets -- {{{ Suspend all widgets
function vicious.suspend() function vicious.suspend()
for w, i in pairs(registered) do for w, i in pairs(registered) do
for _, v in pairs(i) do for _, v in pairs(i) do
vicious.unregister(w, true, v) vicious.unregister(w, true, v)
end
end end
end
end end
-- }}} -- }}}
-- {{{ Activate a widget -- {{{ Activate a widget
function vicious.activate(widget) function vicious.activate(widget)
for w, i in pairs(registered) do for w, i in pairs(registered) do
if widget == nil or w == widget then if widget == nil or w == widget then
for _, v in pairs(i) do for _, v in pairs(i) do
regregister(v) regregister(v)
end end
end
end end
end
end end
-- }}} -- }}}

View File

@ -10,8 +10,8 @@ local setmetatable = setmetatable
local string = { format = string.format } local string = { format = string.format }
local helpers = require("vicious.helpers") local helpers = require("vicious.helpers")
local math = { local math = {
min = math.min, min = math.min,
floor = math.floor floor = math.floor
} }
-- }}} -- }}}
@ -23,71 +23,71 @@ local bat = {}
-- {{{ Battery widget type -- {{{ Battery widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
local battery = helpers.pathtotable("/sys/class/power_supply/"..warg) local battery = helpers.pathtotable("/sys/class/power_supply/"..warg)
local battery_state = { local battery_state = {
["Full\n"] = "", ["Full\n"] = "",
["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", 0} return {battery_state["Unknown\n"], 0, "N/A", 0}
end
-- Get state information
local state = battery_state[battery.status] or battery_state["Unknown\n"]
-- Get capacity information
if battery.charge_now then
remaining, capacity = battery.charge_now, battery.charge_full
capacity_design = battery.charge_full_design or capacity
elseif battery.energy_now then
remaining, capacity = battery.energy_now, battery.energy_full
capacity_design = battery.energy_full_design or capacity
else
return {battery_state["Unknown\n"], 0, "N/A", 0}
end
-- Calculate capacity and wear percentage (but work around broken BAT/ACPI implementations)
local percent = math.min(math.floor(remaining / capacity * 100), 100)
local wear = math.floor(100 - capacity / capacity_design * 100)
-- Get charge information
if battery.current_now then
rate = tonumber(battery.current_now)
elseif battery.power_now then
rate = tonumber(battery.power_now)
else
return {state, percent, "N/A", wear}
end
-- Calculate remaining (charging or discharging) time
local time = "N/A"
if rate ~= nil and rate ~= 0 then
if state == "+" then
timeleft = (tonumber(capacity) - tonumber(remaining)) / tonumber(rate)
elseif state == "" then
timeleft = tonumber(remaining) / tonumber(rate)
else
return {state, percent, time, wear}
end end
-- Calculate time
local hoursleft = math.floor(timeleft)
local minutesleft = math.floor((timeleft - hoursleft) * 60 )
time = string.format("%02d:%02d", hoursleft, minutesleft) -- Get state information
end local state = battery_state[battery.status] or battery_state["Unknown\n"]
return {state, percent, time, wear} -- Get capacity information
if battery.charge_now then
remaining, capacity = battery.charge_now, battery.charge_full
capacity_design = battery.charge_full_design or capacity
elseif battery.energy_now then
remaining, capacity = battery.energy_now, battery.energy_full
capacity_design = battery.energy_full_design or capacity
else
return {battery_state["Unknown\n"], 0, "N/A", 0}
end
-- Calculate capacity and wear percentage (but work around broken BAT/ACPI implementations)
local percent = math.min(math.floor(remaining / capacity * 100), 100)
local wear = math.floor(100 - capacity / capacity_design * 100)
-- Get charge information
if battery.current_now then
rate = tonumber(battery.current_now)
elseif battery.power_now then
rate = tonumber(battery.power_now)
else
return {state, percent, "N/A", wear}
end
-- Calculate remaining (charging or discharging) time
local time = "N/A"
if rate ~= nil and rate ~= 0 then
if state == "+" then
timeleft = (tonumber(capacity) - tonumber(remaining)) / tonumber(rate)
elseif state == "" then
timeleft = tonumber(remaining) / tonumber(rate)
else
return {state, percent, time, wear}
end
-- Calculate time
local hoursleft = math.floor(timeleft)
local minutesleft = math.floor((timeleft - hoursleft) * 60 )
time = string.format("%02d:%02d", hoursleft, minutesleft)
end
return {state, percent, time, wear}
end end
-- }}} -- }}}

View File

@ -12,8 +12,8 @@ local setmetatable = setmetatable
local math = { floor = math.floor } local math = { floor = math.floor }
local table = { insert = table.insert } local table = { insert = table.insert }
local string = { local string = {
sub = string.sub, sub = string.sub,
gmatch = string.gmatch gmatch = string.gmatch
} }
-- }}} -- }}}
@ -30,50 +30,50 @@ local cpu_active = {}
-- {{{ CPU widget type -- {{{ CPU widget type
local function worker(format) local function worker(format)
local cpu_lines = {} local cpu_lines = {}
-- Get CPU stats -- Get CPU stats
local f = io.open("/proc/stat") local f = io.open("/proc/stat")
for line in f:lines() do for line in f:lines() do
if string.sub(line, 1, 3) ~= "cpu" then break end if string.sub(line, 1, 3) ~= "cpu" then break end
cpu_lines[#cpu_lines+1] = {} cpu_lines[#cpu_lines+1] = {}
for i in string.gmatch(line, "[%s]+([^%s]+)") do for i in string.gmatch(line, "[%s]+([^%s]+)") do
table.insert(cpu_lines[#cpu_lines], i) table.insert(cpu_lines[#cpu_lines], i)
end
end end
end f:close()
f:close()
-- Ensure tables are initialized correctly -- Ensure tables are initialized correctly
for i = #cpu_total + 1, #cpu_lines do for i = #cpu_total + 1, #cpu_lines do
cpu_total[i] = 0 cpu_total[i] = 0
cpu_usage[i] = 0 cpu_usage[i] = 0
cpu_active[i] = 0 cpu_active[i] = 0
end
for i, v in ipairs(cpu_lines) do
-- Calculate totals
local total_new = 0
for j = 1, #v do
total_new = total_new + v[j]
end end
local active_new = total_new - (v[4] + v[5])
-- Calculate percentage
local diff_total = total_new - cpu_total[i]
local diff_active = active_new - cpu_active[i]
if diff_total == 0 then diff_total = 1E-6 end for i, v in ipairs(cpu_lines) do
cpu_usage[i] = math.floor((diff_active / diff_total) * 100) -- Calculate totals
local total_new = 0
for j = 1, #v do
total_new = total_new + v[j]
end
local active_new = total_new - (v[4] + v[5])
-- Store totals -- Calculate percentage
cpu_total[i] = total_new local diff_total = total_new - cpu_total[i]
cpu_active[i] = active_new local diff_active = active_new - cpu_active[i]
end
return cpu_usage if diff_total == 0 then diff_total = 1E-6 end
cpu_usage[i] = math.floor((diff_active / diff_total) * 100)
-- Store totals
cpu_total[i] = total_new
cpu_active[i] = active_new
end
return cpu_usage
end end
-- }}} -- }}}

View File

@ -18,43 +18,43 @@ local cpufreq = {}
-- {{{ CPU frequency widget type -- {{{ CPU frequency widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
local _cpufreq = helpers.pathtotable("/sys/devices/system/cpu/"..warg.."/cpufreq") local _cpufreq = helpers.pathtotable("/sys/devices/system/cpu/"..warg.."/cpufreq")
local governor_state = { local governor_state = {
["ondemand\n"] = "", ["ondemand\n"] = "",
["powersave\n"] = "", ["powersave\n"] = "",
["userspace\n"] = "¤", ["userspace\n"] = "¤",
["performance\n"] = "", ["performance\n"] = "",
["conservative\n"] = "" ["conservative\n"] = ""
} }
-- Default frequency and voltage values -- Default frequency and voltage values
local freqv = { local freqv = {
["mhz"] = "N/A", ["ghz"] = "N/A", ["mhz"] = "N/A", ["ghz"] = "N/A",
["v"] = "N/A", ["mv"] = "N/A", ["v"] = "N/A", ["mv"] = "N/A",
} }
-- Get the current frequency -- Get the current frequency
local freq = tonumber(_cpufreq.scaling_cur_freq) local freq = tonumber(_cpufreq.scaling_cur_freq)
-- Calculate MHz and GHz -- Calculate MHz and GHz
if freq then if freq then
freqv.mhz = freq / 1000 freqv.mhz = freq / 1000
freqv.ghz = freqv.mhz / 1000 freqv.ghz = freqv.mhz / 1000
-- Get the current voltage -- Get the current voltage
if _cpufreq.scaling_voltages then if _cpufreq.scaling_voltages then
freqv.mv = tonumber(string.match(_cpufreq.scaling_voltages, freq.."[%s]([%d]+)")) freqv.mv = tonumber(string.match(_cpufreq.scaling_voltages, freq.."[%s]([%d]+)"))
-- Calculate voltage from mV -- Calculate voltage from mV
freqv.v = freqv.mv / 1000 freqv.v = freqv.mv / 1000
end
end end
end
-- Get the current governor -- Get the current governor
local governor = _cpufreq.scaling_governor local governor = _cpufreq.scaling_governor
-- Represent the governor as a symbol -- Represent the governor as a symbol
governor = governor_state[governor] or governor or "N/A" governor = governor_state[governor] or governor or "N/A"
return {freqv.mhz, freqv.ghz, freqv.mv, freqv.v, governor} return {freqv.mhz, freqv.ghz, freqv.mv, freqv.v, governor}
end end
-- }}} -- }}}

View File

@ -18,26 +18,26 @@ local cpuinf = {}
-- {{{ CPU Information widget type -- {{{ CPU Information widget type
local function worker(format) local function worker(format)
local id = nil local id = nil
local cpu_info = {} -- Get CPU info local cpu_info = {} -- Get CPU info
for line in io.lines("/proc/cpuinfo") do for line in io.lines("/proc/cpuinfo") do
for k, v in string.gmatch(line, "([%a%s]+)[%s]+:[%s]([%d]+).-$") do for k, v in string.gmatch(line, "([%a%s]+)[%s]+:[%s]([%d]+).-$") do
if k == "processor" then if k == "processor" then
id = v id = v
elseif k == "cpu MHz\t" or k == "cpu MHz" then elseif k == "cpu MHz\t" or k == "cpu MHz" then
local speed = tonumber(v) local speed = tonumber(v)
cpu_info["{cpu"..id.." mhz}"] = speed cpu_info["{cpu"..id.." mhz}"] = speed
cpu_info["{cpu"..id.." ghz}"] = speed / 1000 cpu_info["{cpu"..id.." ghz}"] = speed / 1000
elseif k == "cache size" then elseif k == "cache size" then
local cache = tonumber(v) local cache = tonumber(v)
cpu_info["{cpu"..id.." kb}"] = cache cpu_info["{cpu"..id.." kb}"] = cache
cpu_info["{cpu"..id.." mb}"] = cache / 1024 cpu_info["{cpu"..id.." mb}"] = cache / 1024
end end
end
end end
end
return cpu_info return cpu_info
end end
-- }}} -- }}}

View File

@ -7,8 +7,8 @@
-- {{{ Grab environment -- {{{ Grab environment
local setmetatable = setmetatable local setmetatable = setmetatable
local os = { local os = {
date = os.date, date = os.date,
time = os.time time = os.time
} }
-- }}} -- }}}
@ -20,7 +20,7 @@ local date = {}
-- {{{ Date widget type -- {{{ Date widget type
local function worker(format, warg) local function worker(format, warg)
return os.date(format or nil, warg and os.time()+warg or nil) return os.date(format or nil, warg and os.time()+warg or nil)
end end
-- }}} -- }}}

View File

@ -10,8 +10,8 @@ local setmetatable = setmetatable
local string = { match = string.match } local string = { match = string.match }
local helpers = require("vicious.helpers") local helpers = require("vicious.helpers")
local os = { local os = {
time = os.time, time = os.time,
difftime = os.difftime difftime = os.difftime
} }
-- }}} -- }}}
@ -30,43 +30,43 @@ local unit = { ["s"] = 1, ["kb"] = 2, ["mb"] = 2048 }
-- {{{ Disk I/O widget type -- {{{ Disk I/O widget type
local function worker(format) local function worker(format)
local disk_lines = {} local disk_lines = {}
for line in io.lines("/proc/diskstats") do for line in io.lines("/proc/diskstats") do
local device, read, write = local device, read, write =
-- Linux kernel documentation: Documentation/iostats.txt -- Linux kernel documentation: Documentation/iostats.txt
string.match(line, "([^%s]+) %d+ %d+ (%d+) %d+ %d+ %d+ (%d+)") string.match(line, "([^%s]+) %d+ %d+ (%d+) %d+ %d+ %d+ (%d+)")
disk_lines[device] = { read, write } disk_lines[device] = { read, write }
end
local time = os.time()
local interval = os.difftime(time, disk_time)
if interval == 0 then interval = 1 end
for device, stats in pairs(disk_lines) do
-- Avoid insane values on startup
local last_stats = disk_stats[device] or stats
-- Check for overflows and counter resets (> 2^32)
if stats[1] < last_stats[1] or stats[2] < last_stats[2] then
last_stats[1], last_stats[2] = stats[1], stats[2]
end end
-- Diskstats are absolute, substract our last reading local time = os.time()
-- * divide by timediff because we don't know the timer value local interval = os.difftime(time, disk_time)
local read = (stats[1] - last_stats[1]) / interval if interval == 0 then interval = 1 end
local write = (stats[2] - last_stats[2]) / interval
-- Calculate and store I/O for device, stats in pairs(disk_lines) do
helpers.uformat(disk_usage, device.." read", read, unit) -- Avoid insane values on startup
helpers.uformat(disk_usage, device.." write", write, unit) local last_stats = disk_stats[device] or stats
helpers.uformat(disk_usage, device.." total", read + write, unit)
end
disk_time = time -- Check for overflows and counter resets (> 2^32)
disk_stats = disk_lines if stats[1] < last_stats[1] or stats[2] < last_stats[2] then
last_stats[1], last_stats[2] = stats[1], stats[2]
end
return disk_usage -- Diskstats are absolute, substract our last reading
-- * divide by timediff because we don't know the timer value
local read = (stats[1] - last_stats[1]) / interval
local write = (stats[2] - last_stats[2]) / interval
-- Calculate and store I/O
helpers.uformat(disk_usage, device.." read", read, unit)
helpers.uformat(disk_usage, device.." write", write, unit)
helpers.uformat(disk_usage, device.." total", read + write, unit)
end
disk_time = time
disk_stats = disk_lines
return disk_usage
end end
-- }}} -- }}}

View File

@ -23,29 +23,29 @@ local unit = { ["mb"] = 1024, ["gb"] = 1024^2 }
-- {{{ Filesystem widget type -- {{{ Filesystem widget type
local function worker(format, warg) local function worker(format, warg)
-- Fallback to listing local filesystems -- Fallback to listing local filesystems
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 " .. helpers.shellquote(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)
helpers.uformat(fs_info, m .. " used", u, unit) helpers.uformat(fs_info, m .. " used", u, unit)
helpers.uformat(fs_info, m .. " avail", a, unit) helpers.uformat(fs_info, m .. " avail", a, unit)
fs_info["{" .. m .. " used_p}"] = tonumber(p) fs_info["{" .. m .. " used_p}"] = tonumber(p)
fs_info["{" .. m .. " avail_p}"] = 100 - tonumber(p) fs_info["{" .. m .. " avail_p}"] = 100 - tonumber(p)
end
end end
end f:close()
f:close()
return fs_info return fs_info
end end
-- }}} -- }}}

View File

@ -10,7 +10,7 @@ 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 = {
match = string.match match = string.match
} }
-- }}} -- }}}
@ -22,55 +22,55 @@ local gmail = {}
-- {{{ Variable definitions -- {{{ Variable definitions
local rss = { local rss = {
inbox = "https://mail.google.com/mail/feed/atom", inbox = "https://mail.google.com/mail/feed/atom",
unread = "https://mail.google.com/mail/feed/atom/unread", unread = "https://mail.google.com/mail/feed/atom/unread",
--labelname = "https://mail.google.com/mail/feed/atom/labelname", --labelname = "https://mail.google.com/mail/feed/atom/labelname",
} }
-- Default is just Inbox -- Default is just Inbox
local feed = rss.inbox local feed = rss.inbox
local mail = { local mail = {
["{count}"] = 0, ["{count}"] = 0,
["{subject}"] = "N/A" ["{subject}"] = "N/A"
} }
-- }}} -- }}}
-- {{{ 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) 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
local xml = f:read(2000) local xml = f:read(2000)
if xml ~= nil then if xml ~= nil then
return mail return mail
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 end
-- Spam sanitize the subject and store mail["{count}"] = -- Count comes before messages and matches at least 0
mail["{subject}"] = helpers.escape(title) tonumber(string.match(xml, "<fullcount>([%d]+)</fullcount>")) or mail["{count}"]
end
f:close() -- Find subject tag
local title = string.match(xml, "<entry>.-<title>(.-)</title>")
return mail 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()
return mail
end end
-- }}} -- }}}

View File

@ -19,21 +19,21 @@ local hddtemp = {}
-- {{{ HDD Temperature widget type -- {{{ HDD Temperature widget type
local function worker(format, warg) local function worker(format, warg)
-- Fallback to default hddtemp port -- Fallback to default hddtemp port
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 quoted = helpers.shellquote(warg) local quoted = helpers.shellquote(warg)
local f = io.popen("echo | curl --connect-timeout 1 -fsm 3 telnet://127.0.0.1:"..quoted) 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
hdd_temp["{"..d.."}"] = tonumber(t) hdd_temp["{"..d.."}"] = tonumber(t)
end
end end
end f:close()
f:close()
return hdd_temp return hdd_temp
end end
-- }}} -- }}}

View File

@ -22,31 +22,31 @@ local subject = "N/A"
-- {{{ Mailbox widget type -- {{{ Mailbox widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
-- mbox could be huge, get a 30kb chunk from EOF -- mbox could be huge, get a 30kb chunk from EOF
if type(warg) ~= "table" then _mbox = warg end if type(warg) ~= "table" then _mbox = warg end
-- * attachment could be much bigger than 30kb -- * attachment could be much bigger than 30kb
local f = io.open(_mbox or warg[1]) local f = io.open(_mbox or warg[1])
f:seek("end", -30720) f:seek("end", -30720)
local txt = f:read("*all") local txt = f:read("*all")
f:close() f:close()
-- Find all Subject lines -- Find all Subject lines
for i in string.gfind(txt, "Subject: ([^\n]*)") do for i in string.gfind(txt, "Subject: ([^\n]*)") do
subject = i subject = i
end
-- Check if we should scroll, or maybe truncate
if type(warg) == "table" then
if warg[3] ~= nil then
subject = helpers.scroll(subject, warg[2], warg[3])
else
subject = helpers.truncate(subject, warg[2])
end end
end
return {helpers.escape(subject)} -- Check if we should scroll, or maybe truncate
if type(warg) == "table" then
if warg[3] ~= nil then
subject = helpers.scroll(subject, warg[2], warg[3])
else
subject = helpers.truncate(subject, warg[2])
end
end
return {helpers.escape(subject)}
end end
-- }}} -- }}}

View File

@ -17,41 +17,41 @@ local mboxc = {}
-- {{{ Mbox count widget type -- {{{ Mbox count widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
-- Initialize counters -- Initialize counters
local count = { old = 0, total = 0, new = 0 } local count = { old = 0, total = 0, new = 0 }
-- Get data from mbox files -- Get data from mbox files
for i=1, #warg do for i=1, #warg do
local f = io.open(warg[i]) local f = io.open(warg[i])
while true do while true do
-- Read the mbox line by line, if we are going to read -- Read the mbox line by line, if we are going to read
-- some *HUGE* folders then switch to reading chunks -- some *HUGE* folders then switch to reading chunks
local lines = f:read("*line") local lines = f:read("*line")
if not lines then break end if not lines then break end
-- Find all messages -- Find all messages
-- * http://www.jwz.org/doc/content-length.html -- * http://www.jwz.org/doc/content-length.html
local _, from = string.find(lines, "^From[%s]") local _, from = string.find(lines, "^From[%s]")
if from ~= nil then count.total = count.total + 1 end if from ~= nil then count.total = count.total + 1 end
-- Read messages have the Status header -- Read messages have the Status header
local _, status = string.find(lines, "^Status:[%s]RO$") local _, status = string.find(lines, "^Status:[%s]RO$")
if status ~= nil then count.old = count.old + 1 end if status ~= nil then count.old = count.old + 1 end
-- Skip the folder internal data -- Skip the folder internal data
local _, int = string.find(lines, "^Subject:[%s].*FOLDER[%s]INTERNAL[%s]DATA") local _, int = string.find(lines, "^Subject:[%s].*FOLDER[%s]INTERNAL[%s]DATA")
if int ~= nil then count.total = count.total - 1 end if int ~= nil then count.total = count.total - 1 end
end
f:close()
end end
f:close()
end
-- Substract total from old to get the new count -- Substract total from old to get the new count
count.new = count.total - count.old count.new = count.total - count.old
return {count.total, count.old, count.new} return {count.total, count.old, count.new}
end end
-- }}} -- }}}

View File

@ -18,25 +18,25 @@ local mdir = {}
-- {{{ Maildir widget type -- {{{ Maildir widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
-- Initialize counters -- Initialize counters
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]) quoted_path = helpers.shellquote(warg[i])
-- Recursively find new messages -- Recursively find new messages
local f = io.popen("find "..quoted_path.." -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 "..quoted_path.." -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
return {count.new, count.cur} return {count.new, count.cur}
end end
-- }}} -- }}}

View File

@ -19,33 +19,33 @@ local mem = {}
-- {{{ Memory widget type -- {{{ Memory widget type
local function worker(format) local function worker(format)
local _mem = { buf = {}, swp = {} } local _mem = { buf = {}, swp = {} }
-- Get MEM info -- Get MEM info
for line in io.lines("/proc/meminfo") do for line in io.lines("/proc/meminfo") do
for k, v in string.gmatch(line, "([%a]+):[%s]+([%d]+).+") do for k, v in string.gmatch(line, "([%a]+):[%s]+([%d]+).+") do
if k == "MemTotal" then _mem.total = math.floor(v/1024) if k == "MemTotal" then _mem.total = math.floor(v/1024)
elseif k == "MemFree" then _mem.buf.f = math.floor(v/1024) elseif k == "MemFree" then _mem.buf.f = math.floor(v/1024)
elseif k == "Buffers" then _mem.buf.b = math.floor(v/1024) elseif k == "Buffers" then _mem.buf.b = math.floor(v/1024)
elseif k == "Cached" then _mem.buf.c = math.floor(v/1024) elseif k == "Cached" then _mem.buf.c = math.floor(v/1024)
elseif k == "SwapTotal" then _mem.swp.t = math.floor(v/1024) elseif k == "SwapTotal" then _mem.swp.t = math.floor(v/1024)
elseif k == "SwapFree" then _mem.swp.f = math.floor(v/1024) elseif k == "SwapFree" then _mem.swp.f = math.floor(v/1024)
end end
end
end end
end
-- Calculate memory percentage -- Calculate memory percentage
_mem.free = _mem.buf.f + _mem.buf.b + _mem.buf.c _mem.free = _mem.buf.f + _mem.buf.b + _mem.buf.c
_mem.inuse = _mem.total - _mem.free _mem.inuse = _mem.total - _mem.free
_mem.bcuse = _mem.total - _mem.buf.f _mem.bcuse = _mem.total - _mem.buf.f
_mem.usep = math.floor(_mem.inuse / _mem.total * 100) _mem.usep = math.floor(_mem.inuse / _mem.total * 100)
-- Calculate swap percentage -- Calculate swap percentage
_mem.swp.inuse = _mem.swp.t - _mem.swp.f _mem.swp.inuse = _mem.swp.t - _mem.swp.f
_mem.swp.usep = math.floor(_mem.swp.inuse / _mem.swp.t * 100) _mem.swp.usep = math.floor(_mem.swp.inuse / _mem.swp.t * 100)
return {_mem.usep, _mem.inuse, _mem.total, _mem.free, return {_mem.usep, _mem.inuse, _mem.total, _mem.free,
_mem.swp.usep, _mem.swp.inuse, _mem.swp.t, _mem.swp.f, _mem.swp.usep, _mem.swp.inuse, _mem.swp.t, _mem.swp.f,
_mem.bcuse } _mem.bcuse }
end end
-- }}} -- }}}

View File

@ -19,45 +19,45 @@ local mpd = {}
-- {{{ MPD widget type -- {{{ MPD widget type
local function worker(format, warg) local function worker(format, warg)
local mpd_state = { local mpd_state = {
["{volume}"] = 0, ["{volume}"] = 0,
["{state}"] = "N/A", ["{state}"] = "N/A",
["{Artist}"] = "N/A", ["{Artist}"] = "N/A",
["{Title}"] = "N/A", ["{Title}"] = "N/A",
["{Album}"] = "N/A", ["{Album}"] = "N/A",
["{Genre}"] = "N/A", ["{Genre}"] = "N/A",
--["{Name}"] = "N/A", --["{Name}"] = "N/A",
--["{file}"] = "N/A", --["{file}"] = "N/A",
} }
-- Fallback to MPD defaults -- Fallback to MPD defaults
local pass = warg and (warg.password or warg[1]) or "\"\"" local pass = warg and (warg.password or warg[1]) or "\"\""
local host = warg and (warg.host or warg[2]) or "127.0.0.1" local host = warg and (warg.host or warg[2]) or "127.0.0.1"
local port = warg and (warg.port or warg[3]) or "6600" local port = warg and (warg.port or warg[3]) or "6600"
-- Construct MPD client options -- Construct MPD client options
local mpdh = "telnet://"..host..":"..port local mpdh = "telnet://"..host..":"..port
local echo = "echo 'password "..pass.."\nstatus\ncurrentsong\nclose'" local echo = "echo 'password "..pass.."\nstatus\ncurrentsong\nclose'"
-- Get data from MPD server -- Get data from MPD server
local f = io.popen(echo.." | curl --connect-timeout 1 -fsm 3 "..mpdh) local f = io.popen(echo.." | curl --connect-timeout 1 -fsm 3 "..mpdh)
for line in f:lines() do for line in f:lines() do
for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
if k == "volume" then mpd_state["{"..k.."}"] = v and tonumber(v) if k == "volume" then mpd_state["{"..k.."}"] = v and tonumber(v)
elseif k == "state" then mpd_state["{"..k.."}"] = helpers.capitalize(v) elseif k == "state" then mpd_state["{"..k.."}"] = helpers.capitalize(v)
elseif k == "Artist" then mpd_state["{"..k.."}"] = helpers.escape(v) elseif k == "Artist" then mpd_state["{"..k.."}"] = helpers.escape(v)
elseif k == "Title" then mpd_state["{"..k.."}"] = helpers.escape(v) elseif k == "Title" then mpd_state["{"..k.."}"] = helpers.escape(v)
elseif k == "Album" then mpd_state["{"..k.."}"] = helpers.escape(v) elseif k == "Album" then mpd_state["{"..k.."}"] = helpers.escape(v)
elseif k == "Genre" then mpd_state["{"..k.."}"] = helpers.escape(v) elseif k == "Genre" then mpd_state["{"..k.."}"] = helpers.escape(v)
--elseif k == "Name" then mpd_state["{"..k.."}"] = helpers.escape(v) --elseif k == "Name" then mpd_state["{"..k.."}"] = helpers.escape(v)
--elseif k == "file" then mpd_state["{"..k.."}"] = helpers.escape(v) --elseif k == "file" then mpd_state["{"..k.."}"] = helpers.escape(v)
end end
end
end end
end f:close()
f:close()
return mpd_state return mpd_state
end end
-- }}} -- }}}

View File

@ -23,57 +23,57 @@ local net = {}
local nets = {} local nets = {}
-- Variable definitions -- Variable definitions
local unit = { ["b"] = 1, ["kb"] = 1024, local unit = { ["b"] = 1, ["kb"] = 1024,
["mb"] = 1024^2, ["gb"] = 1024^3 ["mb"] = 1024^2, ["gb"] = 1024^3
} }
-- {{{ Net widget type -- {{{ Net widget type
local function worker(format) local function worker(format)
local args = {} local args = {}
-- Get NET stats -- Get NET stats
for line in io.lines("/proc/net/dev") do for line in io.lines("/proc/net/dev") do
-- Match wmaster0 as well as rt0 (multiple leading spaces) -- Match wmaster0 as well as rt0 (multiple leading spaces)
local name = string.match(line, "^[%s]?[%s]?[%s]?[%s]?([%w]+):") local name = string.match(line, "^[%s]?[%s]?[%s]?[%s]?([%w]+):")
if name ~= nil then if name ~= nil then
-- Received bytes, first value after the name -- Received bytes, first value after the name
local recv = tonumber(string.match(line, ":[%s]*([%d]+)")) local recv = tonumber(string.match(line, ":[%s]*([%d]+)"))
-- Transmited bytes, 7 fields from end of the line -- Transmited bytes, 7 fields from end of the line
local send = tonumber(string.match(line, local send = tonumber(string.match(line,
"([%d]+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d$")) "([%d]+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d$"))
helpers.uformat(args, name .. " rx", recv, unit) helpers.uformat(args, name .. " rx", recv, unit)
helpers.uformat(args, name .. " tx", send, unit) helpers.uformat(args, name .. " tx", send, unit)
-- Operational state and carrier detection -- Operational state and carrier detection
local sysnet = helpers.pathtotable("/sys/class/net/" .. name) local sysnet = helpers.pathtotable("/sys/class/net/" .. name)
args["{"..name.." carrier}"] = tonumber(sysnet.carrier) or 0 args["{"..name.." carrier}"] = tonumber(sysnet.carrier) or 0
local now = os.time() local now = os.time()
if nets[name] == nil then if nets[name] == nil then
-- Default values on the first run -- Default values on the first run
nets[name] = {} nets[name] = {}
helpers.uformat(args, name .. " down", 0, unit) helpers.uformat(args, name .. " down", 0, unit)
helpers.uformat(args, name .. " up", 0, unit) helpers.uformat(args, name .. " up", 0, unit)
else -- Net stats are absolute, substract our last reading else -- Net stats are absolute, substract our last reading
local interval = now - nets[name].time local interval = now - nets[name].time
if interval <= 0 then interval = 1 end if interval <= 0 then interval = 1 end
local down = (recv - nets[name][1]) / interval local down = (recv - nets[name][1]) / interval
local up = (send - nets[name][2]) / interval local up = (send - nets[name][2]) / interval
helpers.uformat(args, name .. " down", down, unit) helpers.uformat(args, name .. " down", down, unit)
helpers.uformat(args, name .. " up", up, unit) helpers.uformat(args, name .. " up", up, unit)
end end
nets[name].time = now nets[name].time = now
-- Store totals -- Store totals
nets[name][1] = recv nets[name][1] = recv
nets[name][2] = send nets[name][2] = send
end
end end
end
return args return args
end end
-- }}} -- }}}

View File

@ -9,8 +9,8 @@ local io = { lines = io.lines }
local setmetatable = setmetatable local setmetatable = setmetatable
local string = { find = string.find } local string = { find = string.find }
local os = { local os = {
time = os.time, time = os.time,
date = os.date date = os.date
} }
-- }}} -- }}}
@ -22,40 +22,40 @@ local org = {}
-- {{{ OrgMode widget type -- {{{ OrgMode widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
-- Compute delays -- Compute delays
local today = os.time{ year=os.date("%Y"), month=os.date("%m"), day=os.date("%d") } local today = os.time{ year=os.date("%Y"), month=os.date("%m"), day=os.date("%d") }
local soon = today + 24 * 3600 * 3 -- 3 days ahead is close local soon = today + 24 * 3600 * 3 -- 3 days ahead is close
local future = today + 24 * 3600 * 7 -- 7 days ahead is maximum local future = today + 24 * 3600 * 7 -- 7 days ahead is maximum
-- Initialize counters -- Initialize counters
local count = { past = 0, today = 0, soon = 0, future = 0 } local count = { past = 0, today = 0, soon = 0, future = 0 }
-- Get data from agenda files -- Get data from agenda files
for i=1, #warg do for i=1, #warg do
for line in io.lines(warg[i]) do for line in io.lines(warg[i]) do
local scheduled = string.find(line, "SCHEDULED:") local scheduled = string.find(line, "SCHEDULED:")
local closed = string.find(line, "CLOSED:") local closed = string.find(line, "CLOSED:")
local deadline = string.find(line, "DEADLINE:") local deadline = string.find(line, "DEADLINE:")
if (scheduled and not closed) or (deadline and not closed) then if (scheduled and not closed) or (deadline and not closed) then
local b, e, y, m, d = string.find(line, "(%d%d%d%d)-(%d%d)-(%d%d)") local b, e, y, m, d = string.find(line, "(%d%d%d%d)-(%d%d)-(%d%d)")
if b then if b then
local t = os.time{ year = y, month = m, day = d } local t = os.time{ year = y, month = m, day = d }
if t < today then count.past = count.past + 1 if t < today then count.past = count.past + 1
elseif t == today then count.today = count.today + 1 elseif t == today then count.today = count.today + 1
elseif t <= soon then count.soon = count.soon + 1 elseif t <= soon then count.soon = count.soon + 1
elseif t <= future then count.future = count.future + 1 elseif t <= future then count.future = count.future + 1
end end
end
end
end end
end
end end
end
return {count.past, count.today, count.soon, count.future} return {count.past, count.today, count.soon, count.future}
end end
-- }}} -- }}}

View File

@ -12,8 +12,8 @@ local los = { getenv = os.getenv }
local setmetatable = setmetatable local setmetatable = setmetatable
local helpers = require("vicious.helpers") local helpers = require("vicious.helpers")
local string = { local string = {
gsub = string.gsub, gsub = string.gsub,
match = string.match match = string.match
} }
-- }}} -- }}}
@ -25,48 +25,48 @@ local os = {}
-- {{{ Operating system widget type -- {{{ Operating system widget type
local function worker(format) local function worker(format)
local system = { local system = {
["ostype"] = "N/A", ["ostype"] = "N/A",
["hostname"] = "N/A", ["hostname"] = "N/A",
["osrelease"] = "N/A", ["osrelease"] = "N/A",
["username"] = "N/A", ["username"] = "N/A",
["entropy"] = "N/A", ["entropy"] = "N/A",
["entropy_p"] = "N/A" ["entropy_p"] = "N/A"
} }
-- Linux manual page: uname(2) -- Linux manual page: uname(2)
local kernel = helpers.pathtotable("/proc/sys/kernel") local kernel = helpers.pathtotable("/proc/sys/kernel")
for k, v in pairs(system) do for k, v in pairs(system) do
if kernel[k] then if kernel[k] then
system[k] = string.gsub(kernel[k], "[%s]*$", "") system[k] = string.gsub(kernel[k], "[%s]*$", "")
end
end end
end
-- BSD manual page: uname(1) -- BSD manual page: uname(1)
if system["ostype"] == "N/A" then if system["ostype"] == "N/A" then
local f = io.popen("uname -snr") local f = io.popen("uname -snr")
local uname = f:read("*line") local uname = f:read("*line")
f:close() f:close()
system["ostype"], system["hostname"], system["osrelease"] = system["ostype"], system["hostname"], system["osrelease"] =
string.match(uname, "([%w]+)[%s]([%w%p]+)[%s]([%w%p]+)") string.match(uname, "([%w]+)[%s]([%w%p]+)[%s]([%w%p]+)")
end end
-- Linux manual page: random(4) -- Linux manual page: random(4)
if kernel.random then if kernel.random then
-- Linux 2.6 default entropy pool is 4096-bits -- Linux 2.6 default entropy pool is 4096-bits
local poolsize = tonumber(kernel.random.poolsize) local poolsize = tonumber(kernel.random.poolsize)
-- Get available entropy and calculate percentage -- Get available entropy and calculate percentage
system["entropy"] = tonumber(kernel.random.entropy_avail) system["entropy"] = tonumber(kernel.random.entropy_avail)
system["entropy_p"] = math.ceil(system["entropy"] * 100 / poolsize) system["entropy_p"] = math.ceil(system["entropy"] * 100 / poolsize)
end end
-- Get user from the environment -- Get user from the environment
system["username"] = los.getenv("USER") system["username"] = los.getenv("USER")
return {system["ostype"], system["osrelease"], system["username"], return {system["ostype"], system["osrelease"], system["username"],
system["hostname"], system["entropy"], system["entropy_p"]} system["hostname"], system["entropy"], system["entropy_p"]}
end end
-- }}} -- }}}

View File

@ -17,31 +17,25 @@ local pkg = {}
-- {{{ Packages widget type -- {{{ Packages widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
-- Initialize counters -- Initialize counters
local updates = 0 local updates = 0
local manager = { local manager = {
["Arch"] = { cmd = "pacman -Qu" }, ["Arch"] = { cmd = "pacman -Qu" },
["Arch C"] = { cmd = "checkupdates" }, ["Arch S"] = { cmd = "checkupdates" },
["Arch S"] = { cmd = "yes | pacman -Sup", sub = 1 }, }
["Debian"] = { cmd = "apt-show-versions -u -b" },
["Ubuntu"] = { cmd = "aptitude search '~U'" },
["Fedora"] = { cmd = "yum list updates", sub = 3 },
["FreeBSD"] ={ cmd = "pkg_version -I -l '<'" },
["Mandriva"]={ cmd = "urpmq --auto-select" }
}
-- Check if updates are available -- Check if updates are available
local _pkg = manager[warg] local _pkg = manager[warg]
local f = io.popen(_pkg.cmd) local f = io.popen(_pkg.cmd)
for line in f:lines() do for line in f:lines() do
updates = updates + 1 updates = updates + 1
end end
f:close() f:close()
return {_pkg.sub and math.max(updates-_pkg.sub, 0) or updates} return {_pkg.sub and math.max(updates-_pkg.sub, 0) or updates}
end end
-- }}} -- }}}

View File

@ -7,10 +7,10 @@
local io = { open = io.open } local io = { open = io.open }
local setmetatable = setmetatable local setmetatable = setmetatable
local string = { local string = {
len = string.len, len = string.len,
sub = string.sub, sub = string.sub,
match = string.match, match = string.match,
gmatch = string.gmatch gmatch = string.gmatch
} }
-- }}} -- }}}
@ -25,35 +25,35 @@ local mddev = {}
-- {{{ RAID widget type -- {{{ RAID widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
mddev[warg] = { mddev[warg] = {
["found"] = false, ["found"] = false,
["active"] = 0, ["active"] = 0,
["assigned"] = 0 ["assigned"] = 0
} }
-- Linux manual page: md(4) -- Linux manual page: md(4)
local f = io.open("/proc/mdstat") local f = io.open("/proc/mdstat")
for line in f:lines() do for line in f:lines() do
if mddev[warg]["found"] then if mddev[warg]["found"] then
local updev = string.match(line, "%[[_U]+%]") local updev = string.match(line, "%[[_U]+%]")
for i in string.gmatch(updev, "U") do for i in string.gmatch(updev, "U") do
mddev[warg]["active"] = mddev[warg]["active"] + 1 mddev[warg]["active"] = mddev[warg]["active"] + 1
end end
break break
elseif string.sub(line, 1, string.len(warg)) == warg then elseif string.sub(line, 1, string.len(warg)) == warg then
mddev[warg]["found"] = true mddev[warg]["found"] = true
for i in string.gmatch(line, "%[[%d]%]") do for i in string.gmatch(line, "%[[%d]%]") do
mddev[warg]["assigned"] = mddev[warg]["assigned"] + 1 mddev[warg]["assigned"] = mddev[warg]["assigned"] + 1
end end
end
end end
end f:close()
f:close()
return {mddev[warg]["assigned"], mddev[warg]["active"]} return {mddev[warg]["assigned"], mddev[warg]["active"]}
end end
-- }}} -- }}}

View File

@ -19,28 +19,28 @@ local thermal = {}
-- {{{ Thermal widget type -- {{{ Thermal widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
local zone = { -- Known temperature data sources local zone = { -- Known temperature data sources
["sys"] = {"/sys/class/thermal/", file = "temp", div = 1000}, ["sys"] = {"/sys/class/thermal/", file = "temp", div = 1000},
["core"] = {"/sys/devices/platform/", file = "temp2_input",div = 1000}, ["core"] = {"/sys/devices/platform/", file = "temp2_input",div = 1000},
["proc"] = {"/proc/acpi/thermal_zone/",file = "temperature"} ["proc"] = {"/proc/acpi/thermal_zone/",file = "temperature"}
} -- Default to /sys/class/thermal } -- Default to /sys/class/thermal
warg = type(warg) == "table" and warg or { warg, "sys" } warg = type(warg) == "table" and warg or { warg, "sys" }
-- Get temperature from thermal zone -- Get temperature from thermal zone
local _thermal = helpers.pathtotable(zone[warg[2]][1] .. warg[1]) local _thermal = helpers.pathtotable(zone[warg[2]][1] .. warg[1])
local data = warg[3] and _thermal[warg[3]] or _thermal[zone[warg[2]].file] local data = warg[3] and _thermal[warg[3]] or _thermal[zone[warg[2]].file]
if data then if data then
if zone[warg[2]].div then if zone[warg[2]].div then
return {data / zone[warg[2]].div} return {data / zone[warg[2]].div}
else -- /proc/acpi "temperature: N C" else -- /proc/acpi "temperature: N C"
return {tonumber(string.match(data, "[%d]+"))} return {tonumber(string.match(data, "[%d]+"))}
end end
end end
return {0} return {0}
end end
-- }}} -- }}}

View File

@ -19,17 +19,17 @@ local uptime = {}
-- {{{ Uptime widget type -- {{{ Uptime widget type
local function worker(format) local function worker(format)
local proc = helpers.pathtotable("/proc") local proc = helpers.pathtotable("/proc")
-- Get system uptime -- Get system uptime
local up_t = math.floor(string.match(proc.uptime, "[%d]+")) local up_t = math.floor(string.match(proc.uptime, "[%d]+"))
local up_d = math.floor(up_t / (3600 * 24)) local up_d = math.floor(up_t / (3600 * 24))
local up_h = math.floor((up_t % (3600 * 24)) / 3600) local up_h = math.floor((up_t % (3600 * 24)) / 3600)
local up_m = math.floor(((up_t % (3600 * 24)) % 3600) / 60) local up_m = math.floor(((up_t % (3600 * 24)) % 3600) / 60)
local l1, l5, l15 = -- Get load averages for past 1, 5 and 15 minutes local l1, l5, l15 = -- Get load averages for past 1, 5 and 15 minutes
string.match(proc.loadavg, "([%d%.]+)[%s]([%d%.]+)[%s]([%d%.]+)") string.match(proc.loadavg, "([%d%.]+)[%s]([%d%.]+)[%s]([%d%.]+)")
return {up_d, up_h, up_m, l1, l5, l15} return {up_d, up_h, up_m, l1, l5, l15}
end end
-- }}} -- }}}

View File

@ -19,35 +19,35 @@ local volume = {}
-- {{{ Volume widget type -- {{{ Volume widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
local mixer_state = { local mixer_state = {
["on"] = "", -- "", ["on"] = "", -- "",
["off"] = "" -- "M" ["off"] = "" -- "M"
} }
-- Get mixer control contents -- Get mixer control contents
local f = io.popen("amixer -M get " .. helpers.shellquote(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()
-- Capture mixer control state: [5%] ... ... [on] -- Capture mixer control state: [5%] ... ... [on]
local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)") local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
-- Handle mixers without data -- Handle mixers without data
if volu == nil then if volu == nil then
return {0, mixer_state["off"]} return {0, mixer_state["off"]}
end end
-- Handle mixers without mute -- Handle mixers without mute
if mute == "" and volu == "0" if mute == "" and volu == "0"
-- Handle mixers that are muted -- Handle mixers that are muted
or mute == "off" then or mute == "off" then
mute = mixer_state["off"] mute = mixer_state["off"]
else else
mute = mixer_state["on"] mute = mixer_state["on"]
end end
return {tonumber(volu), mute} return {tonumber(volu), mute}
end end
-- }}} -- }}}

View File

@ -20,74 +20,74 @@ local weather = {}
-- Initialize function tables -- Initialize function tables
local _weather = { local _weather = {
["{city}"] = "N/A", ["{city}"] = "N/A",
["{wind}"] = "N/A", ["{wind}"] = "N/A",
["{windmph}"] = "N/A", ["{windmph}"] = "N/A",
["{windkmh}"] = "N/A", ["{windkmh}"] = "N/A",
["{sky}"] = "N/A", ["{sky}"] = "N/A",
["{weather}"] = "N/A", ["{weather}"] = "N/A",
["{tempf}"] = "N/A", ["{tempf}"] = "N/A",
["{tempc}"] = "N/A", ["{tempc}"] = "N/A",
["{dewf}"] = "N/A", ["{dewf}"] = "N/A",
["{dewc}"] = "N/A", ["{dewc}"] = "N/A",
["{humid}"] = "N/A", ["{humid}"] = "N/A",
["{press}"] = "N/A" ["{press}"] = "N/A"
} }
-- {{{ Weather widget type -- {{{ Weather widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
-- 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 url = "http://weather.noaa.gov/pub/data/observations/metar/decoded/"..warg local url = "http://weather.noaa.gov/pub/data/observations/metar/decoded/"..warg
local f = io.popen("curl --connect-timeout 1 -fsm 3 "..helpers.shellquote(url)..".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()
-- Check if there was a timeout or a problem with the station -- Check if there was a timeout or a problem with the station
if ws == nil then return _weather end if ws == nil then return _weather end
_weather["{city}"] = -- City and/or area _weather["{city}"] = -- City and/or area
string.match(ws, "^(.+)%,.*%([%u]+%)") or _weather["{city}"] string.match(ws, "^(.+)%,.*%([%u]+%)") or _weather["{city}"]
_weather["{wind}"] = -- Wind direction and degrees if available _weather["{wind}"] = -- Wind direction and degrees if available
string.match(ws, "Wind:[%s][%a]+[%s][%a]+[%s](.+)[%s]at.+$") or _weather["{wind}"] string.match(ws, "Wind:[%s][%a]+[%s][%a]+[%s](.+)[%s]at.+$") or _weather["{wind}"]
_weather["{windmph}"] = -- Wind speed in MPH if available _weather["{windmph}"] = -- Wind speed in MPH if available
string.match(ws, "Wind:[%s].+[%s]at[%s]([%d]+)[%s]MPH") or _weather["{windmph}"] string.match(ws, "Wind:[%s].+[%s]at[%s]([%d]+)[%s]MPH") or _weather["{windmph}"]
_weather["{sky}"] = -- Sky conditions if available _weather["{sky}"] = -- Sky conditions if available
string.match(ws, "Sky[%s]conditions:[%s](.-)[%c]") or _weather["{sky}"] string.match(ws, "Sky[%s]conditions:[%s](.-)[%c]") or _weather["{sky}"]
_weather["{weather}"] = -- Weather conditions if available _weather["{weather}"] = -- Weather conditions if available
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 _weather["{dewf}"] = -- Dew Point in fahrenheit
string.match(ws, "Dew[%s]Point:[%s]([%-]?[%d%.]+).*[%c]") or _weather["{dewf}"] 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
string.match(ws, "Pressure[%s].+%((.+)[%s]hPa%)") or _weather["{press}"] string.match(ws, "Pressure[%s].+%((.+)[%s]hPa%)") or _weather["{press}"]
-- Wind speed in km/h if MPH was available -- Wind speed in km/h if MPH was available
if _weather["{windmph}"] ~= "N/A" then if _weather["{windmph}"] ~= "N/A" then
_weather["{windmph}"] = tonumber(_weather["{windmph}"]) _weather["{windmph}"] = tonumber(_weather["{windmph}"])
_weather["{windkmh}"] = math.ceil(_weather["{windmph}"] * 1.6) _weather["{windkmh}"] = math.ceil(_weather["{windmph}"] * 1.6)
end -- Temperature in °C if °F was available end -- Temperature in °C if °F was available
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 end -- Dew Point in °C if °F was available
if _weather["{dewf}"] ~= "N/A" then if _weather["{dewf}"] ~= "N/A" then
_weather["{dewf}"] = tonumber(_weather["{dewf}"]) _weather["{dewf}"] = tonumber(_weather["{dewf}"])
_weather["{dewc}"] = math.ceil((_weather["{dewf}"] - 32) * 5/9) _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}"])
end end
if _weather["{weather}"] ~= "N/A" then if _weather["{weather}"] ~= "N/A" then
_weather["{weather}"] = helpers.capitalize(_weather["{weather}"]) _weather["{weather}"] = helpers.capitalize(_weather["{weather}"])
end end
return _weather return _weather
end end
-- }}} -- }}}

View File

@ -9,12 +9,12 @@ local math = { ceil = math.ceil }
local setmetatable = setmetatable local setmetatable = setmetatable
local helpers = require("vicious.helpers") local helpers = require("vicious.helpers")
local io = { local io = {
open = io.open, open = io.open,
popen = io.popen popen = io.popen
} }
local string = { local string = {
find = string.find, find = string.find,
match = string.match match = string.match
} }
-- }}} -- }}}
@ -32,60 +32,60 @@ local iwcpaths = { "/sbin", "/usr/sbin", "/usr/local/sbin", "/usr/bin" }
-- {{{ Wireless widget type -- {{{ Wireless widget type
local function worker(format, warg) local function worker(format, warg)
if not warg then return end if not warg then return end
-- Default values -- Default values
local winfo = { local winfo = {
["{ssid}"] = "N/A", ["{ssid}"] = "N/A",
["{mode}"] = "N/A", ["{mode}"] = "N/A",
["{chan}"] = 0, ["{chan}"] = 0,
["{rate}"] = 0, ["{rate}"] = 0,
["{link}"] = 0, ["{link}"] = 0,
["{linp}"] = 0, ["{linp}"] = 0,
["{sign}"] = 0 ["{sign}"] = 0
} }
-- Sbin paths aren't in user PATH, search for the binary -- Sbin paths aren't in user PATH, search for the binary
if iwconfig == "iwconfig" then if iwconfig == "iwconfig" then
for _, p in ipairs(iwcpaths) do for _, p in ipairs(iwcpaths) do
local f = io.open(p .. "/iwconfig", "rb") local f = io.open(p .. "/iwconfig", "rb")
if f then if f then
iwconfig = p .. "/iwconfig" iwconfig = p .. "/iwconfig"
f:close() f:close()
break break
end end
end
end end
end
-- Get data from iwconfig where available -- Get data from iwconfig where available
local f = io.popen(iwconfig .." ".. helpers.shellquote(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()
-- iwconfig wasn't found, isn't executable, or non-wireless interface -- iwconfig wasn't found, isn't executable, or non-wireless interface
if iw == nil or string.find(iw, "No such device") then if iw == nil or string.find(iw, "No such device") then
return winfo return winfo
end end
-- Output differs from system to system, some stats can be -- Output differs from system to system, some stats can be
-- separated by =, and not all drivers report all stats -- separated by =, and not all drivers report all stats
winfo["{ssid}"] = -- SSID can have almost anything in it winfo["{ssid}"] = -- SSID can have almost anything in it
helpers.escape(string.match(iw, 'ESSID[=:]"(.-)"') or winfo["{ssid}"]) helpers.escape(string.match(iw, 'ESSID[=:]"(.-)"') or winfo["{ssid}"])
winfo["{mode}"] = -- Modes are simple, but also match the "-" in Ad-Hoc winfo["{mode}"] = -- Modes are simple, but also match the "-" in Ad-Hoc
string.match(iw, "Mode[=:]([%w%-]*)") or winfo["{mode}"] string.match(iw, "Mode[=:]([%w%-]*)") or winfo["{mode}"]
winfo["{chan}"] = -- Channels are plain digits winfo["{chan}"] = -- Channels are plain digits
tonumber(string.match(iw, "Channel[=:]([%d]+)") or winfo["{chan}"]) 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 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}"]) 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 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}"]) tonumber(string.match(iw, "Link Quality[=:]([%d]+)") or winfo["{link}"])
winfo["{sign}"] = -- Signal level can be a negative value, don't display decibel notation winfo["{sign}"] = -- Signal level can be a negative value, don't display decibel notation
tonumber(string.match(iw, "Signal level[=:]([%-]?[%d]+)") or winfo["{sign}"]) tonumber(string.match(iw, "Signal level[=:]([%-]?[%d]+)") or winfo["{sign}"])
-- Link quality percentage if quality was available -- Link quality percentage if quality was available
if winfo["{link}"] ~= 0 then winfo["{linp}"] = math.ceil(winfo["{link}"] / 0.7) end if winfo["{link}"] ~= 0 then winfo["{linp}"] = math.ceil(winfo["{link}"] / 0.7) end
return winfo return winfo
end end
-- }}} -- }}}

View File

@ -124,9 +124,9 @@ volicon:buttons(awful.util.table.join(
awful.button({ }, 1, awful.button({ }, 1,
function() awful.util.spawn_with_shell("pamixer -t") end), function() awful.util.spawn_with_shell("pamixer -t") end),
awful.button({ }, 4, awful.button({ }, 4,
function() awful.util.spawn_with_shell("pamixer -i 3") end), function() awful.util.spawn_with_shell("pamixer -i 2") end),
awful.button({ }, 5, awful.button({ }, 5,
function() awful.util.spawn_with_shell("pamixer -d 3") end) function() awful.util.spawn_with_shell("pamixer -d 2") end)
)) ))
volpct:buttons(volicon:buttons()) volpct:buttons(volicon:buttons())
volspace:buttons(volicon:buttons()) volspace:buttons(volicon:buttons())
@ -148,22 +148,6 @@ mem = wibox.widget.textbox()
vicious.register(mem, vicious.widgets.mem, "Mem: $1% Use: $2MB Total: $3MB Free: $4MB Swap: $5%", 2) vicious.register(mem, vicious.widgets.mem, "Mem: $1% Use: $2MB Total: $3MB Free: $4MB Swap: $5%", 2)
-- End Mem }}} -- End Mem }}}
-- --
-- {{{ Start Gmail
--mailicon = wibox.widget.imagebox(beautiful.widget_mail)
--mailwidget = wibox.widget.textbox()
--gmail_t = awful.tooltip({ objects = { mailwidget },})
--vicious.register(mailwidget, vicious.widgets.gmail,
-- function (widget, args)
-- gmail_t:set_text(args["{subject}"])
-- gmail_t:add_to_object(mailicon)
-- return args["{count}"]
-- end, 120)
--
-- mailicon:buttons(awful.util.table.join(
-- awful.button({ }, 1, function () awful.util.spawn("urxvt -e mutt", false) end)
-- ))
-- End Gmail }}}
--
-- {{{ Start Wifi -- {{{ Start Wifi
wifiicon = wibox.widget.imagebox() wifiicon = wibox.widget.imagebox()
wifiicon:set_image(beautiful.widget_wifi) wifiicon:set_image(beautiful.widget_wifi)

View File

@ -1,33 +1,33 @@
-- {{{ init environment -- {{{ init environment
local wakka = {} local wakka = {}
local capi = { local capi = {
mouse = mouse, mouse = mouse,
screen = screen screen = screen
} }
-- {{{ display -- {{{ display
-- formats the lines for the notify -- formats the lines for the notify
local function display() local function display()
local lines = "<u>AUR Updates:</u>\n" local lines = "<u>AUR Updates:</u>\n"
local f = io.popen("cower -u", "r") local f = io.popen("cower -u", "r")
local s = f:read('*all') local s = f:read('*all')
line = lines .. "\n" .. s .. "\n" line = lines .. "\n" .. s .. "\n"
f:close() f:close()
return line return line
end end
-- }}} -- }}}
-- }}} -- }}}
function wakka.addToWidget(mywidget) function wakka.addToWidget(mywidget)
mywidget:add_signal('mouse::enter', function () mywidget:add_signal('mouse::enter', function ()
usage = naughty.notify({ usage = naughty.notify({
text = string.format('<span font_desc="%s">%s</span>', "monospace", display()), text = string.format('<span font_desc="%s">%s</span>', "monospace", display()),
timeout = 0, timeout = 0,
hover_timeout = 0.5, hover_timeout = 0.5,
screen = capi.mouse.screen screen = capi.mouse.screen
}) })
end) end)
mywidget:add_signal('mouse::leave', function () naughty.destroy(usage) end) mywidget:add_signal('mouse::leave', function () naughty.destroy(usage) end)
end end
return wakka return wakka

View File

@ -1,39 +1,39 @@
-- {{{ init environment -- {{{ init environment
local wakka = {} local wakka = {}
local capi = { local capi = {
mouse = mouse, mouse = mouse,
screen = screen screen = screen
} }
-- {{{ display -- {{{ display
-- formats the lines for the notify -- formats the lines for the notify
local function display() local function display()
local lines = "<u>Bitcoin:</u>\n" local lines = "<u>Bitcoin:</u>\n"
local tick = "<u>Ask:</u>\n" local tick = "<u>Ask:</u>\n"
local f = io.popen("bitcoind getbalance", "r") local f = io.popen("bitcoind getbalance", "r")
local t = io.popen("curl -q -s https://api.bitcoinaverage.com/ticker/global/AUD/ask", "r") local t = io.popen("curl -q -s https://api.bitcoinaverage.com/ticker/global/AUD/ask", "r")
local s = f:read('*all') local s = f:read('*all')
local g = t:read('*all') local g = t:read('*all')
line = lines .. "\n" .. s .. "\n" line = lines .. "\n" .. s .. "\n"
ticker = tick .. "\n" .. g .. "\n" ticker = tick .. "\n" .. g .. "\n"
f:close() f:close()
t:close() t:close()
-- return line, ticker -- return line, ticker
return string.format('%s%s',line, ticker) return string.format('%s%s',line, ticker)
end end
function wakka.addToWidget(mywidget) function wakka.addToWidget(mywidget)
mywidget:add_signal('mouse::enter', function () mywidget:add_signal('mouse::enter', function ()
run_display = display() run_display = display()
usage = naughty.notify({ usage = naughty.notify({
text = string.format('<span font_desc="%s">%s</span>', "monospace", run_display), text = string.format('<span font_desc="%s">%s</span>', "monospace", run_display),
timeout = 0, timeout = 0,
hover_timeout = 0.5, hover_timeout = 0.5,
screen = capi.mouse.screen screen = capi.mouse.screen
}) })
end) end)
mywidget:add_signal('mouse::leave', function () naughty.destroy(usage) end) mywidget:add_signal('mouse::leave', function () naughty.destroy(usage) end)
end end
return wakka return wakka

View File

@ -1,33 +1,33 @@
-- {{{ init environment -- {{{ init environment
local wakka = {} local wakka = {}
local capi = { local capi = {
mouse = mouse, mouse = mouse,
screen = screen screen = screen
} }
-- {{{ display -- {{{ display
-- formats the lines for the notify -- formats the lines for the notify
local function display() local function display()
local lines = "<u>GFX Temp:</u>\n" local lines = "<u>GFX Temp:</u>\n"
local f = io.popen("/opt/bin/aticonfig --odgt | grep Temperature | cut -c 43-52", "r") local f = io.popen("/opt/bin/aticonfig --odgt | grep Temperature | cut -c 43-52", "r")
local s = f:read('*all') local s = f:read('*all')
line = lines .. "\n" .. s .. "\n" line = lines .. "\n" .. s .. "\n"
f:close() f:close()
return line return line
end end
-- }}} -- }}}
-- }}} -- }}}
function wakka.addToWidget(mywidget) function wakka.addToWidget(mywidget)
mywidget:add_signal('mouse::enter', function () mywidget:add_signal('mouse::enter', function ()
usage = naughty.notify({ usage = naughty.notify({
text = string.format('<span font_desc="%s">%s</span>', "monospace", display()), text = string.format('<span font_desc="%s">%s</span>', "monospace", display()),
timeout = 0, timeout = 0,
hover_timeout = 0.5, hover_timeout = 0.5,
screen = capi.mouse.screen screen = capi.mouse.screen
}) })
end) end)
mywidget:add_signal('mouse::leave', function () naughty.destroy(usage) end) mywidget:add_signal('mouse::leave', function () naughty.destroy(usage) end)
end end
return wakka return wakka

View File

@ -11,8 +11,8 @@ local modkey = "Mod4"
local beautiful = require("beautiful") local beautiful = require("beautiful")
local naughty = require("naughty") local naughty = require("naughty")
local capi = { local capi = {
root = root, root = root,
client = client client = client
} }
module("keydoc") module("keydoc")
@ -23,101 +23,101 @@ local orig = awful.key.new
-- Replacement for awful.key.new -- Replacement for awful.key.new
local function new(mod, key, press, release, docstring) local function new(mod, key, press, release, docstring)
-- Usually, there is no use of release, let's just use it for doc -- Usually, there is no use of release, let's just use it for doc
-- if it's a string. -- if it's a string.
if press and release and not docstring and type(release) == "string" then if press and release and not docstring and type(release) == "string" then
docstring = release docstring = release
release = nil release = nil
end end
local k = orig(mod, key, press, release) local k = orig(mod, key, press, release)
-- Remember documentation for this key (we take the first one) -- Remember documentation for this key (we take the first one)
if k and #k > 0 and docstring then if k and #k > 0 and docstring then
doc[k[1]] = { help = docstring, doc[k[1]] = { help = docstring,
group = currentgroup } group = currentgroup }
end end
return k return k
end end
awful.key.new = new -- monkey patch awful.key.new = new -- monkey patch
-- Turn a key to a string -- Turn a key to a string
local function key2str(key) local function key2str(key)
local sym = key.key or key.keysym local sym = key.key or key.keysym
local translate = { local translate = {
["#14"] = "#", ["#14"] = "#",
[" "] = "Space", [" "] = "Space",
} }
sym = translate[sym] or sym sym = translate[sym] or sym
if not key.modifiers or #key.modifiers == 0 then return sym end if not key.modifiers or #key.modifiers == 0 then return sym end
local result = "" local result = ""
local translate = { local translate = {
[modkey] = "", [modkey] = "",
Shift = "", Shift = "",
Control = "Ctrl", Control = "Ctrl",
} }
for _, mod in pairs(key.modifiers) do for _, mod in pairs(key.modifiers) do
mod = translate[mod] or mod mod = translate[mod] or mod
result = result .. mod .. " + " result = result .. mod .. " + "
end end
return result .. sym return result .. sym
end end
-- Unicode "aware" length function (well, UTF8 aware) -- Unicode "aware" length function (well, UTF8 aware)
-- See: http://lua-users.org/wiki/LuaUnicode -- See: http://lua-users.org/wiki/LuaUnicode
local function unilen(str) local function unilen(str)
local _, count = string.gsub(str, "[^\128-\193]", "") local _, count = string.gsub(str, "[^\128-\193]", "")
return count return count
end end
-- Start a new group -- Start a new group
function group(name) function group(name)
currentgroup = name currentgroup = name
return {} return {}
end end
local function markup(keys) local function markup(keys)
local result = {} local result = {}
-- Compute longest key combination -- Compute longest key combination
local longest = 0 local longest = 0
for _, key in ipairs(keys) do for _, key in ipairs(keys) do
if doc[key] then if doc[key] then
longest = math.max(longest, unilen(key2str(key))) longest = math.max(longest, unilen(key2str(key)))
end
end end
end
local curgroup = nil local curgroup = nil
for _, key in ipairs(keys) do for _, key in ipairs(keys) do
if doc[key] then if doc[key] then
local help, group = doc[key].help, doc[key].group local help, group = doc[key].help, doc[key].group
local skey = key2str(key) local skey = key2str(key)
result[group] = (result[group] or "") .. result[group] = (result[group] or "") ..
'<span font="DejaVu Sans Mono 10" color="' .. beautiful.fg_widget_clock .. '"> ' .. '<span font="DejaVu Sans Mono 10" color="' .. beautiful.fg_widget_clock .. '"> ' ..
string.format("%" .. (longest - unilen(skey)) .. "s ", "") .. skey .. string.format("%" .. (longest - unilen(skey)) .. "s ", "") .. skey ..
'</span> <span color="' .. beautiful.fg_widget_value .. '">' .. '</span> <span color="' .. beautiful.fg_widget_value .. '">' ..
help .. '</span>\n' help .. '</span>\n'
end
end end
end
return result return result
end end
-- Display help in a naughty notification -- Display help in a naughty notification
local nid = nil local nid = nil
function display() function display()
local strings = awful.util.table.join( local strings = awful.util.table.join(
markup(capi.root.keys()), markup(capi.root.keys()),
capi.client.focus and markup(capi.client.focus:keys()) or {}) capi.client.focus and markup(capi.client.focus:keys()) or {})
local result = "" local result = ""
for group, res in pairs(strings) do for group, res in pairs(strings) do
if #result > 0 then result = result .. "\n" end if #result > 0 then result = result .. "\n" end
result = result .. result = result ..
'<span weight="bold" color="' .. beautiful.fg_widget_value_important .. '">' .. '<span weight="bold" color="' .. beautiful.fg_widget_value_important .. '">' ..
group .. "</span>\n" .. res group .. "</span>\n" .. res
end end
nid = naughty.notify({ text = result, nid = naughty.notify({ text = result,
replaces_id = nid, replaces_id = nid,
hover_timeout = 0.1, hover_timeout = 0.1,
timeout = 30 }).id timeout = 30 }).id
end end

View File

@ -1,33 +1,33 @@
-- {{{ init environment -- {{{ init environment
local wakka = {} local wakka = {}
local capi = { local capi = {
mouse = mouse, mouse = mouse,
screen = screen screen = screen
} }
-- {{{ display -- {{{ display
-- formats the lines for the notify -- formats the lines for the notify
local function display() local function display()
local lines = "<u>Namecoin:</u>\n" local lines = "<u>Namecoin:</u>\n"
local f = io.popen("namecoind getbalance", "r") local f = io.popen("namecoind getbalance", "r")
local s = f:read('*all') local s = f:read('*all')
line = lines .. "\n" .. s .. "\n" line = lines .. "\n" .. s .. "\n"
f:close() f:close()
return line return line
end end
-- }}} -- }}}
-- }}} -- }}}
function wakka.addToWidget(mywidget) function wakka.addToWidget(mywidget)
mywidget:add_signal('mouse::enter', function () mywidget:add_signal('mouse::enter', function ()
usage = naughty.notify({ usage = naughty.notify({
text = string.format('<span font_desc="%s">%s</span>', "monospace", display()), text = string.format('<span font_desc="%s">%s</span>', "monospace", display()),
timeout = 0, timeout = 0,
hover_timeout = 0.5, hover_timeout = 0.5,
screen = capi.mouse.screen screen = capi.mouse.screen
}) })
end) end)
mywidget:add_signal('mouse::leave', function () naughty.destroy(usage) end) mywidget:add_signal('mouse::leave', function () naughty.destroy(usage) end)
end end
return wakka return wakka

View File

@ -1,33 +1,33 @@
-- {{{ init environment -- {{{ init environment
local wakka = {} local wakka = {}
local capi = { local capi = {
mouse = mouse, mouse = mouse,
screen = screen screen = screen
} }
-- {{{ display -- {{{ display
-- formats the lines for the notify -- formats the lines for the notify
local function display() local function display()
local lines = "<u>Pacman Updates:</u>\n" local lines = "<u>Pacman Updates:</u>\n"
local f = io.popen("pacman -Qqu", "r") local f = io.popen("pacman -Qqu", "r")
local s = f:read('*all') local s = f:read('*all')
line = lines .. "\n" .. s .. "\n" line = lines .. "\n" .. s .. "\n"
f:close() f:close()
return line return line
end end
-- }}} -- }}}
-- }}} -- }}}
function wakka.addToWidget(mywidget) function wakka.addToWidget(mywidget)
mywidget:add_signal('mouse::enter', function () mywidget:add_signal('mouse::enter', function ()
usage = naughty.notify({ usage = naughty.notify({
text = string.format('<span font_desc="%s">%s</span>', "monospace", display()), text = string.format('<span font_desc="%s">%s</span>', "monospace", display()),
timeout = 0, timeout = 0,
hover_timeout = 0.5, hover_timeout = 0.5,
screen = capi.mouse.screen screen = capi.mouse.screen
}) })
end) end)
mywidget:add_signal('mouse::leave', function () naughty.destroy(usage) end) mywidget:add_signal('mouse::leave', function () naughty.destroy(usage) end)
end end
return wakka return wakka

View File

@ -1,33 +1,33 @@
-- {{{ init environment -- {{{ init environment
local wakka = {} local wakka = {}
local capi = { local capi = {
mouse = mouse, mouse = mouse,
screen = screen screen = screen
} }
-- {{{ display -- {{{ display
-- formats the lines for the notify -- formats the lines for the notify
local function display() local function display()
local lines = "<u>AUR Updates:</u>\n" local lines = "<u>AUR Updates:</u>\n"
local f = io.popen("archey", "r") local f = io.popen("archey", "r")
local s = f:read('*all') local s = f:read('*all')
line = lines .. "\n" .. s .. "\n" line = lines .. "\n" .. s .. "\n"
f:close() f:close()
return line return line
end end
-- }}} -- }}}
-- }}} -- }}}
function wakka.addToWidget(mywidget) function wakka.addToWidget(mywidget)
mywidget:add_signal('mouse::enter', function () mywidget:add_signal('mouse::enter', function ()
usage = naughty.notify({ usage = naughty.notify({
text = string.format('<span font_desc="%s">%s</span>', "monospace", display()), text = string.format('<span font_desc="%s">%s</span>', "monospace", display()),
timeout = 0, timeout = 0,
hover_timeout = 0.5, hover_timeout = 0.5,
screen = capi.mouse.screen screen = capi.mouse.screen
}) })
end) end)
mywidget:add_signal('mouse::leave', function () naughty.destroy(usage) end) mywidget:add_signal('mouse::leave', function () naughty.destroy(usage) end)
end end
return wakka return wakka

View File

@ -41,6 +41,5 @@ bspc config pointer_action3 resize_corner
bspc rule -a thunar desktop='^1' state=floating follow=on bspc rule -a thunar desktop='^1' state=floating follow=on
bspc rule -a firefox desktop='^2' bspc rule -a firefox desktop='^2'
bspc rule -a Galculator state=floating
bspc rule -a Void_Exit_Session state=floating layer=above bspc rule -a Void_Exit_Session state=floating layer=above
bspc rule -a Exit_Session state=floating layer=above bspc rule -a Exit_Session state=floating layer=above

View File

@ -26,23 +26,17 @@ no-fading-destroyed-argb = false;
# Backend # Backend
backend = "xrender"; backend = "xrender";
vsync = "opengl"; vsync = "none";
mark-wmwin-focused = true;
mark-ovredir-focused = true;
detect-rounded-corners = true;
detect-client-opacity = true;
refresh-rate = 0;
paint-on-overlay = true; paint-on-overlay = true;
mark-wmwin-focused = true;
unredir-if-possible = true; unredir-if-possible = true;
detect-transient = true; detect-rounded-corners = true;
detect-client-leader = true;
# GLX backend # GLX backend
glx-no-stencil = true; glx-no-stencil = true;
glx-no-rebind-pixmap = true; glx-no-rebind-pixmap = true;
opacity-rule = [ opacity-rule = [
"85:class_g *?= 'xterm'",
"0:_NET_WM_STATE@:32a * = '_NET_WM_STATE_HIDDEN'" "0:_NET_WM_STATE@:32a * = '_NET_WM_STATE_HIDDEN'"
]; ];

View File

@ -1,27 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd"> <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig> <fontconfig>
<match target="font"> <match target="font">
<edit name="antialias" mode="assign"> <edit name="antialias" mode="assign">
<bool>true</bool> <bool>true</bool>
</edit> </edit>
<edit name="hinting" mode="assign"> <edit name="hinting" mode="assign">
<bool>true</bool> <bool>true</bool>
</edit> </edit>
<edit name="hintstyle" mode="assign"> <edit name="hintstyle" mode="assign">
<const>hintslight</const> <const>hintslight</const>
</edit> </edit>
<edit name="rgba" mode="assign"> <edit name="rgba" mode="assign">
<const>rgb</const> <const>rgb</const>
</edit> </edit>
<edit name="autohint" mode="assign"> <edit name="autohint" mode="assign">
<bool>true</bool> <bool>true</bool>
</edit> </edit>
<edit name="lcdfilter" mode="assign"> <edit name="lcdfilter" mode="assign">
<const>lcddefault</const> <const>lcddefault</const>
</edit> </edit>
<edit name="dpi" mode="assign"> <edit name="dpi" mode="assign">
<double>96</double> <double>96</double>
</edit> </edit>
</match> </match>
</fontconfig> </fontconfig>

View File

@ -5,7 +5,7 @@ file:///home/liveuser/Pictures
file:///home/liveuser/Music file:///home/liveuser/Music
file:///home/liveuser/Videos file:///home/liveuser/Videos
file:///home/liveuser/Templates file:///home/liveuser/Templates
file:///home/liveuser/.config .config file:///home/liveuser/.config
file:///home/liveuser/.config/polybar file:///home/liveuser/.config/polybar
file:///home/liveuser/.config/termite file:///home/liveuser/.config/termite
file:///home/liveuser/.config/openbox file:///home/liveuser/.config/openbox

View File

@ -62,19 +62,13 @@ exec_always --no-startup-id al-polybar-session
exec_always --no-startup-id nitrogen --restore exec_always --no-startup-id nitrogen --restore
exec_always --no-startup-id xrdb -load ~/.Xresources exec_always --no-startup-id xrdb -load ~/.Xresources
# Trayer
exec_always --no-startup-id pkill trayer; trayer --edge bottom \
--align left --heighttype pixel --height 18 --widthtype request \
--SetDockType false --expand true --transparent true --alpha 255
# If you have a numpad you may want to enable this # If you have a numpad you may want to enable this
# exec_always --no-startup-id numlockx on # exec_always --no-startup-id numlockx on
# run once # run once
exec --no-startup-id ksuperkey -e 'Super_L=Alt_L|F1'
exec --no-startup-id al-compositor --start
exec --no-startup-id nitrogen --restore
exec --no-startup-id xfsettingsd exec --no-startup-id xfsettingsd
exec --no-startup-id al-compositor --start
exec --no-startup-id ksuperkey -e 'Super_L=Alt_L|F1'
exec --no-startup-id /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 exec --no-startup-id /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1
########################################################### ###########################################################

View File

@ -124,7 +124,7 @@ super + alt + shift + {h,j,k,l}
super + {Left,Down,Up,Right} super + {Left,Down,Up,Right}
bspc node -v {-20 0,0 20,0 -20,20 0} bspc node -v {-20 0,0 20,0 -20,20 0}
# volume control keys
XF86AudioMute XF86AudioMute
pamixer -t pamixer -t
XF86AudioRaiseVolume XF86AudioRaiseVolume

View File

@ -2,6 +2,6 @@
<channel name="keyboards" version="1.0"> <channel name="keyboards" version="1.0">
<property name="Default" type="empty"> <property name="Default" type="empty">
<property name="Numlock" type="bool" value="true"/> <property name="Numlock" type="bool" value="false"/>
</property> </property>
</channel> </channel>

View File

@ -6,17 +6,17 @@
<property name="sleep-button-action" type="uint" value="1"/> <property name="sleep-button-action" type="uint" value="1"/>
<property name="hibernate-button-action" type="uint" value="2"/> <property name="hibernate-button-action" type="uint" value="2"/>
<property name="brightness-switch-restore-on-exit" type="int" value="1"/> <property name="brightness-switch-restore-on-exit" type="int" value="1"/>
<property name="brightness-switch" type="int" value="0"/> <property name="brightness-switch" type="int" value="1"/>
<property name="lid-action-on-battery" type="uint" value="1"/> <property name="lid-action-on-battery" type="uint" value="1"/>
<property name="lid-action-on-ac" type="uint" value="1"/> <property name="lid-action-on-ac" type="uint" value="1"/>
<property name="logind-handle-lid-switch" type="bool" value="true"/> <property name="logind-handle-lid-switch" type="bool" value="true"/>
<property name="dpms-on-ac-off" type="uint" value="0"/> <property name="dpms-on-ac-off" type="uint" value="0"/>
<property name="dpms-on-ac-sleep" type="uint" value="0"/> <property name="dpms-on-ac-sleep" type="uint" value="0"/>
<property name="blank-on-ac" type="int" value="0"/> <property name="blank-on-ac" type="int" value="0"/>
<property name="show-tray-icon" type="bool" value="true"/> <property name="show-tray-icon" type="bool" value="false"/>
<property name="general-notification" type="bool" value="false"/> <property name="general-notification" type="bool" value="false"/>
<property name="inactivity-on-ac" type="uint" value="14"/> <property name="inactivity-on-ac" type="uint" value="14"/>
<property name="lock-screen-suspend-hibernate" type="bool" value="false"/> <property name="lock-screen-suspend-hibernate" type="bool" value="false"/>
<property name="dpms-enabled" type="bool" value="false"/> <property name="dpms-enabled" type="bool" value="true"/>
</property> </property>
</channel> </channel>

View File

@ -28,8 +28,8 @@
<property name="KeyThemeName" type="empty"/> <property name="KeyThemeName" type="empty"/>
<property name="ToolbarStyle" type="string" value="icons"/> <property name="ToolbarStyle" type="string" value="icons"/>
<property name="ToolbarIconSize" type="empty"/> <property name="ToolbarIconSize" type="empty"/>
<property name="MenuImages" type="bool" value="false"/> <property name="MenuImages" type="bool" value="true"/>
<property name="ButtonImages" type="bool" value="false"/> <property name="ButtonImages" type="bool" value="true"/>
<property name="MenuBarAccel" type="empty"/> <property name="MenuBarAccel" type="empty"/>
<property name="CursorThemeName" type="string" value="ArchLabs-Light"/> <property name="CursorThemeName" type="string" value="ArchLabs-Light"/>
<property name="CursorThemeSize" type="empty"/> <property name="CursorThemeSize" type="empty"/>

View File

@ -28,8 +28,8 @@
<property name="KeyThemeName" type="empty"/> <property name="KeyThemeName" type="empty"/>
<property name="ToolbarStyle" type="string" value="icons"/> <property name="ToolbarStyle" type="string" value="icons"/>
<property name="ToolbarIconSize" type="empty"/> <property name="ToolbarIconSize" type="empty"/>
<property name="MenuImages" type="bool" value="false"/> <property name="MenuImages" type="bool" value="true"/>
<property name="ButtonImages" type="bool" value="false"/> <property name="ButtonImages" type="bool" value="true"/>
<property name="MenuBarAccel" type="empty"/> <property name="MenuBarAccel" type="empty"/>
<property name="CursorThemeName" type="string" value="ArchLabs-Light"/> <property name="CursorThemeName" type="string" value="ArchLabs-Light"/>
<property name="CursorThemeSize" type="empty"/> <property name="CursorThemeSize" type="empty"/>

View File

@ -41,14 +41,12 @@ kbdrate -d 400 -r 50
# 1/1 mouse acceleration # 1/1 mouse acceleration
xset m 1/1 xset m 1/1
# Do NOT put commands below the exec lines # Do NOT put commands below the exec lines
case $session in case $session in
i3|i3wm) exec i3 ;; i3|i3wm) exec i3 ;;
bsp|bspwm) exec bspwm ;; bsp|bspwm) exec bspwm ;;
xfce|xfce4) exec startxfce4 ;; xfce|xfce4) exec startxfce4 ;;
openbox) exec openbox-session ;; openbox) exec openbox-session ;;
awesome) exec awesome ;; awesome) exec awesome ;;
dwm) exec dwm ;; *) exec "$1" # Unknown, try running it
*) exec "$1" # Unknown, try running it
esac esac

View File

@ -3,8 +3,8 @@
# sourced at boot by xinit # sourced at boot by xinit
[ -d /sbin ] && PATH="$PATH:/sbin" [ -d /sbin ] && PATH="$PATH:/sbin"
[ -d /usr/sbin ] && PATH="$PATH:/usr/sbin" [ -d /usr/sbin ] && PATH="$PATH:/usr/sbin"
[ -d ~/bin ] && PATH="$HOME/bin:$PATH" [ -d "$HOME/bin" ] && PATH="$HOME/bin:$PATH"
export XDG_CONFIG_HOME="$HOME/.config" export XDG_CONFIG_HOME="$HOME/.config"

View File

@ -1,5 +1,5 @@
# .zprofile # .zprofile
# sourced by zsh when used as a login shell # sourced by zsh when used as a login shell
# automatically run startx when logging in to tty1 # automatically run startx when logging in on tty1
[[ -z $DISPLAY ]] && [[ $XDG_VTNR -eq 1 ]] && exec startx -- vt1 &>/dev/null [[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && exec startx -- vt1 &>/dev/null

View File

@ -65,7 +65,7 @@ while getopts ":hvqwcbrl" opt; do
*Lock) i3lock-fancy ;; *Lock) i3lock-fancy ;;
*Logout) session-logout ;; *Logout) session-logout ;;
*Reboot) systemctl reboot ;; *Reboot) systemctl reboot ;;
*Shutdown) systemctl poweroff *Shutdown) systemctl -i poweroff
esac esac
;; ;;
*) *)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
Name=$(basename "$0") Name=$(basename "$0")
Version="0.1" Version="0.2"
_usage() { _usage() {
cat <<EOF cat <<EOF
@ -43,7 +43,7 @@ toggle_polybar() {
toggle_compton() { toggle_compton() {
if [[ $opt -eq 1 ]]; then if (( $opt == 1 )); then
if [[ $(pidof compton) ]]; then if [[ $(pidof compton) ]]; then
al-compositor --stop al-compositor --stop
else else
@ -65,7 +65,7 @@ toggle_compton() {
toggle_redshift() { toggle_redshift() {
if [[ $opt -eq 1 ]]; then if (( $opt == 1 )); then
if [[ $(pidof redshift) ]]; then if [[ $(pidof redshift) ]]; then
pkill redshift pkill redshift
else else
@ -93,7 +93,7 @@ toggle_redshift() {
toggle_caffeine() { toggle_caffeine() {
if [[ $opt -eq 1 ]]; then if (( $opt == 1 )); then
if [[ $(pidof caffeine) ]]; then if [[ $(pidof caffeine) ]]; then
killall caffeine killall caffeine
else else

View File

@ -8,26 +8,26 @@ total() { UPD=$(checkupdates | wc -l) ;}
while true; do while true; do
total total
if hash notify-send &>/dev/null; then if hash notify-send &>/dev/null; then
if [[ $UPD -gt 50 ]]; then if (( $UPD > 50 )); then
notify-send -u critical -i $ICON "You really need to update!!" "$UPD New packages" notify-send -u critical -i $ICON "You really need to update!!" "$UPD New packages"
elif [[ $UPD -gt 25 ]]; then elif (( $UPD > 25 )); then
notify-send -u normal -i $ICON "You should update soon" "$UPD New packages" notify-send -u normal -i $ICON "You should update soon" "$UPD New packages"
elif [[ $UPD -gt 2 ]]; then elif (( $UPD > 2 )); then
notify-send -u low -i $ICON "$UPD New packages" notify-send -u low -i $ICON "$UPD New packages"
fi fi
fi fi
while [[ $UPD -gt 0 ]]; do while (( $UPD > 0 )); do
if [[ $UPD -eq 1 ]]; then if (( $UPD == 1 )); then
echo "$UPD Update" echo "$UPD Update"
elif [[ $UPD -gt 1 ]]; then elif (( $UPD > 1 )); then
echo "$UPD Updates" echo "$UPD Updates"
fi fi
sleep 10 sleep 10
total total
done done
while [[ $UPD -eq 0 ]]; do while (( $UPD == 0 )); do
echo $BAR_ICON echo $BAR_ICON
sleep 1800 sleep 1800
total total