feat: conky is eating my life

This commit is contained in:
Kat Inskip 2025-03-18 18:32:41 -07:00
parent b7c510de28
commit 34bc9ae04e
Signed by: kat
GPG key ID: 465E64DECEA8CF0F
15 changed files with 1830 additions and 98 deletions

View file

@ -0,0 +1,197 @@
local _dir_ = debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])") or "./"
package.path = _dir_ .. "?.lua"
kat = require("kat")
liluat = require("liluat")
ftcsv = require("ftcsv")
function tpl(t)
local ct = liluat.compile(t, { start_tag = "{%", end_tag = "%}" })
return function(values)
return liluat.render(ct, values)
end
end
function string.split(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t = {}
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
table.insert(t, str)
end
return t
end
components = {}
local base_font = "Monaspace Krypton"
local formats = {
h1 = string.format("%s:bold:size=16", base_font),
font = "${font %s}%s$font",
item = "${color grey}%s:$color",
}
local font_formats = {
h1 = "not_nil",
}
function conky_fmt(trigger, ...)
text = table.concat({...}, " ")
if font_formats[trigger] ~= nil then
return conky_parse(string.format(formats.font, formats[trigger], text))
else
return conky_parse(string.format(formats[trigger], text))
end
end
function cpu_model()
return string.format([=[${execi %i grep model /proc/cpuinfo | cut -d : -f2 | tail -1 | sed 's/\s//' | sed 's/ [[:digit:]]*-Core Processor$//g'}]=], kat.exec_interval)
end
function cpu_sct()
return string.format("${execi %i %scpu_sct.sh}", kat.exec_interval, kat.root_dir)
end
function conky_cpu_section()
local cpu_tpl = tpl([[
${lua fmt h1 CPU} ${hr}
${color grey}Variety:$color {%= cpu_model() %} {%= cpu_sct() %}
${cpugraph}
${color grey}Frequency:$color ${freq_g} GHz
${color grey}Usage:$color $cpu%
]])
return conky_parse(cpu_tpl({ cpu_model = cpu_model, cpu_sct = cpu_sct }))
end
function gpu_query(query)
return string.format([[${execi %i nvidia-smi --query-gpu=%s --format=csv,noheader | sed 's/\d*\s\%%//' }]], 15, query)
end
-- GPU Query
local query_headers = {
"index",
"name",
"driver_version",
"fan.speed",
"utilization.gpu",
"utilization.memory",
"utilization.encoder",
"utilization.decoder",
"clocks.current.graphics",
"clocks.current.sm",
"clocks.current.memory",
"clocks.current.video",
"memory.used",
"memory.total",
"temperature.gpu",
}
local gpu_display_templates = {
index = "${lua fmt h1 GPU %s} ${hr}",
default = "${lua fmt item %s} %s",
}
local gpu_header_aliases = {
["name"] = "Card",
["driver_version"] = "Driver Version",
["fan.speed"] = "Fan Speed",
["utilization.gpu"] = "Core Usage",
["utilization.memory"] = "Memory Usage",
["utilization.encoder"] = "Encoder Usage",
["utilization.decoder"] = "Decoder Usage",
["clocks.current.graphics"] = "Core Frequency",
["clocks.current.sm"] = "SM Frequency",
["clocks.current.memory"] = "Memory Frequency",
["clocks.current.video"] = "Video Frequency",
["memory.used"] = "Memory Used",
["memory.total"] = "Memory Total",
["temperature.gpu"] = "Temperature",
};
-- Reverse index
local query_headers_index = {}
for i, header in ipairs(query_headers) do
query_headers_index[header] = i
end
-- Command generation caching
local query_header_string = table.concat(query_headers, ",")
local query_command = string.format("nvidia-smi --query-gpu=%s --format=csv,nounits", query_header_string)
local headers = nil
function gpu_csv_query()
local gpus = {}
local query_ran = io.popen(query_command)
local query = query_ran:read("*all")
local query = query:gsub(",%s", ",")
local items, raw_headers = ftcsv.parse(query, {
loadFromString = true,
})
if headers == nil then
headers = {}
for i, heading in ipairs(raw_headers) do
local heading_split = string.split(heading)
local query_unit
local key = heading_split[1]
-- if the heading does not have a [unit] section
if #heading_split == 1 then
-- use a table to define what the key's unit should be
local keys_to_units = {
["temperature.gpu"] = "°C",
index = nil,
driver_version = nil,
name = nil,
}
-- give it a unit
query_unit = keys_to_units[key]
else
query_unit = string.sub(heading_split[2], 2, -2)
local unit_remap = {
MiB = " MiB"
}
if unit_remap[query_unit] ~= nil then
query_unit = unit_remap[query_unit]
end
end
headers[heading] = {
clean = key,
unit = query_unit
}
end
end
for i, gpu in pairs(items) do
current_gpu = {}
for header, data in pairs(gpu) do
local cur_header = headers[header]
local subformat = "%s%s"
local unit = cur_header.unit or ""
data_sf = string.format(subformat, data, unit)
local display_idx = query_headers_index[cur_header.clean] or 500
if gpu_display_templates[cur_header.clean] ~= nil then
display = string.format(gpu_display_templates[cur_header.clean], data_sf)
else
display = string.format(gpu_display_templates.default, gpu_header_aliases[cur_header.clean], data_sf)
end
current_gpu[display_idx] = display
end
gpus[i] = current_gpu
end
return gpus
end
-- GPU Display
function conky_gpu_section()
gpus = gpu_csv_query()
-- TODO: Replace NVIDIA-SMI separate calls with all 1 call and a CSV parsing
local text = ""
for idx, gpu in pairs(gpus) do
for i=1,#gpu do
text = text .. string.format("%s\n", gpu[i])
end
end
return conky_parse(text)
end
return components