Corona SDK is a mobile application development framework that supports Lua scripting. While the integration and debugging of Corona applications has been available in ZeroBrane Studio since v0.34, starting from v0.35, ZeroBrane Studio also provides live coding. The video below demonstrates how you can use debugging and live coding with Corona applications (you may need to switch the video to 720p to make the text more readable):
The first thing you need to do is to open
main.lua file from the project you want to work with (you can do this by using
File | Open...) and then set the project directory to the directory with your
main.lua file. You can do this by going to
Project | Project Directory | Choose...
Project | Project Directory | Set From Current File.
To enable the integration shown in the demo, you need to select Corona as an interpreter in ZeroBrane Studio by going to
Program | Lua Interpreters | Corona. If you installed Corona in the default location on OSX (
/Applications/CoronaSDK) or on Windows (
C:\Program Files\Corona Labs\Corona SDK or
D:\Program Files\Corona Labs\Corona SDK), it will be found and used by the IDE.
After this is done, you can use
Project | Run command to run the application. If there is a problem with finding the Corona simulator, you will see an error message in the Output window.
require("mobdebug").start() line to your
main.lua script. This will allow you to use
Project | Start Debugging to debug your application.
The debugger in the IDE provides access to all debugging functions you would expect: breakpoints, stepping in/over/out, the stack view (to access a stack trace and all local/upvalue values, including complex ones), the watch view (to evaluate arbitrary expressions), and the console (to run code fragments and modify values in your application while it is suspended in the debugger). Some additional details are available in the Getting Started section of the documentation.
If you don't set a breakpoint before you start debugging your application, you can go to
Project | Break (or use the toolbar button) to pause your application and inspect its state and set breakpoints you need. If the exact location where the application is stopped cannot be determined (as it may be inside the Corona engine itself), you may see a message
Debugging suspended at =?:0 (couldn't activate the file). in the Output window. The application is indeed suspended and after you are done inspecting it and changing breakpoints, you can continue its execution by going to
Project | Continue.
There is one more thing that is worth mentioning. The Corona SDK engine seems to include a check that automatically restarts your application when it detects that the application is "stalled". This is exactly what happens when the application is being debugged as it passes the control back to the IDE (even though for a short time), so it may look like the application is started twice (if you put a breakpoint in your main script). To avoid this effect, you can start debugging inside
enterFrame event handler, which I'm going to demonstrate in the next section.
Live coding allows you to make changes to your application and immediately see the effect of those changes (as you saw in the demo). This is enabled by going to
Project | Run as Scratchpad, but before showing you the code, it may be useful to review how live coding works with ZeroBrane Studio. When a change is detected in the IDE, three things have to happen:
1. The currently executed application is suspended or aborted (this is configurable, but for Corona interpreter the application is suspended).
2. The new code is being executed in the environment of your application, thus making effective all changes to global variables and functions.
3. The application is then continued from the same point where it's suspended.
These aspects are important, because you may need to apply small changes to your code to make it "live coding" friendly. For example, a usual way to registering an event handler is this (assuming
onUpdate is the event handler function):
However, if you modify this function while running as scratchpad, nothing visible happens. As you may guess, when you register an event listener, the engine stores a reference to the
onUpdate function and any change to the function doesn't invalidate the reference. You may remove and re-add the event listener, but there is a simpler way: we can wrap a call to
onUpdate into an anonymous function, thus allowing us make changes to
onUpdate that the engine will see:
Runtime:addEventListener("enterFrame", function(event) pcall(onUpdate, event) end)
We can also add
pcall around a call to
onUpdate so that any run-time errors happening in that function when you make changes, don't kill your application. All the compilation error will be reported to you in the IDE and only valid Lua code will be executed in the application.
Now we can look at the
done = nil function onUpdate(event) -- let the first call to onUpdate to return quickly; -- start the debugging during the second call to trick Corona SDK -- and avoid restarting the app. if done == nil then done = false return end if not done then require("mobdebug").start() done = true end -- try to modify the following three lines while running this code live -- (using `Project | Run as Scratchpad`) ball:setFillColor(0, 127, 255, 255) bkgd:setFillColor(127, 0, 127) xspeed, yspeed = 6, 9 end
In this fragment we use a global variable
done to control the logic in the
onUpdate handled. The first time the handler is called, the variable is
nil, which sets
false and returns from the method. On the second call the debugger is started and the variable is set to
true to avoid starting the debugger again. The reason why we want to return quickly from the method during the first call is to trick that check that Corona SDK does that causes the app to be restarted when doing debugging.
The last three lines in the
onUpdate method can be modified during live coding (as shown in the demo) and the changes are immediately executed with results immediately shown. You can apply the same type of structure to your projects to pick a code fragment you want to experiment with. Note that
ball, bkgd, xspeed, and yspeed are global variables; the current implementation will not work with upvalues as the newly created version of
onUpdate will not "see" the current values of those upvalues.