mirror of
https://github.com/kikito/inspect.lua.git
synced 2024-12-15 14:34:21 +00:00
made inspect.lua not object-oriented
This commit is contained in:
parent
7a0dae850d
commit
0de3c69e5d
221
inspect.lua
221
inspect.lua
@ -45,7 +45,7 @@ local controlCharsTranslation = {
|
|||||||
local function unescapeChar(c) return controlCharsTranslation[c] end
|
local function unescapeChar(c) return controlCharsTranslation[c] end
|
||||||
|
|
||||||
local function unescape(str)
|
local function unescape(str)
|
||||||
local result, _ = string.gsub( str, "(%c)", unescapeChar )
|
local result, _ = string.gsub(str, "(%c)", unescapeChar)
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -84,8 +84,7 @@ local function sortKeys(a, b)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function getDictionaryKeys(t)
|
local function getDictionaryKeys(t)
|
||||||
local length = #t
|
local keys, length = {}, #t
|
||||||
local keys = {}
|
|
||||||
for k,_ in pairs(t) do
|
for k,_ in pairs(t) do
|
||||||
if isDictionaryKey(k, length) then table.insert(keys, k) end
|
if isDictionaryKey(k, length) then table.insert(keys, k) end
|
||||||
end
|
end
|
||||||
@ -95,12 +94,12 @@ end
|
|||||||
|
|
||||||
local function getToStringResultSafely(t, mt)
|
local function getToStringResultSafely(t, mt)
|
||||||
local __tostring = type(mt) == 'table' and rawget(mt, '__tostring')
|
local __tostring = type(mt) == 'table' and rawget(mt, '__tostring')
|
||||||
local string, status
|
local str, ok
|
||||||
if type(__tostring) == 'function' then
|
if type(__tostring) == 'function' then
|
||||||
status, string = pcall(__tostring, t)
|
ok, str = pcall(__tostring, t)
|
||||||
string = status and string or 'error: ' .. tostring(string)
|
str = ok and str or 'error: ' .. tostring(str)
|
||||||
end
|
end
|
||||||
return string
|
if type(str) == 'string' and #str > 0 then return str end
|
||||||
end
|
end
|
||||||
|
|
||||||
local maxIdsMetaTable = {
|
local maxIdsMetaTable = {
|
||||||
@ -118,161 +117,159 @@ local idsMetaTable = {
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
local Inspector = {}
|
local function countTableAppearances(t, tableAppearances)
|
||||||
|
tableAppearances = tableAppearances or setmetatable({}, {__mode = "k"})
|
||||||
|
|
||||||
function Inspector:new(t, depth)
|
|
||||||
local inspector = {
|
|
||||||
buffer = {},
|
|
||||||
depth = depth,
|
|
||||||
level = 0,
|
|
||||||
tableAppearances = setmetatable({}, {__mode = "k"}),
|
|
||||||
maxIds = setmetatable({}, maxIdsMetaTable),
|
|
||||||
ids = setmetatable({}, idsMetaTable),
|
|
||||||
}
|
|
||||||
|
|
||||||
setmetatable(inspector, {__index = Inspector})
|
|
||||||
|
|
||||||
inspector:countTableAppearances(t)
|
|
||||||
|
|
||||||
return inspector:putValue(t)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:countTableAppearances(t)
|
|
||||||
if type(t) == 'table' then
|
if type(t) == 'table' then
|
||||||
if not self.tableAppearances[t] then
|
if not tableAppearances[t] then
|
||||||
self.tableAppearances[t] = 1
|
tableAppearances[t] = 1
|
||||||
for k,v in pairs(t) do
|
for k,v in pairs(t) do
|
||||||
self:countTableAppearances(k)
|
countTableAppearances(k, tableAppearances)
|
||||||
self:countTableAppearances(v)
|
countTableAppearances(v, tableAppearances)
|
||||||
end
|
end
|
||||||
self:countTableAppearances(getmetatable(t))
|
countTableAppearances(getmetatable(t), tableAppearances)
|
||||||
else
|
else
|
||||||
self.tableAppearances[t] = self.tableAppearances[t] + 1
|
tableAppearances[t] = tableAppearances[t] + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return tableAppearances
|
||||||
end
|
end
|
||||||
|
|
||||||
function Inspector:tabify()
|
-------------------------------------------------------------------
|
||||||
self:puts("\n", string.rep(" ", self.level))
|
function inspect.dump(rootObject, depth)
|
||||||
return self
|
depth = depth or math.huge
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:up()
|
local buffer = {}
|
||||||
self.level = self.level - 1
|
local blen = 0 -- buffer length
|
||||||
end
|
local level = 0
|
||||||
|
local maxIds = setmetatable({}, maxIdsMetaTable)
|
||||||
|
local ids = setmetatable({}, idsMetaTable)
|
||||||
|
|
||||||
function Inspector:down()
|
local tableAppearances = countTableAppearances(rootObject)
|
||||||
self.level = self.level + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:puts(...)
|
local function down(f)
|
||||||
|
level = level + 1
|
||||||
|
f()
|
||||||
|
level = level - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local function puts(...)
|
||||||
local args = {...}
|
local args = {...}
|
||||||
local len = #self.buffer
|
|
||||||
for i=1, #args do
|
for i=1, #args do
|
||||||
len = len + 1
|
blen = blen + 1
|
||||||
self.buffer[len] = tostring(args[i])
|
buffer[blen] = tostring(args[i])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:commaControl(needsComma)
|
local function tabify()
|
||||||
if needsComma then self:puts(',') end
|
puts("\n", string.rep(" ", level))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function commaControl(needsComma)
|
||||||
|
if needsComma then puts(',') end
|
||||||
return true
|
return true
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:putTable(t)
|
|
||||||
if self:alreadyVisited(t) then
|
|
||||||
self:puts('<table ', self:getId(t), '>')
|
|
||||||
elseif self.depth and self.level >= self.depth then
|
|
||||||
self:puts('{...}')
|
|
||||||
else
|
|
||||||
if self.tableAppearances[t] > 1 then
|
|
||||||
self:puts('<',self:getId(t),'>')
|
|
||||||
end
|
end
|
||||||
self:puts('{')
|
|
||||||
self:down()
|
|
||||||
|
|
||||||
|
local function alreadyVisited(v)
|
||||||
|
return ids[type(v)][v] ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getId(v)
|
||||||
|
local tv = type(v)
|
||||||
|
local id = ids[tv][v]
|
||||||
|
if not id then
|
||||||
|
id = maxIds[tv] + 1
|
||||||
|
maxIds[tv] = id
|
||||||
|
ids[tv][v] = id
|
||||||
|
end
|
||||||
|
return id
|
||||||
|
end
|
||||||
|
|
||||||
|
local putValue -- forward declaration that needs to go before putTable & putKey
|
||||||
|
|
||||||
|
local function putKey(k)
|
||||||
|
if isIdentifier(k) then return puts(k) end
|
||||||
|
puts( "[" )
|
||||||
|
putValue(k)
|
||||||
|
puts("]")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function putTable(t)
|
||||||
|
if alreadyVisited(t) then
|
||||||
|
puts('<table ', getId(t), '>')
|
||||||
|
elseif level >= depth then
|
||||||
|
puts('{...}')
|
||||||
|
else
|
||||||
|
if tableAppearances[t] > 1 then puts('<', getId(t), '>') end
|
||||||
|
|
||||||
|
local dictKeys = getDictionaryKeys(t)
|
||||||
local length = #t
|
local length = #t
|
||||||
local mt = getmetatable(t)
|
local mt = getmetatable(t)
|
||||||
|
local to_string_result = getToStringResultSafely(t, mt)
|
||||||
|
|
||||||
local string = getToStringResultSafely(t, mt)
|
puts('{')
|
||||||
if type(string) == 'string' and #string > 0 then
|
down(function()
|
||||||
self:puts(' -- ', unescape(string))
|
if to_string_result then
|
||||||
if length >= 1 then self:tabify() end -- tabify the array values
|
puts(' -- ', unescape(to_string_result))
|
||||||
|
if length >= 1 then tabify() end -- tabify the array values
|
||||||
end
|
end
|
||||||
|
|
||||||
local needsComma = false
|
local needsComma = false
|
||||||
for i=1, length do
|
for i=1, length do
|
||||||
needsComma = self:commaControl(needsComma)
|
needsComma = commaControl(needsComma)
|
||||||
self:puts(' '):putValue(t[i])
|
puts(' ')
|
||||||
|
putValue(t[i])
|
||||||
end
|
end
|
||||||
|
|
||||||
local dictKeys = getDictionaryKeys(t)
|
|
||||||
|
|
||||||
for _,k in ipairs(dictKeys) do
|
for _,k in ipairs(dictKeys) do
|
||||||
needsComma = self:commaControl(needsComma)
|
needsComma = commaControl(needsComma)
|
||||||
self:tabify():putKey(k):puts(' = '):putValue(t[k])
|
tabify()
|
||||||
|
putKey(k)
|
||||||
|
puts(' = ')
|
||||||
|
putValue(t[k])
|
||||||
end
|
end
|
||||||
|
|
||||||
if mt then
|
if mt then
|
||||||
needsComma = self:commaControl(needsComma)
|
needsComma = commaControl(needsComma)
|
||||||
self:tabify():puts('<metatable> = '):putValue(mt)
|
tabify()
|
||||||
|
puts('<metatable> = ')
|
||||||
|
putValue(mt)
|
||||||
end
|
end
|
||||||
|
end)
|
||||||
self:up()
|
|
||||||
|
|
||||||
if #dictKeys > 0 or mt then -- dictionary table. Justify closing }
|
if #dictKeys > 0 or mt then -- dictionary table. Justify closing }
|
||||||
self:tabify()
|
tabify()
|
||||||
elseif length > 0 then -- array tables have one extra space before closing }
|
elseif length > 0 then -- array tables have one extra space before closing }
|
||||||
self:puts(' ')
|
puts(' ')
|
||||||
end
|
end
|
||||||
self:puts('}')
|
|
||||||
|
puts('}')
|
||||||
end
|
end
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:alreadyVisited(v)
|
|
||||||
return self.ids[type(v)][v] ~= nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:getId(v)
|
|
||||||
local tv = type(v)
|
|
||||||
local id = self.ids[tv][v]
|
|
||||||
if not id then
|
|
||||||
id = self.maxIds[tv] + 1
|
|
||||||
self.maxIds[tv] = id
|
|
||||||
self.ids[tv][v] = id
|
|
||||||
end
|
end
|
||||||
return id
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:putValue(v)
|
-- putvalue is forward-declared before putTable & putKey
|
||||||
|
putValue = function(v)
|
||||||
local tv = type(v)
|
local tv = type(v)
|
||||||
|
|
||||||
if tv == 'string' then
|
if tv == 'string' then
|
||||||
self:puts(smartQuote(unescape(v)))
|
puts(smartQuote(unescape(v)))
|
||||||
elseif tv == 'number' or tv == 'boolean' or tv == 'nil' then
|
elseif tv == 'number' or tv == 'boolean' or tv == 'nil' then
|
||||||
self:puts(tostring(v))
|
puts(tostring(v))
|
||||||
elseif tv == 'table' then
|
elseif tv == 'table' then
|
||||||
self:putTable(v)
|
putTable(v)
|
||||||
else
|
else
|
||||||
self:puts('<',tv,' ',self:getId(v),'>')
|
puts('<',tv,' ',getId(v),'>')
|
||||||
end
|
end
|
||||||
return self
|
end
|
||||||
|
|
||||||
|
putValue(rootObject)
|
||||||
|
|
||||||
|
return table.concat(buffer)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Inspector:putKey(k)
|
setmetatable(inspect, { __call = function(_, ...) return inspect.dump(...) end })
|
||||||
if isIdentifier(k) then return self:puts(k) end
|
|
||||||
return self:puts( "[" ):putValue(k):puts("]")
|
|
||||||
end
|
|
||||||
|
|
||||||
function Inspector:tostring()
|
|
||||||
return table.concat(self.buffer)
|
|
||||||
end
|
|
||||||
|
|
||||||
setmetatable(inspect, { __call = function(_,t,depth)
|
|
||||||
return Inspector:new(t, depth):tostring()
|
|
||||||
end })
|
|
||||||
|
|
||||||
return inspect
|
return inspect
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user