From 6b7956fe6b916362eceb014ef6e092c6fae015c6 Mon Sep 17 00:00:00 2001 From: tv Date: Thu, 12 Nov 2026 18:06:27 +0000 Subject: cgit-about-filter: share column widths between tables --- .../simple/cgit-about-filter/cgit-about-filter.lua | 90 ++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/pkgs/simple/cgit-about-filter/cgit-about-filter.lua b/pkgs/simple/cgit-about-filter/cgit-about-filter.lua index d4f441a..cd20d54 100644 --- a/pkgs/simple/cgit-about-filter/cgit-about-filter.lua +++ b/pkgs/simple/cgit-about-filter/cgit-about-filter.lua @@ -96,6 +96,95 @@ div#cgit div#summary td + td { ]] +-- Column widths, shared by all tables with the same header. A column's +-- weight is the larger of its longest word and its average cell length, in +-- characters; code counts more, as monospace is wider. Narrow columns get a +-- fixed width, the others a share of what's left. +local code_weight = 1.25 +local narrow = 12 + +local function length(s) + s = s:gsub("&#?%w+;", "x") + return select(2, s:gsub("[^\128-\191]", "")) +end + +local function cell_weights(cell) + local longest, total = 0, 0 + local function add(text, factor) + for word in text:gmatch("%S+") do + local n = length(word) * factor + longest = math.max(longest, n) + total = total + n + 1 + end + end + for code in cell:gmatch("(.-)") do + add((code:gsub("<[^>]+>", "")), code_weight) + end + add((cell:gsub(".-", " "):gsub("<[^>]+>", " ")), 1) + return longest, math.max(total - 1, 0) +end + +local function cells(row) + local result = {} + for cell in row:gmatch("]*>(.-)") do + table.insert(result, cell) + end + return result +end + +local function header(tbl) + return table.concat(cells(tbl:match("(.-)") or ""), "\0") +end + +local function column_widths(output) + local stats = {} + for tbl in output:gmatch(".-
") do + local key = header(tbl) + stats[key] = stats[key] or { rows = 0, longest = {}, total = {} } + local s = stats[key] + for row in tbl:gmatch("(.-)") do + s.rows = s.rows + 1 + for i, cell in ipairs(cells(row)) do + local longest, total = cell_weights(cell) + s.longest[i] = math.max(s.longest[i] or 0, longest) + s.total[i] = (s.total[i] or 0) + total + end + end + end + local widths = {} + for key, s in pairs(stats) do + local weights, wide = {}, 0 + for i = 1, #s.longest do + weights[i] = math.max(s.longest[i], s.total[i] / s.rows) + if weights[i] > narrow then + wide = wide + weights[i] + end + end + local cols = {} + for i, weight in ipairs(weights) do + if weight > narrow then + cols[i] = string.format('', 100 * weight / wide) + else + cols[i] = string.format('', math.ceil(weight) + 1) + end + end + widths[key] = "" .. table.concat(cols) .. "" + end + return widths +end + +-- Add the column widths, and let code break after underscores. +local function layout_tables(output) + local widths = column_widths(output) + return (output:gsub(".-
", function(tbl) + local key = header(tbl) + tbl = tbl:gsub("(.-)", function(code) + return "" .. code:gsub("_", "_") .. "" + end) + return "" .. widths[key] .. tbl:sub(#"
" + 1) + end)) +end + local buffer = "" local should_render = true local current_dir = "" -- Stores the directory prefix of the file being processed @@ -169,6 +258,7 @@ function filter_close() if output then if output:find("
", 1, true) then emit(table_style) + output = layout_tables(output) end emit(output) else -- cgit v1.3.1