--[[-- This module provides development-only asserts and other debug guards. Instead of a regular Lua @{assert}(), use @{dbg.dassert}() which can be toggled at runtime. dbg.dassert(important_variable ~= nil) For checking whether the input given to a function is sane, you can use @{dbg.guard}(). dbg:guard(NickelConf.frontLightLevel, "set", function(new_intensity) assert(type(new_intensity) == "number", "Wrong brightness value type (expected number)!") assert(new_intensity >= 0 and new_intensity <= 100, "Wrong brightness value given!") end) These functions don't do anything when debugging is turned off. --]]-- local logger = require("logger") local dump = require("dump") local isAndroid, android = pcall(require, "android") local Dbg = { -- set to nil so first debug:turnOff call won't be skipped is_on = nil, is_verbose = nil, } local Dbg_mt = {} local LvDEBUG if isAndroid then LvDEBUG = function(...) local line = {} for _, v in ipairs({...}) do if type(v) == "table" then table.insert(line, dump(v, math.huge)) else table.insert(line, tostring(v)) end end return android.LOGV(table.concat(line, " ")) end else LvDEBUG = function(...) local line = { os.date("%x-%X DEBUG"), } for _, v in ipairs({...}) do if type(v) == "table" then table.insert(line, dump(v, math.huge)) else table.insert(line, tostring(v)) end end table.insert(line, "\n") return io.write(table.concat(line, " ")) end end --- Helper function to help dealing with nils in Dbg:guard... local function pack_values(...) return select("#", ...), {...} end --- Turn on debug mode. -- This should only be used in tests and at the user's request. function Dbg:turnOn() if self.is_on == true then return end self.is_on = true logger:setLevel(logger.levels.dbg) Dbg_mt.__call = function(_, ...) return LvDEBUG(...) end --- Pass a guard function to detect bad input values. Dbg.guard = function(_, mod, method, pre_guard, post_guard) local old_method = mod[method] mod[method] = function(...) if pre_guard then pre_guard(...) end local n, values = pack_values(old_method(...)) if post_guard then post_guard(...) end return unpack(values, 1, n) end end --- Use this instead of a regular Lua @{assert}(). Dbg.dassert = function(check, msg) assert(check, msg) return check end end --- Turn off debug mode. -- This should only be used in tests and at the user's request. function Dbg:turnOff() if self.is_on == false then return end self.is_on = false logger:setLevel(logger.levels.info) Dbg_mt.__call = function() end -- NOTE: This doesn't actually disengage previously wrapped methods! Dbg.guard = function() end Dbg.dassert = function(check) return check end end --- Turn on verbose mode. -- This should only be used in tests and at the user's request. function Dbg:setVerbose(verbose) self.is_verbose = verbose end --- Simple table dump. function Dbg:v(...) if self.is_verbose then return LvDEBUG(...) end end --- Simple traceback. function Dbg:traceback() return LvDEBUG(debug.traceback()) end setmetatable(Dbg, Dbg_mt) Dbg:turnOff() return Dbg