--[[
Licensed under GNU General Public License v2
- * (c) 2013, Luke Bonham
+ * (c) 2018, Uli Schlacter
+ * (c) 2018, Otto Modinos
+ * (c) 2013, Luca CPZ
--]]
-local helpers = require("lain.helpers")
-local shell = require("awful.util").shell
-local focused = require("awful.screen").focused
-local wibox = require("wibox")
-local naughty = require("naughty")
-local string = string
-local tonumber = tonumber
-
--- File system disk space usage
+local helpers = require("lain.helpers")
+local Gio = require("lgi").Gio
+local focused = require("awful.screen").focused
+local wibox = require("wibox")
+local naughty = require("naughty")
+local math = math
+local string = string
+local tconcat = table.concat
+local type = type
+local tonumber = tonumber
+local query_size = Gio.FILE_ATTRIBUTE_FILESYSTEM_SIZE
+local query_free = Gio.FILE_ATTRIBUTE_FILESYSTEM_FREE
+local query_used = Gio.FILE_ATTRIBUTE_FILESYSTEM_USED
+local query = query_size .. "," .. query_free .. "," .. query_used
+
+-- File systems info
-- lain.widget.fs
local function factory(args)
- local fs = { unit = { ["mb"] = 1024, ["gb"] = 1024^2 }, widget = wibox.widget.textbox() }
+ local fs = {
+ widget = wibox.widget.textbox(),
+ units = {
+ [1] = "Kb", [2] = "Mb", [3] = "Gb",
+ [4] = "Tb", [5] = "Pb", [6] = "Eb",
+ [7] = "Zb", [8] = "Yb"
+ }
+ }
function fs.hide()
if not fs.notification then return end
end
function fs.show(seconds, scr)
- fs.update()
- fs.hide()
-
- if fs.followtag then
- fs.notification_preset.screen = focused()
- else
- fs.notification_preset.screen = scr or 1
- end
-
- fs.notification = naughty.notify({
+ fs.hide(); fs.update()
+ fs.notification_preset.screen = fs.followtag and focused() or scr or 1
+ fs.notification = naughty.notify {
preset = fs.notification_preset,
- timeout = seconds or 5
- })
+ timeout = type(seconds) == "number" and seconds or 5
+ }
end
- local args = args or {}
- local timeout = args.timeout or 600
- local partition = args.partition or "/"
- local showpopup = args.showpopup or "on"
- local notify = args.notify or "on"
- local settings = args.settings or function() end
+ local args = args or {}
+ local timeout = args.timeout or 600
+ local partition = args.partition
+ local threshold = args.threshold or 99
+ local showpopup = args.showpopup or "on"
+ local settings = args.settings or function() end
- fs.options = args.options
fs.followtag = args.followtag or false
fs.notification_preset = args.notification_preset
}
end
- helpers.set_map(partition, false)
-
function fs.update()
- fs_info, fs_now = {}, {}
- helpers.async({ shell, "-c", "/usr/bin/env LC_ALL=C df -k --output=target,size,used,avail,pcent" }, function(f)
- for line in string.gmatch(f, "\n[^\n]+") do
- local m,s,u,a,p = string.match(line, "(/.-%s).-(%d+).-(%d+).-(%d+).-([%d]+)%%")
- m = m:gsub(" ", "") -- clean target from any whitespace
-
- fs_info[m .. " size_mb"] = string.format("%.1f", tonumber(s) / fs.unit["mb"])
- fs_info[m .. " size_gb"] = string.format("%.1f", tonumber(s) / fs.unit["gb"])
- fs_info[m .. " used_mb"] = string.format("%.1f", tonumber(u) / fs.unit["mb"])
- fs_info[m .. " used_gb"] = string.format("%.1f", tonumber(u) / fs.unit["gb"])
- fs_info[m .. " used_p"] = p
- fs_info[m .. " avail_mb"] = string.format("%.1f", tonumber(a) / fs.unit["mb"])
- fs_info[m .. " avail_gb"] = string.format("%.1f", tonumber(a) / fs.unit["gb"])
- fs_info[m .. " avail_p"] = string.format("%d", 100 - tonumber(p))
+ local notifytable = { [1] = string.format("%-10s %-5s %s\t%s\t\n", "path", "used", "free", "size") }
+ local pathlen = 10
+ local maxpathidx = 1
+ fs_now = {}
+
+ for _, mount in ipairs(Gio.unix_mounts_get()) do
+ local path = Gio.unix_mount_get_mount_path(mount)
+ local root = Gio.File.new_for_path(path)
+ local info = root:query_filesystem_info(query)
+
+ if info then
+ local size = info:get_attribute_uint64(query_size)
+ local used = info:get_attribute_uint64(query_used)
+ local free = info:get_attribute_uint64(query_free)
+
+ if size > 0 then
+ local units = math.floor(math.log(size)/math.log(1024))
+
+ fs_now[path] = {
+ units = fs.units[units],
+ percentage = math.floor(100 * used / size), -- used percentage
+ size = size / math.pow(1024, math.floor(units)),
+ used = used / math.pow(1024, math.floor(units)),
+ free = free / math.pow(1024, math.floor(units))
+ }
+
+ if fs_now[path].percentage > 0 then -- don't notify unused file systems
+ notifytable[#notifytable+1] = string.format("\n%-10s %-3s\t%.2f\t%.2f\t%s", path,
+ math.floor(fs_now[path].percentage) .. "%", fs_now[path].free, fs_now[path].size,
+ fs_now[path].units)
+
+ if #path > pathlen then
+ pathlen = #path
+ maxpathidx = #notifytable
+ end
+ end
+ end
end
+ end
+
+ widget = fs.widget
+ settings()
- fs_now.size_mb = fs_info[partition .. " size_mb"] or "N/A"
- fs_now.size_gb = fs_info[partition .. " size_gb"] or "N/A"
- fs_now.used = fs_info[partition .. " used_p"] or "N/A"
- fs_now.used_mb = fs_info[partition .. " used_mb"] or "N/A"
- fs_now.used_gb = fs_info[partition .. " used_gb"] or "N/A"
- fs_now.available = fs_info[partition .. " avail_p"] or "N/A"
- fs_now.available_mb = fs_info[partition .. " avail_mb"] or "N/A"
- fs_now.available_gb = fs_info[partition .. " avail_gb"] or "N/A"
-
- notification_preset = fs.notification_preset
- widget = fs.widget
- settings()
-
- if notify == "on" and tonumber(fs_now.used) and tonumber(fs_now.used) >= 99 and not helpers.get_map(partition) then
- naughty.notify({
+ if partition and fs_now[partition] and fs_now[partition].percentage >= threshold then
+ if not helpers.get_map(partition) then
+ naughty.notify {
preset = naughty.config.presets.critical,
title = "Warning",
- text = partition .. " is full",
- })
+ text = string.format("%s is above %d%% (%d%%)", partition, threshold, fs_now[partition].percentage)
+ }
helpers.set_map(partition, true)
else
helpers.set_map(partition, false)
end
- end)
+ end
+
+ if pathlen > 10 then -- formatting aesthetics
+ local pathspaces
+ for i = 1, #notifytable do
+ pathspaces = notifytable[i]:match("[ ]+")
+ if i ~= maxpathidx and pathspaces then
+ notifytable[i] = notifytable[i]:gsub(pathspaces, pathspaces .. string.rep(" ", pathlen - 10))
+ end
+ end
+ end
- local notifycmd = (fs.options and string.format("dfs %s", fs.options)) or "dfs"
- helpers.async(helpers.scripts_dir .. notifycmd, function(ws)
- fs.notification_preset.text = ws:gsub("\n*$", "")
- end)
+ fs.notification_preset.text = tconcat(notifytable)
end
if showpopup == "on" then
fs.widget:connect_signal('mouse::leave', function () fs.hide() end)
end
- helpers.newtimer(partition, timeout, fs.update)
+ helpers.newtimer(partition or "fs", timeout, fs.update)
return fs
end