annotate LibFarmbuyer.lua @ 19:f560cf82e7d3

Smarter handling of missed item cache entries. Basic persistent logging of debug messages (options panel or /loot debug alsolog) and script to print same.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Mon, 29 Aug 2011 01:29:13 +0000
parents 5ee4edd24c13
children 8f7ec6ccf5e3
rev   line source
farmbuyer@1 1 --[[
farmbuyer@1 2 Not really meant for public use. Stuff that I keep using everywhere and
farmbuyer@1 3 got tired of reimplementing, or even copy-and-pasting. The notes here are
farmbuyer@1 4 reminders to myself.
farmbuyer@1 5
farmbuyer@1 6 Library contents:
farmbuyer@1 7 - author_debug
farmbuyer@1 8 Evaluates to true if I'm hacking on something.
farmbuyer@1 9
farmbuyer@19 10 - tableprint(t[,f])
farmbuyer@1 11 A single print() call to the contents of T, including nils; strings are
farmbuyer@19 12 cleaned up with respect to embedded '|'/control chars. If a function F is
farmbuyer@19 13 passed, calls that instead of print(). Returns the results of F, or the
farmbuyer@19 14 text string passed to print(), depending on which was used.
farmbuyer@1 15
farmbuyer@1 16 - safeprint(...)
farmbuyer@19 17 Same as tableprint() on the argument list. Returns the results of tableprint.
farmbuyer@1 18
farmbuyer@1 19 - safeiprint(...)
farmbuyer@19 20 Same as safeprint() but with <index> numbers inserted. Returns the results
farmbuyer@19 21 of tableprint.
farmbuyer@19 22 Ex: safeiprint(a,b,c) --> <1>,a,<2>,b,<3>,c
farmbuyer@1 23
farmbuyer@1 24 - t = StaticPopup(t)
farmbuyer@1 25 Fills out "typical" settings inside T, especially if T contains any kind
farmbuyer@1 26 of editbox:
farmbuyer@1 27 + cannot accept an empty editbox
farmbuyer@1 28 + pressing Enter runs OnAccept
farmbuyer@1 29 + editbox grabs keyboard focus
farmbuyer@1 30 + OnAccept runs with editbox's text in dialog.usertext
farmbuyer@1 31 Returns T.
farmbuyer@1 32
farmbuyer@1 33 - nullfunc()
farmbuyer@1 34 Empty placeholder function. Will be less useful if WoW ever moves to Lua 5.2.
farmbuyer@1 35 This is a fascinating and educational place to insert print calls...
farmbuyer@1 36
farmbuyer@1 37 - tabledump(t)/dumptable(t)
farmbuyer@1 38 If author_debug, this runs the builtin /dump command on T. Otherwise nothing.
farmbuyer@1 39
farmbuyer@1 40 - DoOnceNextUpdate(f)
farmbuyer@1 41 Runs F on the next frame refresh cycle. Multiple calls in one cycle will
farmbuyer@1 42 stack LIFO. Calls *while* processing the stack are safe, and will be stacked
farmbuyer@1 43 up for the next cycle.
farmbuyer@6 44
farmbuyer@6 45 - safecall (func, ...)
farmbuyer@6 46 A modified copy of the xpcall wrapper duplicated in every Ace3 file in the
farmbuyer@6 47 whole damn library.
farmbuyer@6 48
farmbuyer@6 49 - new(...), del(t), copy(t), clear()
farmbuyer@6 50 Ditto for table recycling.
farmbuyer@1 51 ]]
farmbuyer@1 52
farmbuyer@19 53 local MAJOR, MINOR = "LibFarmbuyer", 12
farmbuyer@1 54 assert(LibStub,MAJOR.." requires LibStub")
farmbuyer@1 55 local lib = LibStub:NewLibrary(MAJOR, MINOR)
farmbuyer@1 56 if not lib then return end
farmbuyer@1 57
farmbuyer@1 58 _G[MAJOR] = lib
farmbuyer@1 59
farmbuyer@1 60 ----------------------------------------------------------------------
farmbuyer@6 61 --[[
farmbuyer@6 62 Recycling functions yoinked from AceConfigDialog and tweaked
farmbuyer@6 63 ]]
farmbuyer@1 64 local new, del, copy, clear
farmbuyer@6 65 do
farmbuyer@6 66 local pool = setmetatable({},{__mode="k"})
farmbuyer@6 67 function clear()
farmbuyer@6 68 wipe(pool)
farmbuyer@6 69 end
farmbuyer@6 70 function new(...) -- slightly modified variant, takes optional initializers
farmbuyer@6 71 local t = next(pool)
farmbuyer@6 72 if t then
farmbuyer@6 73 pool[t] = nil
farmbuyer@6 74 for i = 1, select('#',...) do
farmbuyer@6 75 t[i] = select(i,...)
farmbuyer@6 76 end
farmbuyer@6 77 return t
farmbuyer@6 78 else
farmbuyer@6 79 return {...}
farmbuyer@6 80 end
farmbuyer@6 81 end
farmbuyer@6 82 function copy(t)
farmbuyer@6 83 local c = new()
farmbuyer@6 84 for k, v in pairs(t) do
farmbuyer@6 85 c[k] = v
farmbuyer@6 86 end
farmbuyer@6 87 return c
farmbuyer@6 88 end
farmbuyer@6 89 function del(t)
farmbuyer@6 90 wipe(t)
farmbuyer@6 91 pool[t] = true
farmbuyer@6 92 end
farmbuyer@6 93 end
farmbuyer@6 94 lib.new, lib.del, lib.copy, lib.clear = new, del, copy, clear
farmbuyer@1 95
farmbuyer@1 96
farmbuyer@1 97 ----------------------------------------------------------------------
farmbuyer@1 98 --[[
farmbuyer@1 99 safeprint
farmbuyer@1 100 ]]
farmbuyer@19 101 local tconcat = table.concat
farmbuyer@1 102 local function undocontrol(c)
farmbuyer@1 103 return ("\\%.3d"):format(c:byte())
farmbuyer@1 104 end
farmbuyer@1 105 function lib.safeprint(...)
farmbuyer@1 106 local args = { n=select('#',...), ... }
farmbuyer@19 107 return lib.tableprint(args)
farmbuyer@1 108 end
farmbuyer@1 109 function lib.safeiprint(...)
farmbuyer@1 110 local args = { n=select('#',...), ... }
farmbuyer@1 111 local last = args.n
farmbuyer@1 112 while last > 0 do
farmbuyer@1 113 table.insert (args, last, "<"..last..">")
farmbuyer@1 114 last = last - 1
farmbuyer@1 115 end
farmbuyer@1 116 args.n = 2 * args.n
farmbuyer@19 117 return lib.tableprint(args)
farmbuyer@1 118 end
farmbuyer@19 119 function lib.tableprint(t,f)
farmbuyer@1 120 for i = 1, (tonumber(t.n) or #t) do
farmbuyer@1 121 t[i] = tostring(t[i]):gsub('\124','\124\124')
farmbuyer@1 122 :gsub('(%c)', undocontrol)
farmbuyer@1 123 end
farmbuyer@19 124 local msg = tconcat(t,' ', i, tonumber(t.n) or #t)
farmbuyer@19 125 if f then
farmbuyer@19 126 return f(msg)
farmbuyer@1 127 else
farmbuyer@19 128 print(msg)
farmbuyer@19 129 return msg,t
farmbuyer@1 130 end
farmbuyer@1 131 end
farmbuyer@1 132
farmbuyer@1 133 -- See below for global versions.
farmbuyer@1 134
farmbuyer@1 135
farmbuyer@1 136 ----------------------------------------------------------------------
farmbuyer@1 137 local StaticPopupDialogs = _G.StaticPopupDialogs
farmbuyer@1 138
farmbuyer@1 139 local function EditBoxOnTextChanged_notempty (editbox) -- this is also called when first shown
farmbuyer@1 140 if editbox:GetText() ~= "" then
farmbuyer@1 141 editbox:GetParent().button1:Enable()
farmbuyer@1 142 else
farmbuyer@1 143 editbox:GetParent().button1:Disable()
farmbuyer@1 144 end
farmbuyer@1 145 end
farmbuyer@1 146 local function EditBoxOnEnterPressed_accept (editbox)
farmbuyer@1 147 local dialog = editbox:GetParent()
farmbuyer@1 148 StaticPopupDialogs[dialog.which].OnAccept (dialog, dialog.data, dialog.data2)
farmbuyer@1 149 dialog:Hide()
farmbuyer@1 150 end
farmbuyer@1 151 local function OnShow_witheditbox (dialog, data)
farmbuyer@1 152 local info = StaticPopupDialogs[dialog.which]
farmbuyer@16 153 --dialog[info.hasWideEditBox and "wideEditBox" or "editBox"]:SetFocus()
farmbuyer@16 154 dialog.editBox:SetFocus()
farmbuyer@1 155 if info.farm_OnShow then
farmbuyer@1 156 return info.farm_OnShow (dialog, data)
farmbuyer@1 157 end
farmbuyer@1 158 end
farmbuyer@1 159 local function OnAccept_witheditbox (dialog, data, data2)
farmbuyer@1 160 local info = StaticPopupDialogs[dialog.which]
farmbuyer@16 161 --dialog.usertext = dialog[info.hasWideEditBox and "wideEditBox" or "editBox"]:GetText():trim()
farmbuyer@16 162 dialog.usertext = dialog.editBox:GetText():trim()
farmbuyer@1 163 if info.farm_OnAccept then
farmbuyer@1 164 return info.farm_OnAccept (dialog, data, data2)
farmbuyer@1 165 end
farmbuyer@1 166 end
farmbuyer@16 167 local function OnHide_cleanup (dialog)
farmbuyer@16 168 dialog.data = nil
farmbuyer@16 169 dialog.data2 = nil
farmbuyer@16 170 end
farmbuyer@1 171
farmbuyer@1 172 --[[
farmbuyer@1 173 StaticPopup
farmbuyer@1 174 ]]
farmbuyer@1 175 function lib.StaticPopup (t)
farmbuyer@1 176 if t.hasEditBox then
farmbuyer@1 177 t.EditBoxOnTextChanged = EditBoxOnTextChanged_notempty
farmbuyer@1 178 t.EditBoxOnEnterPressed = EditBoxOnEnterPressed_accept
farmbuyer@1 179 if t.OnShow then
farmbuyer@1 180 t.farm_OnShow = t.OnShow
farmbuyer@1 181 end
farmbuyer@1 182 t.OnShow = OnShow_witheditbox
farmbuyer@1 183 if t.OnAccept then
farmbuyer@1 184 t.farm_OnAccept = t.OnAccept
farmbuyer@1 185 end
farmbuyer@1 186 t.OnAccept = OnAccept_witheditbox
farmbuyer@1 187 -- this calls OnCancel with "clicked", unless noCancelOnEscape is set
farmbuyer@1 188 t.EditBoxOnEscapePressed = StaticPopup_EscapePressed
farmbuyer@1 189 end
farmbuyer@1 190
farmbuyer@16 191 if not t.OnHide then
farmbuyer@16 192 t.OnHide = OnHide_cleanup
farmbuyer@16 193 end
farmbuyer@16 194
farmbuyer@1 195 t.timeout = 0
farmbuyer@1 196 t.whileDead = true
farmbuyer@1 197 t.hideOnEscape = true
farmbuyer@1 198 t.enterClicksFirstButton = true
farmbuyer@1 199
farmbuyer@1 200 return t
farmbuyer@1 201 end
farmbuyer@1 202
farmbuyer@1 203
farmbuyer@1 204 ----------------------------------------------------------------------
farmbuyer@1 205 --[[
farmbuyer@1 206 This is ugly, but at least it all gets GC'd almost immediately.
farmbuyer@1 207 ]]
farmbuyer@1 208 function lib.nullfunc() end
farmbuyer@1 209
farmbuyer@1 210 if ({
farmbuyer@1 211 ["Bandwagon"] = true, ["Kilvin"] = true, ["Waterfaucet"] = true,
farmbuyer@1 212 ["Farmbuyer"] = true, ["Oxdeadbeef"] = true, ["Pointystick"] = true,
farmbuyer@1 213 ["Angryhobbit"] = true, ["Malrubius"] = true, ["Hemogoblin"] = true,
farmbuyer@16 214 ["Ossipago"] = true,
farmbuyer@1 215 })[UnitName("player")] then
farmbuyer@1 216 lib.author_debug = true
farmbuyer@1 217 _G.safeprint = lib.safeprint
farmbuyer@1 218 _G.safeiprint = lib.safeiprint
farmbuyer@1 219 function lib.tabledump(t)
farmbuyer@1 220 _G.UIParentLoadAddOn("Blizzard_DebugTools")
farmbuyer@1 221 _G.LibF_DEBUG = t
farmbuyer@1 222 _G.SlashCmdList.DUMP("LibF_DEBUG")
farmbuyer@1 223 end
farmbuyer@1 224 else
farmbuyer@1 225 lib.tabledump = lib.nullfunc
farmbuyer@1 226 end
farmbuyer@1 227 lib.dumptable = lib.tabledump
farmbuyer@1 228
farmbuyer@1 229
farmbuyer@1 230 ----------------------------------------------------------------------
farmbuyer@1 231 --[[
farmbuyer@1 232 DoOnceNextUpdate
farmbuyer@1 233 ]]
farmbuyer@1 234 do
farmbuyer@1 235 local frame = CreateFrame("Frame", "LibFarmbuyerDONUFrame")
farmbuyer@1 236 frame:Hide()
farmbuyer@1 237 frame:SetScript("OnUpdate", function()
farmbuyer@1 238 frame:Hide()
farmbuyer@1 239 local q = frame.nexttime
farmbuyer@1 240 local tmp
farmbuyer@1 241 frame.nexttime = nil
farmbuyer@1 242 while q do
farmbuyer@1 243 tmp = q
farmbuyer@1 244 q.f(frame)
farmbuyer@1 245 q = q.n
farmbuyer@1 246 del(tmp)
farmbuyer@1 247 end
farmbuyer@1 248 end)
farmbuyer@1 249
farmbuyer@1 250 function lib.DoOnceNextUpdate (func)
farmbuyer@1 251 local nextt = new()
farmbuyer@1 252 nextt.f = func
farmbuyer@1 253 nextt.n = frame.nexttime
farmbuyer@1 254 frame.nexttime = nextt
farmbuyer@1 255 frame:Show()
farmbuyer@1 256 end
farmbuyer@1 257 end
farmbuyer@1 258
farmbuyer@1 259
farmbuyer@1 260 ----------------------------------------------------------------------
farmbuyer@6 261 --[[
farmbuyer@6 262 safecall
farmbuyer@6 263 ]]
farmbuyer@1 264 do
farmbuyer@6 265 local xpcall = xpcall
farmbuyer@6 266
farmbuyer@6 267 local function errorhandler(err)
farmbuyer@6 268 --return geterrorhandler()(err)
farmbuyer@6 269 --print("in error handler", err)
farmbuyer@6 270 return err
farmbuyer@1 271 end
farmbuyer@6 272
farmbuyer@6 273 local template = ([[
farmbuyer@6 274 local xpcall, eh = ...
farmbuyer@6 275 local method, ARGS
farmbuyer@6 276 local function call() return method(ARGS) end
farmbuyer@6 277
farmbuyer@6 278 local function dispatch (func, ...)
farmbuyer@6 279 method = func
farmbuyer@6 280 if not method then return end
farmbuyer@6 281 ARGS = ...
farmbuyer@6 282 return xpcall (call, eh)
farmbuyer@1 283 end
farmbuyer@6 284
farmbuyer@6 285 return dispatch
farmbuyer@6 286 ]]):gsub('\t',' ')
farmbuyer@6 287
farmbuyer@6 288 local function CreateDispatcher(argCount)
farmbuyer@6 289 local ARGS = {}
farmbuyer@6 290 for i = 1, argCount do ARGS[i] = "arg"..i end
farmbuyer@19 291 local code = template:gsub("ARGS", tconcat(ARGS, ", "))
farmbuyer@6 292 return assert(loadstring(code, "LibF/safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
farmbuyer@1 293 end
farmbuyer@6 294
farmbuyer@6 295 local Dispatchers = setmetatable({
farmbuyer@6 296 [0] = function(func)
farmbuyer@6 297 return xpcall (func, errorhandler)
farmbuyer@1 298 end
farmbuyer@6 299 }, {
farmbuyer@6 300 __index = function (Ds, argCount)
farmbuyer@6 301 local dispatcher = CreateDispatcher(argCount)
farmbuyer@6 302 Ds[argCount] = dispatcher
farmbuyer@6 303 return dispatcher
farmbuyer@6 304 end
farmbuyer@6 305 })
farmbuyer@6 306
farmbuyer@6 307 function lib.safecall (func, ...)
farmbuyer@6 308 if type(func) == 'function' then
farmbuyer@6 309 return Dispatchers[select('#', ...)](func, ...)
farmbuyer@6 310 end
farmbuyer@1 311 end
farmbuyer@1 312 end
farmbuyer@1 313
farmbuyer@6 314
farmbuyer@6 315 ----------------------------------------------------------------------
farmbuyer@6 316
farmbuyer@1 317 -- vim: noet