first tests with dictionary-type table are passing!

This commit is contained in:
Enrique García Cota 2011-04-23 23:29:52 +02:00
parent ecf208a938
commit 51153a31c6
2 changed files with 80 additions and 28 deletions

View File

@ -16,60 +16,108 @@ local function smartQuote(str)
return string.format("%q", str ) return string.format("%q", str )
end end
local unescapedChars = { local controlCharsTranslation = {
["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n",
["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v", ["\\"] = "\\\\" ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v", ["\\"] = "\\\\"
} }
local function unescapeChar(c) local function unescapeChar(c) return controlCharsTranslation[c] end
return unescapedChars[c]
end
local function unescape(str) local function unescape(str)
return string.gsub( str, "(%c)", unescapeChar ) return string.gsub( str, "(%c)", unescapeChar )
end end
local function isIdentifier(str)
return string.match( str, "^[_%a][_%a%d]*$" )
end
local Buffer = {} local function isArrayKey(k, length)
return type(k)=='number' and 1 <= k and k <= length
end
function Buffer:new() local function isDictionaryKey(k, length)
return setmetatable( { data = {} }, { return not isArrayKey(k, length)
__index = Buffer, end
__tostring = function(instance) return table.concat(instance.data) end
local function isDictionary(t)
local length = #t
for k,_ in pairs(t) do
if isDictionaryKey(k, length) then return true end
end
return false
end
local Inspector = {}
function Inspector:new()
return setmetatable( { buffer = {} }, {
__index = Inspector,
__tostring = function(instance) return table.concat(instance.buffer) end
} ) } )
end end
function Buffer:add(...) function Inspector:puts(...)
local args = {...} local args = {...}
for i=1, #args do for i=1, #args do
table.insert(self.data, tostring(args[i])) table.insert(self.buffer, tostring(args[i]))
end end
return self return self
end end
function Buffer:addValue(v) function Inspector:tabify(level)
local tv = type(v) self:puts("\n", string.rep(" ", level))
return self
if tv == 'string' then end
self:add(smartQuote(unescape(v)))
elseif tv == 'number' or tv == 'boolean' then function Inspector:addTable(t, level)
self:add(tostring(v)) self:puts('{')
elseif tv == 'table' then local length = #t
self:add('{') local needsComma = false
for i=1, #v do for i=1, length do
if i > 1 then self:add(', ') end if i > 1 then
self:addValue(v[i]) self:puts(', ')
needsComma = true
end end
self:add('}') self:addValue(t[i], level + 1)
else
self:add('<',tv,'>')
end end
for k,v in pairs(t) do
if isDictionaryKey(k, length) then
if needsComma then self:puts(',') end
needsComma = true
self:tabify(level+1):addKey(k):puts(' = '):addValue(v)
end
end
if isDictionary(t) then self:tabify(level) end
self:puts('}')
return self return self
end end
function Inspector:addValue(v, level)
local tv = type(v)
if tv == 'string' then
self:puts(smartQuote(unescape(v)))
elseif tv == 'number' or tv == 'boolean' then
self:puts(tostring(v))
elseif tv == 'table' then
self:addTable(v, level)
else
self:puts('<',tv,'>')
end
return self
end
function Inspector:addKey(k, level)
if type(k) == "string" and isIdentifier(k) then
return self:puts(k)
end
return self:puts( "[" ):addValue(k, level):puts("]")
end
local function inspect(t) local function inspect(t)
return tostring(Buffer:new():addValue(t)) return tostring(Inspector:new():addValue(t,0))
end end
return inspect return inspect

View File

@ -51,7 +51,11 @@ context( 'inspect', function()
end) end)
test('Should work with nested arrays', function() test('Should work with nested arrays', function()
assert_equal(inspect({1,2,3, {4,5}, 6}), "{1, 2, 3, {4, 5}, 6}" ) assert_equal(inspect({'a','b','c', {'d','e'}, 'f'}), '{"a", "b", "c", {"d", "e"}, "f"}' )
end)
test('Should work with simple hash-like tables', function()
assert_equal(inspect({a = 1, b = 2}), "{\n a = 1,\n b = 2\n}")
end) end)
end) end)