local outputEnabled = true
local collectors = {}
local onceUsedLocations = {}
local function indent(source, indentLevel)
local indentString = ("\t"):rep(indentLevel)
return indentString .. source:gsub("\n", "\n" .. indentString)
end
local function indentLines(lines, indentLevel)
local outputBuffer = {}
for _, line in ipairs(lines) do
table.insert(outputBuffer, indent(line, indentLevel))
end
return table.concat(outputBuffer, "\n")
end
local logInfoMetatable = {}
function logInfoMetatable:__tostring()
local outputBuffer = { "LogInfo {" }
local errorCount = #self.errors
local warningCount = #self.warnings
local infosCount = #self.infos
if errorCount + warningCount + infosCount == 0 then
table.insert(outputBuffer, "\t(no messages)")
end
if errorCount > 0 then
table.insert(outputBuffer, ("\tErrors (%d) {"):format(errorCount))
table.insert(outputBuffer, indentLines(self.errors, 2))
table.insert(outputBuffer, "\t}")
end
if warningCount > 0 then
table.insert(outputBuffer, ("\tWarnings (%d) {"):format(warningCount))
table.insert(outputBuffer, indentLines(self.warnings, 2))
table.insert(outputBuffer, "\t}")
end
if infosCount > 0 then
table.insert(outputBuffer, ("\tInfos (%d) {"):format(infosCount))
table.insert(outputBuffer, indentLines(self.infos, 2))
table.insert(outputBuffer, "\t}")
end
table.insert(outputBuffer, "}")
return table.concat(outputBuffer, "\n")
end
local function createLogInfo()
local logInfo = {
errors = {},
warnings = {},
infos = {},
}
setmetatable(logInfo, logInfoMetatable)
return logInfo
end
local Logging = {}
function Logging.capture(callback)
local collector = createLogInfo()
local wasOutputEnabled = outputEnabled
outputEnabled = false
collectors[collector] = true
local success, result = pcall(callback)
collectors[collector] = nil
outputEnabled = wasOutputEnabled
assert(success, result)
return collector
end
function Logging.warn(messageTemplate, ...)
local message = messageTemplate:format(...)
for collector in pairs(collectors) do
table.insert(collector.warnings, message)
end
local trace = debug.traceback("", 2):sub(2)
local fullMessage = ("%s\n%s"):format(message, indent(trace, 1))
if outputEnabled then
warn(fullMessage)
end
end
function Logging.warnOnce(messageTemplate, ...)
local trace = debug.traceback()
if onceUsedLocations[trace] then
return
end
onceUsedLocations[trace] = true
Logging.warn(messageTemplate, ...)
end
return Logging