70 lines
2.4 KiB
Lua
70 lines
2.4 KiB
Lua
local re = require 're'
|
|
local _quote_state = {}
|
|
local max = math.max
|
|
local _quote_patt = re.compile("(({'\n' / '\"' / \"'\" / '\\'}->mark_char) / (']' ({'='*}->mark_eq) (']' / !.)) / .)*",
|
|
{mark_char=function(q)
|
|
if q == "\n" or q == "\\" then
|
|
_quote_state["'"] = false
|
|
_quote_state['"'] = false
|
|
if _quote_state.min_eq == nil then
|
|
_quote_state.min_eq = 0
|
|
end
|
|
elseif q == "'" then
|
|
_quote_state["'"] = false
|
|
elseif q == '"' then
|
|
_quote_state['"'] = false
|
|
end
|
|
end,
|
|
mark_eq=function(eq)
|
|
_quote_state.min_eq = max(_quote_state.min_eq or 0, #eq+1)
|
|
end})
|
|
local function repr(x, depth)
|
|
-- Create a string representation of the object that is close to the lua code that will
|
|
-- reproduce the object (similar to Python's "repr" function)
|
|
depth = depth or 10
|
|
if depth == 0 then return "..." end
|
|
depth = depth - 1
|
|
local x_type = type(x)
|
|
if x_type == 'table' then
|
|
local ret = {}
|
|
local i = 1
|
|
for k, v in pairs(x) do
|
|
if k == i then
|
|
ret[#ret+1] = repr(x[i], depth)
|
|
i = i + 1
|
|
elseif type(k) == 'string' and k:match("[_a-zA-Z][_a-zA-Z0-9]*") then
|
|
ret[#ret+1] = k.."= "..repr(v,depth)
|
|
else
|
|
ret[#ret+1] = "["..repr(k,depth).."]= "..repr(v,depth)
|
|
end
|
|
end
|
|
return "{"..table.concat(ret, ", ").."}"
|
|
elseif x_type == 'string' then
|
|
if x == "\n" then
|
|
return "'\\n'"
|
|
end
|
|
_quote_state = {}
|
|
_quote_patt:match(x)
|
|
if _quote_state["'"] ~= false then
|
|
return "\'" .. x .. "\'"
|
|
elseif _quote_state['"'] ~= false then
|
|
return "\"" .. x .. "\""
|
|
else
|
|
local eq = ("="):rep(_quote_state.min_eq or 0)
|
|
-- BEWARE!!!
|
|
-- Lua's parser and syntax are dumb, so Lua interprets x[[=[asdf]=]] as
|
|
-- a function call to x (i.e. x("=[asdf]=")), instead of indexing x
|
|
-- (i.e. x["asdf"]), which it obviously should be. This can be fixed by
|
|
-- slapping spaces or parens around the [=[asdf]=].
|
|
if x:sub(1, 1) == "\n" then
|
|
return "["..eq.."[\n"..x.."]"..eq.."]"
|
|
else
|
|
return "["..eq.."["..x.."]"..eq.."]"
|
|
end
|
|
end
|
|
else
|
|
return tostring(x)
|
|
end
|
|
end
|
|
return repr
|