Hi everyone, I’ve created an experimental debugger that hooks into the draw loop, allowing you to see a full stack trace of errors as a watch expression, including the local variables at the time of the error. It also comes with an interactive console that you can bring up and also comes up when you have an error. This is just an experiment as we try to come up with better ways of debugging code natively in the app.
function __traceback()
local result = ""
local level = 3
local indent = ""
while true do
local info = debug.getinfo(level, "nSl")
if not info then break end
if info.what == "C" then -- is a C function?
result = string.format("%s\
%d C function", result, level-2)
else -- a Lua function
result = string.format("%s\
%d %s() : <line:%d>",result, level-2, info.name or "???", info.currentline)
end
level = level + 1
indent = indent .. " "
end
return result
end
function __errorHandler(e)
__db = e .. "\
" .. __traceback() .. "\
\
" .. "local variables:\
"
local a = 1
while true do
local name, value = debug.getlocal(2, a)
if not name then break end
if name ~= "(*temporary)" then
__db = string.format("%s\
%s = %s", __db, name, value)
end
a = a + 1
end
end
function __keyboard(key)
if true then
if key == "\
" then
pcall(loadstring(buffer))
buffer = ""
elseif key == BACKSPACE then
if string.len(buffer) > 0 then
buffer = string.sub(buffer, 1, string.len(buffer)-1)
end
else
buffer = buffer .. key
end
end
end
function res()
__paused = false
__db = ""
end
function debugea()
iparameter("showConsole",0,1)
__draw = draw
__db = ""
watch("__db")
__paused = false
__sc = false
buffer = ""
draw = function()
if __paused == false then
local status, err = xpcall(__draw, __errorHandler)
if status == false then
__paused = true
showConsole = 1
end
else
background(0, 0, 0, 255)
end
if showConsole == 1 and __sc == false then
__sc = true
__oldKB = keyboard
keyboard = __keyboard
showKeyboard()
elseif showConsole == 0 and __sc == true then
__sc = false
hideKeyboard()
keyboard = __oldKB
end
if __sc then
--background(0, 0, 0, 255)
font("Inconsolata")
fontSize(22)
textAlign(LEFT)
textMode(CORNER)
--textWrapWidth(WIDTH)
fill(255, 255, 255, 255)
text(":> " .. buffer, 5, HEIGHT-30)
end
end
end
Heres the Main.lua, which contains an example that lets you throw an error on purpose to test the debugging.
-- Use this function to perform your initial setup
function setup()
print("Hello World!")
iparameter("testError", 1,10)
debugea()
end
function test()
local blah = "what?"
local x = 10
bog = fog[5]
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
fill(255, 0, 0, 255)
stroke(255, 255, 255, 255)
ellipse(WIDTH/2 + math.sin(ElapsedTime) * 100, HEIGHT/2, 50)
if testError == 10 then
test()
end
-- Do your drawing here
end
One of the other things we are thinking of is break points and stepping, if we can get them to work. Let me know what you think.
Also, you can type res() in the interactive console to attempt to resume the draw loop when you encounter an error.