Created
April 11, 2024 05:15
-
-
Save max1220/320829badfb885562c3f5bae4efbc898 to your computer and use it in GitHub Desktop.
Configurable Lua table ANSI pretty printer/serializer. Public domain.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local function pretty_print_table(tbl, file, indent, num_fmt, no_ansi, style, seen) | |
-- default parameters | |
file = file or io.stdout | |
indent = indent or 0 | |
num_fmt = tbl.__print_table_number_format or num_fmt or "%.2f" | |
style = tbl.__print_table_colors or style or {} | |
seen = seen or {} | |
-- calculate ANSI color codes | |
local key_code = no_ansi and "" or style.key or "\027[1;36m" | |
local tbl_code = no_ansi and "" or style.tbl or "\027[35m" | |
local comt_code = no_ansi and "" or style.comt or "\027[33m" | |
local str_code = no_ansi and "" or style.str or "\027[32m" | |
local num_code = no_ansi and "" or style.num or "\027[34m" | |
local func_code = no_ansi and "" or style.func or "\027[91m" | |
local bool_on_code = no_ansi and "" or style.bool_on or "\027[92m" | |
local bool_off_code = no_ansi and "" or style.bool_off or "\027[91m" | |
local reset_code = no_ansi and "" or style.reset or "\027[0m" | |
-- from key-value hash format to list of {k,v} tuples | |
local itbl = {} | |
for k, v in pairs(tbl) do | |
table.insert(itbl, { k, v }) | |
end | |
-- sort list of tuples by keys | |
table.sort(itbl, function(a,b) | |
if type(a[1]) == "number" and type(b[1]) == "number" then | |
return a[1] < b[1] | |
else | |
return tostring(a[1]) < tostring(b[1]) | |
end | |
end) | |
-- iterate over tuples, print recursively using ANSI escape sequences for colors | |
local id = (style.indent_chars or "\t"):rep(indent) | |
for i,t in ipairs(itbl) do | |
local k,v = unpack(t) | |
local ls = (i==#itbl) and "" or "," | |
local ke = tostring(k) .. " = " | |
if type(k) == "string" and (("%q"):format(k) ~= "\""..k.."\"") then | |
ke = ("[%q] = "):format(k):gsub("\\\n", "\\n") | |
elseif (type(k)=="number") and (k==i) then | |
ke = "" | |
elseif type(k)=="number" then | |
ke = "[" .. num_code .. k .. reset_code .. key_code .. "] = " | |
end | |
file:write(id .. key_code .. ke .. reset_code) | |
if type(v) == "table" then | |
if seen[v] then | |
file:write(tbl_code .. "{}" .. ls .. comt_code .. " -- repeat: <" .. tostring(v) .. ">" ..reset_code .. "\n") | |
else | |
seen[v] = true | |
file:write(tbl_code .. "{ " .. comt_code .. "-- <" .. tostring(v) .. ">" .. reset_code .. "\n") | |
print_table(v, file, indent+1, num_fmt, no_ansi, style, seen) | |
file:write(id .. tbl_code .. "}" .. reset_code .. ls .. "\n") | |
end | |
elseif type(v) == "string" then | |
file:write(str_code .. ("%q"):format(v):gsub("\\\n", "\\n") .. reset_code .. ls .. "\n") | |
elseif type(v) == "function" then | |
file:write(func_code .. "nil" .. ls .. " -- <" .. tostring(v) .. ">" .. reset_code .. "\n") | |
elseif type(v) == "number" then | |
file:write(num_code .. num_fmt:format(v) .. reset_code .. ls .. "\n") | |
elseif type(v) == "boolean" then | |
file:write((v and (bool_on_code .. "true") or (bool_off_code .. "false")) .. reset_code .. ls .. "\n") | |
else | |
file:write(tostring(v) .. ls .. "\n") | |
end | |
end | |
end | |
local t = {"foo", "bar"} | |
local test = { | |
"First", | |
"Second", | |
"Third", | |
44,55,66, | |
[222] = "is 222", | |
[999] = "Almost 1000", | |
["Hello\nWorld!"] = "Foo Bar!", | |
[false] = true, | |
print = print, | |
hex = { | |
__print_table_number_format = "0x%.1x", | |
[0]=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | |
}, | |
colors = { | |
__print_table_colors = { str = "\027[91m" }, | |
red_str = "This string is red!" | |
}, | |
t_copy_a = t, | |
t_copy_b = t, | |
} | |
print_table(test) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment