Last active
August 22, 2024 16:25
-
-
Save pingbird/974e3fb00b9064371981 to your computer and use it in GitHub Desktop.
Fancy lua serialization
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
--[[ | |
Fancy lua serialization by PixelToast, public domain | |
serializes a value into a fancy and human readable format | |
example: | |
> cserialize({key="value",table={list={1,2,"three"},d="alphabetical order",c=1,b=2,a=3}}) | |
┌─────────────────────────────────────────┐ | |
│"key" = "value" │ | |
│ ┌─────────────────────────────┐│ | |
│ │"a" = 3 ││ | |
│ │"b" = 2 ││ | |
│ │"c" = 1 ││ | |
│ │"d" = "alphabetical order"││ | |
│"table" = │ ┌───────┐ ││ | |
│ │ │1 │ ││ | |
│ │"list" = │2 │ ││ | |
│ │ │"three"│ ││ | |
│ │ └───────┘ ││ | |
│ └─────────────────────────────┘│ | |
└─────────────────────────────────────────┘ | |
]] | |
local box={ | |
ud="│", | |
lr="─", | |
ur="└", | |
rd="┌", | |
ld="┐", | |
lu="┘", | |
e="[]" | |
} | |
--[[local box={ | |
ud="|", | |
lr="-", | |
ur="\\", | |
rd="/", | |
ld="\\", | |
lu="/", | |
e="[]" | |
}]] | |
local function utf8len(s) | |
local t=0 | |
for l1=1,#s do | |
local c=s:byte(l1) | |
if bit.band(c,0xC0)~=0x80 then | |
t=t+1 | |
end | |
end | |
return t | |
end | |
local function txtbl(s,mx) | |
local o={} | |
for c in s:gmatch("[^\r\n]+") do | |
table.insert(o,c) | |
end | |
mx=mx or 0 | |
for l1=1,#o do | |
mx=math.max(mx,utf8len(o[l1])) | |
end | |
for l1=1,#o do | |
o[l1]=o[l1]..(" "):rep(mx-utf8len(o[l1])) | |
end | |
return o,mx | |
end | |
local function consoleBox(s) | |
if s=="" then | |
s=" " | |
end | |
local t,l=txtbl(s) | |
for l1=1,#t do | |
t[l1]=box.ud..t[l1]..box.ud | |
end | |
table.insert(t,1,box.rd..(box.lr:rep(l))..box.ld) | |
table.insert(t,box.ur..(box.lr:rep(l))..box.lu) | |
return table.concat(t,"\n") | |
end | |
local function consoleCat(a,b,al,bl) | |
local at,al=txtbl(a,al) | |
local bt,bl=txtbl(b,bl) | |
if #at==#bt then | |
for l1=1,#bt do | |
bt[l1]=at[l1]..bt[l1] | |
end | |
return table.concat(bt,"\n") | |
end | |
if al==0 then | |
return table.concat(bt,"\n") | |
elseif bl==0 then | |
return table.concat(at,"\n") | |
end | |
local ml=math.max(#at,#bt) | |
for l1=1,math.floor((#bt-#at)/2) do | |
table.insert(at,1,(" "):rep(al)) | |
end | |
for l1=#at+1,ml do | |
table.insert(at,(" "):rep(al)) | |
end | |
for l1=1,math.floor((#at-#bt)/2) do | |
table.insert(bt,1,(" "):rep(bl)) | |
end | |
for l1=#bt+1,ml do | |
table.insert(bt,(" "):rep(bl)) | |
end | |
for l1=1,ml do | |
at[l1]=at[l1]..bt[l1] | |
end | |
return table.concat(at,"\n") | |
end | |
local function _cserialize(t,r) | |
r=r or {} | |
if r[t] then | |
return tostring(t) | |
end | |
local tpe=type(t) | |
if tpe=="table" then | |
local err,res=pcall(function() | |
local ok={} | |
local ov={} | |
local u={} | |
local n=1 | |
r[t]=true | |
while t[n]~=nil do | |
u[n]=true | |
table.insert(ok," ") | |
table.insert(ov,consoleCat(" ",_cserialize(t[n],r))) | |
n=n+1 | |
end | |
local oi={} | |
for k,v in pairs(t) do | |
if not u[k] then | |
table.insert(oi,{k,v}) | |
end | |
end | |
if #oi==0 then | |
for l1=1,#ov do | |
ov[l1]=ov[l1]:sub(4) | |
end | |
end | |
table.sort(oi,function(a,b) | |
return tostring(a[1])<tostring(b[1]) | |
end) | |
for k,v in ipairs(oi) do | |
table.insert(ok,_cserialize(v[1],r)) | |
table.insert(ov,consoleCat(" = ",_cserialize(v[2],r))) | |
end | |
if #ok==0 then | |
return box.e | |
end | |
local _ | |
local kl=0 | |
for k,v in pairs(ok) do | |
if v~=" " then | |
_,kl=txtbl(v,kl) | |
end | |
end | |
if kl==0 then | |
return consoleBox(table.concat(ov,"\n")) | |
end | |
local vl=0 | |
for k,v in pairs(ov) do | |
_,vl=txtbl(v,vl) | |
end | |
local o="" | |
for l1=1,#ok do | |
o=o..consoleCat(ok[l1],ov[l1],kl,vl).."\n" | |
end | |
r[t]=nil | |
return consoleBox(o) | |
end) | |
return err and res or tostring(t) | |
elseif tpe=="number" then | |
if t~=t then | |
return "nan" | |
elseif t==math.huge then | |
return "inf" | |
elseif t==-math.huge then | |
return "-inf" | |
end | |
return tostring(t) | |
elseif tpe=="string" then | |
local o=string.format("%q",t):gsub("\\\n","\\n"):gsub("%z","\\z") | |
return o | |
else | |
return tostring(t) | |
end | |
end | |
function cserialize(t) | |
return _cserialize(t) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment