Something went wrong. Try again.
A collection of my addons for World of Warcraft
Something went wrong. Try again.
4.0 kB · 141 lines
Lua
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142local addon_name = ...
local MAX_DUMPS = 20local MAX_DEPTH = 24
local function print_msg(msg) print("|cff6fa8dcdev_dump:|r " .. msg)end
--- Converts a value into something SavedVariables can store.------ SavedVariables only persist strings, numbers, booleans, and tables of--- those, so anything else is replaced with a descriptive placeholder string.local function sanitize(value, depth, seen) local value_type = type(value)
if value_type == "string" or value_type == "number" or value_type == "boolean" or value_type == "nil" then return value end
if value_type ~= "table" then return "<" .. value_type .. ">" end
-- Widgets (frames, textures, and so on) are tables backed by userdata. Dumping -- them recursively would pull in half the UI, so summarize them instead. if type(value.GetObjectType) == "function" and type(rawget(value, 0)) == "userdata" then local ok, object_type = pcall(value.GetObjectType, value) local ok_name, name = pcall(value.GetName, value) return string.format( "<%s %s>", ok and object_type or "widget", (ok_name and name) or "anonymous" ) end
if seen[value] then return "<cycle>" end
if depth >= MAX_DEPTH then return "<max depth>" end
seen[value] = true
local result = {} for key, inner in pairs(value) do local key_type = type(key) if key_type ~= "string" and key_type ~= "number" and key_type ~= "boolean" then key = "<" .. key_type .. " key> " .. tostring(key) end result[key] = sanitize(inner, depth + 1, seen) end
seen[value] = nil
return resultend
local function pack(...) return { n = select("#", ...), ... }end
local function dump(expr) local entry = { expr = expr, time = date("%Y-%m-%d %H:%M:%S"), build = { GetBuildInfo() }, }
local chunk, compile_error = loadstring("return " .. expr, "=devdump") if not chunk then -- Not an expression, so try it as a statement instead (e.g. `x = 1`). chunk, compile_error = loadstring(expr, "=devdump") end
if not chunk then entry.error = compile_error else local results = pack(pcall(chunk)) if results[1] then entry.results = {} entry.result_count = results.n - 1 for i = 2, results.n do entry.results[i - 1] = sanitize(results[i], 0, {}) end else entry.error = results[2] end end
local dumps = dev_dump_db.dumps table.insert(dumps, entry) while #dumps > MAX_DUMPS do table.remove(dumps, 1) end
if entry.error then print_msg("|cffff6b5eerror:|r " .. tostring(entry.error)) else print_msg(string.format( "saved %d value(s) as dump #%d. /reload to write it to disk.", entry.result_count, #dumps )) endend
local frame = CreateFrame("Frame")frame:RegisterEvent("ADDON_LOADED")frame:SetScript("OnEvent", function(self, event, loaded_addon) if loaded_addon ~= addon_name then return end
dev_dump_db = dev_dump_db or {} dev_dump_db.dumps = dev_dump_db.dumps or {} self:UnregisterEvent("ADDON_LOADED")end)
SLASH_DEV_DUMP1 = "/devdump"SlashCmdList.DEV_DUMP = function(msg) msg = strtrim(msg or "")
if msg == "" then print_msg("usage: /devdump <lua expression> | /devdump list | /devdump clear") elseif msg == "clear" then wipe(dev_dump_db.dumps) print_msg("cleared all dumps.") elseif msg == "list" then if #dev_dump_db.dumps == 0 then print_msg("no dumps saved.") end for i, entry in ipairs(dev_dump_db.dumps) do print_msg(string.format("#%d [%s] %s%s", i, entry.time, entry.expr, entry.error and " (error)" or "")) end else dump(msg) endend