This commit is contained in:
Connor Olding 2016-12-11 04:56:57 -08:00
parent c76f172975
commit af75dcc7c5
3 changed files with 74 additions and 26 deletions

View file

@ -1,3 +1,10 @@
local insert = table.insert
local pairs = pairs
local rawget = rawget
local sort = table.sort
local tostring = tostring
local type = type
local function strpad(num, count, pad) local function strpad(num, count, pad)
num = tostring(num) num = tostring(num)
return (pad:rep(count)..num):sub(#num) return (pad:rep(count)..num):sub(#num)
@ -18,9 +25,9 @@ end
local function order_keys(t) local function order_keys(t)
local oi = {} local oi = {}
for key in pairs(t) do for key in pairs(t) do
table.insert(oi, key) insert(oi, key)
end end
table.sort(oi, mixed_sorter) sort(oi, mixed_sorter)
return oi return oi
end end
@ -33,7 +40,7 @@ local function opairs(t, cache)
return function() return function()
i = i + 1 i = i + 1
local key = oi[i] local key = oi[i]
if key then return key, t[key] end if key ~= nil then return key, t[key] end
end end
end end

74
pt.lua
View file

@ -25,8 +25,8 @@ local function copy(t)
-- shallow copy -- shallow copy
if type(t) ~= 'table' then return end if type(t) ~= 'table' then return end
local new = {} local new = {}
for key, value in pairs(t) do for k,v in pairs(t) do
new[key] = value new[k] = v
end end
return new return new
end end
@ -43,7 +43,10 @@ function pt.__call(pt, args)
self.depth = args.depth or 16 self.depth = args.depth or 16
self.writer = args.writer or io.write self.writer = args.writer or io.write
self.skeleton = args.skeleton or false self.skeleton = args.skeleton or false
self.outer = args.alt_order and self.outer_old or self.outer
self.indent = args.indent or ' '
self.queued = {} self.queued = {}
self.cache = {}
self:inner('__root__', t, '') self:inner('__root__', t, '')
return self.seen return self.seen
end end
@ -61,7 +64,7 @@ function pt.safekey(k)
return s:find('[^%w_]') and ('%q'):format(s) or s return s:find('[^%w_]') and ('%q'):format(s) or s
end end
function pt.safeval(v, indent) function pt.safeval(v, indentation, indent)
if type(v) == 'function' then if type(v) == 'function' then
return 'f'..getaddr(v) return 'f'..getaddr(v)
end end
@ -69,25 +72,28 @@ function pt.safeval(v, indent)
if type(v) == 'number' then if type(v) == 'number' then
return s return s
end end
s = s:find('[\r\n]') and ('\n'..s):gsub('[\r\n]', '\n'..indent..' ') or s -- TODO: move newline/indentation handling to another function?
if s:find('[\r\n]') then
s = ('\n'..s):gsub('[\r\n]', '\n'..indentation..indent)
end
--local safe = ('%q'):format(s) --local safe = ('%q'):format(s)
--return s == safe:sub(2, -2) and s or safe --return s == safe:sub(2, -2) and s or safe
-- TODO: finish matching valid characters -- TODO: finish matching valid characters
return s:find('[^%w_()[]{}.]') and ('%q'):format(s) or s return s:find('[^%w_()[]{}.]') and ('%q'):format(s) or s
end end
function pt:inner(k, v, indent) function pt:inner(k, v, indentation)
if type(v) ~= 'table' then if type(v) ~= 'table' then
if self.skeleton then return end if self.skeleton then return end
self:write(indent, pt.safekey(k), ': ') self:write(indentation, pt.safekey(k), ': ')
self:write(pt.safeval(v, indent), '\n') self:write(pt.safeval(v, indentation, self.indent), '\n')
return return
end end
local addr = getaddr(v) local addr = getaddr(v)
self:write(indent, pt.safekey(k)) self:write(indentation, pt.safekey(k))
if #indent > self.depth or self.skipped[addr] then if #indentation > self.depth or self.skipped[addr] then
--self.skipped[addr] = true -- TODO: extra logics --self.skipped[addr] = true -- TODO: extra logics
self:write(': #t', addr, '\n') self:write(': #t', addr, '\n')
return return
@ -101,12 +107,13 @@ function pt:inner(k, v, indent)
self.seen[addr] = true self.seen[addr] = true
self:write(': &t', addr, '\n') self:write(': &t', addr, '\n')
self:outer(v, indent..' ') self:outer(v, indentation..self.indent)
end end
function pt:outer(t, indent) function pt:outer_old(t, indentation)
if type(t) ~= "table" then if type(t) ~= "table" then
self:write(indent, pt.safeval(t, indent), '\n') local s = pt.safeval(t, indentation, self.indent)
self:write(indentation, s, '\n')
return return
end end
@ -116,29 +123,62 @@ function pt:outer(t, indent)
for k,v in opairs(t) do for k,v in opairs(t) do
if type(v) == 'table' then if type(v) == 'table' then
local addr = getaddr(v) local addr = getaddr(v)
if not self.queued[addr] and not self.seen[addr] and not self.skipped[addr] then if not (self.queued[addr] or self.seen[addr] or self.skipped[addr]) then
self.queued[addr] = true self.queued[addr] = true
ours[k] = v ours[k] = v
else else
not_ours[k] = v not_ours[k] = v
end end
else else
self:inner(k, v, indent) self:inner(k, v, indentation)
end end
end end
for k,v in opairs(not_ours) do for k,v in opairs(not_ours) do
self:inner(k, v, indent) self:inner(k, v, indentation)
end end
for k,v in opairs(ours) do for k,v in opairs(ours) do
self.queued[getaddr(v)] = nil self.queued[getaddr(v)] = nil
self:inner(k, v, indent) self:inner(k, v, indentation)
end end
local mt = getmetatable(t) local mt = getmetatable(t)
if mt ~= nil then if mt ~= nil then
self:inner('__metatable', mt, indent) self:inner('__metatable', mt, indentation)
end
end
function pt:outer(t, indentation)
if type(t) ~= "table" then
local s = pt.safeval(t, indentation, self.indent)
self:write(indentation, s, '\n')
return
end
local ours = {}
for k,v in opairs(t, self.cache) do
if type(v) == 'table' then
local addr = getaddr(v)
if not (self.queued[addr] or self.seen[addr] or self.skipped[addr]) then
self.queued[addr] = true
ours[k] = addr
end
end
end
local mt = getmetatable(t)
if mt ~= nil then
self:inner('__metatable', mt, indentation)
end
for k,v in opairs(t, self.cache) do
local addr = ours[k]
if addr then
self.queued[addr] = nil
end
self:inner(k, v, indentation)
end end
end end

13
run.lua
View file

@ -2,21 +2,22 @@
local pt = require('pt') local pt = require('pt')
t = { t = {
A = { A = 'hello',
B = {
a = 'beep', a = 'beep',
b = 'boop', b = 'boop',
c = 'burp', c = 'burp',
}, },
B = { C = {
a = 'nude', a = 'nude',
b = 'dude', b = 'dude',
c = 'lewd', c = 'lewd',
}, },
C = 'hello', D = 'goodbye',
} }
t.A.d = t.B t.B.d = t.C
t.B.d = t.A t.C.d = t.B
t.D = t t.E = t
function dump(t, fn, seen) function dump(t, fn, seen)
if t == nil then return end if t == nil then return end