Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions BugSack.toc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@

embeds.xml

parsestack.lua
plugins.lua
plugin_stack_compact.lua
locales.lua
core.lua
sack.lua
Expand Down
20 changes: 19 additions & 1 deletion config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,27 @@ frame:SetScript("OnShow", function(frame)
mute:SetChecked(addon.db.mute)
mute:SetPoint("TOPLEFT", minimap, "BOTTOMLEFT", 0, -8)

local info = {}
local pluginFormatterDropdown = CreateFrame("Frame", "BugSackPluginFormatter", frame, "UIDropDownMenuTemplate")
pluginFormatterDropdown:SetPoint("TOPLEFT", mute, "BOTTOMLEFT", -15, -10)
pluginFormatterDropdown.initialize = function()
for name,formatter in pairs(addon.Plugins.formatters) do
wipe(info)
info.text = formatter.label or formatter.name
info.value = formatter.name
info.func = function(self)
addon.db.pluginFormatter = self.value
addon:UpdateDisplay()
end
info.checked = name == addon.db.pluginFormatter
UIDropDownMenu_AddButton(info)
end
end
pluginFormatterDropdown.Text:SetText(L["Formatter plugin"])

local info = {}
local fontSizeDropdown = CreateFrame("Frame", "BugSackFontSize", frame, "UIDropDownMenuTemplate")
fontSizeDropdown:SetPoint("TOPLEFT", mute, "BOTTOMLEFT", -15, -10)
fontSizeDropdown:SetPoint("TOPLEFT", pluginFormatterDropdown, "BOTTOMLEFT", -15, -10)
fontSizeDropdown.initialize = function()
wipe(info)
local fonts = {"GameFontHighlightSmall", "GameFontHighlight", "GameFontHighlightMedium", "GameFontHighlightLarge"}
Expand Down
44 changes: 33 additions & 11 deletions core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,19 @@ do
if type(sv.fontSize) ~= "string" then sv.fontSize = "GameFontHighlight" end
if type(sv.altwipe) ~= "boolean" then sv.altwipe = false end
if type(sv.useMaster) ~= "boolean" then sv.useMaster = false end
if type(sv.pluginFormatter) ~= "string" then sv.pluginFormatter = "default" end
addon.db = sv

-- add our default formatter
addon.Plugins:RegisterFormatter({
name="default",
label="Default",
description="Classic BugSack stacktrace",
formatStack=addon.ColorStack,
formatMessage=addon.ColorMessage,
formatLocals=addon.ColorLocals,
})

-- Make sure we grab any errors fired before bugsack loaded.
local session = addon:GetErrors(BugGrabber:GetSessionId())
if #session > 0 then onError() end
Expand Down Expand Up @@ -213,18 +224,29 @@ do
end
addon.ColorLocals = colorLocals

local errorFormat = "%dx %s"
local errorFormatLocals = "%dx %s\n\nLocals:\n%s"
local errorFormatMessage = "%dx %s"

local function colorMessage(counter,message)
message = message:gsub("^%[string \"(.-)\"%]:","%1:")
return errorFormatMessage:format(counter,message)
end
addon.ColorMessage = colorMessage

local errorFormatStack = "\n\nStack:\n%s"
local errorFormatLocals = "\n\nLocals:\n%s"

function addon:FormatError(err)
if not err.locals then
local s = colorStack(tostring(err.message) .. (err.stack and "\n"..tostring(err.stack) or ""))
local l = colorLocals(tostring(err.locals))
return errorFormat:format(err.counter or -1, s, l)
else
local s = colorStack(tostring(err.message) .. (err.stack and "\n"..tostring(err.stack) or ""))
local l = colorLocals(tostring(err.locals))
return errorFormatLocals:format(err.counter or -1, s, l)
end
local formatter = addon.Plugins:GetFormatter()

local message,stack,locals = err.message,err.stack,err.locals

message,stack,locals = formatter.preformatError(message,stack,locals)

local ret = ""
ret = ret .. formatter.formatMessage(err.counter or -1,message)
ret = ret .. errorFormatStack:format(formatter.formatStack(stack))
if locals then ret = ret .. errorFormatLocals:format(formatter.formatLocals(tostring(locals))) end
return ret
end
end

Expand Down
3 changes: 3 additions & 0 deletions locales.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ L["chatFrameDesc"] = "Prints a reminder to the chat frame when an error is encou
L["Chatframe output"] = "Chatframe output"
L["Current session"] = "Current session"
L["%d bugs have been sent to %s. He must have BugSack to be able to examine them."] = "%d bugs have been sent to %s. He must have BugSack to be able to examine them."
L["Formatter plugin"] = "Formatter plugin"
L["Failure to deserialize incoming data from %s."] = "Failure to deserialize incoming data from %s."
L["Filter"] = "Filter"
L["Filter addon mistakes"] = "Filter addon mistakes"
Expand Down Expand Up @@ -577,4 +578,6 @@ elseif locale == "itIT" then
--L.useMasterDesc = "Play the chosen error sound over the 'Master' sound channel instead of the default one."
end

setmetatable(L,{__index=function(t,k) return k end})

addon.L = L
98 changes: 98 additions & 0 deletions parsestack.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
ParseStack = {}

--[[
[string "=[C]"]: in function `RunScript'
[string "=(tail call)"]: in main chunk
[string "@Interface\SharedXML\UIDropDownMenu.lua"]:71: in function `UIDropDownMenu_Initialize'
[string "@Interface\FrameXML\ChatFrame.lua"]:2174: in function `?'
[string "@Interface\FrameXML\EasyMenu.lua"]:21: in function `EasyMenu'
[string "EasyMenu("qqq")"]:1: in main chunk
[string "*:OnEnterPressed"]:1: in function <[string "*:OnEnterPressed"]:1>
[string "*ChatFrame.xml:127_OnEnterPressed"]:1: in function <[string "*ChatFrame.xml:127_OnEnterPressed"]:1>
--]]

function ParseStack.parsePath(path)
local is_addon = path:lower():match("^interface/addons/")
local is_blizz
path = path:gsub("^[Ii]nterface/","")
path = path:gsub("^[Aa]dd[Oo]ns/","")

local parts = {strsplit(":",path)}
local fileparts = {strsplit("/",parts[1])}
local addon,folder,file
if #fileparts>0 then
addon = is_addon and tremove(fileparts,1)
is_blizz = is_addon and addon:find("Blizzard_",1,true) or (fileparts[1]=="FrameXML" or fileparts[1]=="SharedXML")
if addon and is_blizz then tinsert(fileparts,1,addon) addon=nil end -- back into the path, Blizzard_ addons are not addons
file = tremove(fileparts,#fileparts)
if #fileparts>0 then folder=table.concat(fileparts,"/") end
end
return addon,folder,file,not not is_addon,not not is_blizz
end
local parsePath=ParseStack.parsePath

function ParseStack.parseStack(stack)
if type(stack)=="string" then stack={strsplit("\n",stack)} end
local parsedStack = {}
for i,line in ipairs(stack) do
local orig_line = line
local p = {raw=line}
local _
p.source,_ = line:match("^%[string \"(.-)\"%]:(.*)") -- [string "source"]: | 1: in function `blabla'
if _ then line=_ end
p.linenum,_ = line:match("^(%d+): (.*)") -- 1: in function
if _ then line=_ else line=line:gsub("^ ","") end

if not p.source then
--

elseif p.source=="=[C]" then
p.source_type="c"

elseif p.source=="=(tail call)" then
p.source_type="tailcall"

elseif p.source:sub(1,1)=="@" then -- source file
p.source_type="lua"
p.source_addon,p.source_folder,p.source_file,p.source_is_addon,p.source_is_blizz=parsePath(p.source:sub(2))

elseif p.source:sub(1,1)=="*" then -- xml?
p.source_type="xml"
p.source_addon,p.source_folder,p.source_file,p.source_is_addon,p.source_is_blizz=parsePath(p.source:sub(2))
p.source_file,p.source_linenumx,p.source_handler = p.source:match("^.([^:]+):(%d+)_(.*)")

elseif p.source:find(".xml:<",1,true) then -- xml inline
p.source_type="xml_inline"
local path,tag = p.source:match("(.*):<(.-)>")
p.source_addon,p.source_folder,p.source_file,p.source_is_addon,p.source_is_blizz=parsePath(path)
p.source_xmltag = tag

else
p.source_type="string"
end

if line=="in main chunk" then
p.function_main = line=="in main chunk"
elseif line=="?" then
p.function_unknown = true
else
p.function_name = line:match("^in function `(.-)'")
p.function_angle = line:match("^in function <(.-)>")
if p.function_angle then
p.function_file,p.function_startline = p.function_angle:match("([^/]+):(%d+)$") -- just file name and line
if p.function_file then p.function_angle=nil end
if p.function_file=="[string \""..p.source.."\"]" then
p.function_same=true
p.function_file=nil
p.function_name=nil
end
end
if not p.function_name and not p.function_file and not p.function_same then
p.function_raw = line
end
end

tinsert(parsedStack,p)
end
return parsedStack
end
Loading