Add more flexibility in how whitespace is specified.
[gazelle.git] / sketches / pp.lua
blob889f821e21cb97e0ba10d9aa061b051f56c4b210
2 require "data_structures"
4 function serialize(o, maxdepth, indent, s)
5 local seen = s or Stack:new()
6 local t = type(o)
7 local new_max_depth
8 if maxdepth then new_max_depth = maxdepth-1 end
9 if new_max_depth == 0 then return "<too deep>" end
11 if t == "table" and seen:contains(o) then
12 return "..."
13 else
14 seen:push(o)
15 end
17 if indent and type(indent) ~= "string" then
18 indent = ""
19 end
21 local result
22 local nestedIndent
23 if indent then
24 nestedIndent = indent .. " "
25 end
27 if t == "string" then
28 result = string.format("%q", o)
29 elseif t == "boolean" or t == "number" then
30 result = tostring(t)
31 elseif t == "table" and o.__index == o and o.name then
32 result = string.format("Class: %q", o.name)
33 elseif t == "table" and not (o.class and o.class.tostring) then
34 result = "{"
35 if nestedIndent then result = result .. "\n" .. nestedIndent end
36 local nextIndex = 1
37 local first = true
38 for k, v in pairs(o) do
39 if first then
40 first = false
41 else
42 result = result .. ", "
43 if nestedIndent then result = result .. "\n" .. nestedIndent end
44 end
45 if type(k) == "number" and k == nextIndex then
46 nextIndex = nextIndex + 1
47 else
48 if type(k) == "string" and string.find(k, "^[_%a][_%w]*$") then
49 result = result .. k
50 else
51 result = result .. "[" .. serialize(k, new_max_depth, nil, seen) .. "]"
52 end
53 result = result .. " = "
54 end
55 result = result .. serialize(v, new_max_depth, nestedIndent, seen)
56 end
57 if indent then
58 result = result .. "\n" .. indent
59 end
60 result = result .. "}"
61 else
62 result = o:tostring(nestedIndent)
63 end
65 seen:pop()
66 return result
67 end