diff --git a/logging.lua b/logging.lua index 16c2364..ee1636a 100644 --- a/logging.lua +++ b/logging.lua @@ -52,8 +52,27 @@ function Logger:setIgnoreGlobals(ignoreGlobals) self.ignoreGlobals = ignoreGlobals end +local LogPlain = {} +function LogPlain.of(value, deep) + local obj = { value, deep = deep } + setmetatable(obj, LogPlain) + return obj +end + +function LogPlain.is(value) + return type(value) == "table" and getmetatable(value) == LogPlain +end + +function LogPlain.isDeep(value) + return LogPlain.is(value) and value.deep +end + +function LogPlain.getValue(value) + return LogPlain.is(value) and value[1] or value +end + local RecursionSentinel = {} -function RecursionSentinel.make(table) +function RecursionSentinel.make(table, index) local obj = { table = table } setmetatable(obj, RecursionSentinel) return obj @@ -71,7 +90,8 @@ function RecursionSentinel.getSentinel(knownTables, value) local sentinel = knownTables[value] if sentinel == nil then sentinel = knownTables[value] - knownTables[value] = RecursionSentinel.make(value) + knownTables[#knownTables+1] = value + knownTables[value] = RecursionSentinel.make(value, #knownTables) end return sentinel end @@ -82,7 +102,9 @@ function RecursionSentinel.add(knownTables, value) return sentinel end -function RecursionSentinel.remove(knownTables, value) +function RecursionSentinel.pop(knownTables) + local value = knownTables[#knownTables] + knownTables[#knownTables] = nil knownTables[value] = nil end @@ -114,26 +136,40 @@ for k,v in pairs(_G) do G_[v] = k end -local function _simpleStringify(value, builder, ignoreGlobals, skipFunctions) +local function _simpleStringify(inValue, builder, ignoreGlobals, skipFunctions, plain) + local value = LogPlain.getValue(inValue) + local isPlain = plain or LogPlain.is(inValue) + local isDeep = plain or LogPlain.isDeep(inValue) if type(value) == "table" then - table.insert(builder, "<") + if not isPlain then + table.insert(builder, "<") + end if ignoreGlobals and G_[value] ~= nil then table.insert(builder, "_G.") table.insert(builder, G_[value]) elseif RecursionSentinel.isSentinel(value) then - table.insert(builder, "recurse ") - table.insert(builder, tostring(value.value)) + if isPlain then + table.insert(builder, "") + else + table.insert(builder, "recurse ") + table.insert(builder, tostring(value.value)) + end else - table.insert(builder, tostring(value)) - table.insert(builder, ">{") + if not isPlain then + table.insert(builder, tostring(value)) + table.insert(builder, ">") + end + table.insert(builder, "{") local first = true - for i,v in ipairs(value) do + for _,v in ipairs(value) do if not first then table.insert(builder, ",") else first = false end - _simpleStringify(v, builder, ignoreGlobals) + _simpleStringify(v, builder, ignoreGlobals, skipFunctions, isDeep) end first = #value == 0 for k,v in pairs(value) do @@ -142,32 +178,53 @@ local function _simpleStringify(value, builder, ignoreGlobals, skipFunctions) else first = false end - _simpleStringify(k, builder, ignoreGlobals) + -- String key values are always plain-printed + _simpleStringify(k, builder, ignoreGlobals, skipFunctions, isDeep or type(k) == "string") table.insert(builder, "=") - _simpleStringify(v, builder, ignoreGlobals) + _simpleStringify(v, builder, ignoreGlobals, skipFunctions, isDeep) end table.insert(builder, "}") end - table.insert(builder, ">") - elseif not skipFunctions or type(value) ~= "function" then - local isString = type(value) == "string" - if isString then + if not isPlain then + table.insert(builder, ">") + end + elseif type(value) == "string" then + if not isPlain then table.insert(builder, "\"") end table.insert(builder, tostring(value)) - if isString then + if not isPlain then table.insert(builder, "\"") end + elseif type(value) == "function" then + if not skipFunctions then + local info = debug.getinfo(value, "u") + if not isPlain then + table.insert(builder, tostring(value)) + end + table.insert(builder, "(") + table.insert(builder, tostring(info.nparams)) + if info.isvararg then + table.insert(builder, "*") + end + table.insert(builder, ")") + end + elseif not skipFunctions or type(value) ~= "function" then + table.insert(builder, tostring(value)) end end +local function deepStringify(value) + local collect = {} + _simpleStringify(cloneNonRecursive(value, {}), collect, false, false) + return table.concat(collect) +end + function Logger:_doPrint(level, message, ...) if LogLevel.isGreaterOrEqual(level, self.level) then - local result = { tostring(LogLevel[level]), message } + local result = { tostring(LogLevel[level]), deepStringify(message) } for _,v in ipairs({...}) do - local collect = {} - _simpleStringify(cloneNonRecursive(v, {}), collect) - table.insert(result, table.concat(collect)) + table.insert(result, deepStringify(v)) end self.output(table.concat(result, " ")) end @@ -207,6 +264,10 @@ function Logger:setLevel(level) end end +function Logger.plain(value, deep) + return LogPlain.of(value, deep) +end + Logging.Logger = Logger Logging.LogLevel = LogLevel