-- Add the module to the tree local mod = klhtm local me = {} mod.out = me --[[ Output.lua. These comments last updated R17.8. This module controls printing. For a normal print to the user that will always occur, call mod.out.print(). The second part of this module is trace printing. This is a printout that assists with debugging, which you might not want most users to see. The module provides methods to determine which debug prints should be sent to the user. Then to make a debug print, first call mod.out.checktrace(). If it returns non-nil, call mod.out.printtrace() with the actual message. Defaults are set by around line 27, overrides are set by calls around line 128. ]] --[[ -------------------------------------------------------------------------- Trace Printing for Debugging or Extra Information -------------------------------------------------------------------------- The idea of this section is to provide a detailed method to evaluate whether a specific trace message should be printed. We have a few data structures that are print options of the form "if the print is , do / dont print it". The more specific a print option is, the higher the priority it has. So the defaults, which just say "always print on " or "never print on " are the least specific and will be overridden by . For a release version, it is sufficient to set "error" = true, and the rest = "false", but for a debug version, you might only want to focus on specific sections of code for trace prints. ]] -- These are default printing options. For a release version, error only. For a debug version, maybe warnings too. me.default = { info = false, warning = false, error = true, } me.onload = function() -- optional debug specification --me.setprintstatus("boss", nil, "info", true) --me.setprintstatus("boss", "target", "info", false) end --[[ Suppose the following method calls were made: me.setprintstatus("boss", nil, "warning", true) me.setprintstatus("boss", "event", "info", true) Then me.override would look like me.override = { boss = { warning = true error = true sections = { event = { info = true warning = true error = true } } } } See for more information ]] me.override = { } --[[ me.setprintstatus(modulename, sectionname, messagetype, value) Overrides the default print option for a specific trace print. is a string, the source of the print, e.g. "out" for this module. is a string, a feature in the source module. e.g. "trace" for this section. is either "info" or "warning" or "error". is a boolean, true to enable the print, false to disable it. is an optional parameter. If it is nil, the override will apply to the whole module, but it is now less specific, so an individual section inside that module may be overriden again. will automatically cascade. "error" is assumed to be more important than "warning", which is more important than "info". So if you turn "warning" off, it will turn "info off as well"; if you turn "info" on, "warning" and "error" will be turned on too. ]] me.setprintstatus = function(modulename, sectionname, messagetype, value) -- check module exists if me.override[modulename] == nil then me.override[modulename] = { } end local printdata = me.override[modulename] -- is this for the whole module, or more specific? if sectionname then -- check whether any sections have been defined for this module if printdata.sections == nil then printdata.sections = { } end printdata = printdata.sections -- check whether this section has been defined in the sections list if printdata[sectionname] == nil then printdata[sectionname] = { } end printdata = printdata[sectionname] end -- set printdata[messagetype] = value -- cascade if value == true then if messagetype == "info" then printdata.warning = true messagetype = "warning" end if messagetype == "warning" then printdata.error = true end elseif value == false then if messagetype == "error" then printdata.warning = false messagetype = "warning" end if messagetype == "warning" then printdata.info = false end end end --[[ This is a reverse lookup of the top level of the list . has keys that are strings like "out", and values that are modules (lists), like . reverses this, giving us the name of a module from a reference to it. Calls to supply a module reference and we might like to name the module. However we wouldn't want to search for the module name every time that method is called, since we want it in particular to be fast. We don't fill me.modulelookup at runtime, but each time is called with a parameter that is not a key to , we will search to find that module. ]] me.modulelookup = { } --[[ me.getmodulename(module) Given a reference to a module (subtree of ), returns the name, which is the key in of the module. ]] me.getmodulename = function(module) -- have we already found this module before? local try = me.modulelookup[module] if try then return try end -- manual search local key, value for key, value in mod do if value == module then me.modulelookup[module] = key return key end end return "unknown" end --[[ mod.out.checktrace(messagetype, module, sectionname) Checks whether a debug print with the given properties should be printed. Return: non-nil iff the message should be printed. must be one of "error", "warning" or "info" should always be in the calling context is a description of the feature in that the message concerns. ]] me.checktrace = function(messagetype, module, sectionname) -- start with default print value local value = me.default[messagetype] me.printargs.overridelevel = "default" -- convert module reference to name local modulename = me.getmodulename(module) -- are there any overrides for that module? local printdata = me.override[modulename] if printdata then if printdata[messagetype] then value = printdata[messagetype] me.printargs.overridelevel = "module" end -- are there overrides for this section of the module? if printdata.sections and printdata.sections[sectionname] and (printdata.sections[sectionname][messagetype] ~= nil) then value = printdata.sections[sectionname][messagetype] me.printargs.overridelevel = "section" end end -- pre-return: load arguments for me.printtrace me.printargs.modulename = modulename me.printargs.sectionname = sectionname me.printargs.messagetype = messagetype -- return: nil or non-nil if value == true then return true end end -- This stores the options supplied to , which will slightly affect the printout. me.printargs = { messagetype = "", modulename = "", sectionname = "", overridelevel = "", } --[[ mod.out.printtrace(message) Prints a message that has been OK'd by . ]] me.printtrace = function(message) -- setup the colour. Error = red, warning = yellow, info = blue. Lightish colours. local header = "" if me.printargs.messagetype == "info" then header = "|cff8888ff" elseif me.printargs.messagetype == "warning" then header = "|cffffff44" elseif me.printargs.messagetype == "error" then header = "|cffff8888" end header = header .. "<" .. me.printargs.modulename .. "." .. me.printargs.sectionname .. "> " -- print! me.print(header .. message) end --[[ ---------------------------------------------------------------------- Normal Printing to the Console ---------------------------------------------------------------------- ]] --[[ mod.out.print(message, [chatframeindex, noheader]) Prints out to chat. To print to ChatFrame3, set to 3, etc. Adds a header "KTM: " to the message, unless is non-nil. ]] me.print = function(message, chatframeindex, noheader) -- Get a Frame to write to local chatframe if chatframeindex == nil then chatframe = DEFAULT_CHAT_FRAME else chatframe = getglobal("ChatFrame" .. chatframeindex) if chatframe == nil then chatframe = DEFAULT_CHAT_FRAME end end -- touch up message message = message or "" if noheader == nil then message = "KTM: " .. message end -- write chatframe:AddMessage(message) end --[[ mod.out.booltostring(boolean) Converts a Boolean value (true or false) to a string representation. true -> "true", false -> "false", nil -> "nil" ]] me.booltostring = function(boolean) if boolean == true then return "true" elseif boolean == false then return "false" else return "nil" end end --[[ mod.out.announce(message) Sends a chat message to Raid if possible, or Party if possible, or finally Say. ]] me.announce = function(message) local channel = "SAY" if GetNumRaidMembers() > 0 then channel = "RAID" elseif GetNumPartyMembers() > 0 then channel = "PARTY" end SendChatMessage(message, channel) end