(This post is by Christopher Reimold, who tested and documented the details of Adobe Lightroom plugin debugging.)

Adobe Photoshop Lightroom is a photo management and editing program that offers the ability to extend its functionality through plugins written in Lua. Debugging Lightroom plugin scripts has often been a somewhat cumbersome process, in which one had to resort to printing of variables to the console in order to understand what's going on in your plugin. However, there is now the possibility to use full in-editor interactive debugging which we will briefly demonstrate in this article.

Minimally useful demo Lightroom plugin script

We use the following short script to demonstrate developing and debugging of a Lightroom (LR) plugin in ZeroBrane Studio Lua IDE. The plugin shows the exposure value to the user. To create a plugin for LR, you have to create at least two files and one directory:

(1) The Info.lua file, which is a manifest that provides information about your plugin to LR. Its name is always Info.lua.

(2) Your actual plugin, which is called ShowExposureValue.lua in this example. It is referenced from your Info.lua file, as shown in the highlighted fragment above.

Put these two files into a directory called ExposureValue.lrplugin; the directory can reside anywhere on your hard disk. The .lrplugin extension will make LR recognize this directory as a plugin. On OSX, .lrplugin directories are recognized and treated as a package (single file). This can sometimes be problematic during development, and you can thus use .lrdevplugin as an extension on OSX if you want to avoid this.

If you want to learn more about developing an LR plugin, please have a look at the Lightroom SDK, in particular the programmer's guide and the API reference.

Continue reading Debugging Adobe Lightroom plugins with ZeroBrane Studio

ZeroBrane Studio has supported Corona SDK debugging for over a year, but one of the less known features of the integration is that it supports on-device debugging in addition to debugging in the simulator.

Since you can't initiate this process from the IDE, it requires slightly different steps:

1. You need to include the debugger component (mobdebug.lua) with your application code (to allow require 'mobdebug' command to execute successfully). You can find it under lualibs/mobdebug in ZeroBrane Studio folder.

2. You need to include require('mobdebug').start("IP-address-of-computer-running-ZBS") in your code. Note that with "regular" debugging you simply include require("mobdebug").start(), but in this case you need to provide a domain name or an IP address of the computer with the IDE as this is where the debugger in the application will connect to.

3. You need to start debugger server in the IDE by going to Project | Start Debugger Server.

4. If you do debugging on Android devices, you may need to add android.permission.INTERNET permissions to the build settings, as documented here.

If you open your Lua files in the IDE and you run your application on the device, you should see the message in the IDE that debugging has started. Most of debugging functions should work (stepping, breakpoints and the stack view), but any function that requires loadstring (remote console, watches, or value tooltips) won't work and will cause a run-time error in your application.

If you want to protect yourself from those run-time errors, you may run the following command in the local console ide.debugger.options = {noshell = true, noeval = true}; this will disable remote console and watches/tooltip evaluations to avoid using loadstring in the debugger. This configuration will be in effect for any debugging started remotely and will reset when you start any debugging from the IDE itself.

A better fix would be to allow Corona SDK to support loadstring during debugging; you may upvote this feature request that asks Corona to implement this.

Keszegh Balazs, one of Gideros forum users put together a detailed overview of using ZeroBrane Studio for debugging of Gideros applications, including on-device debugging. Take a look at the tutorial if you have any questions about Gideros debugging with ZeroBrane Studio.

ZeroBrane Studio is often used for remote debugging, when the application being debugged is running on a different computer or a device, and it is very convenient to be able to "redirect" its printed output to the IDE. The IDE supports this functionality and not only allows "redirecting" of the printed output, but also pretty prints the results such that local t = {a = 1, b = 2} print(t) will print {a = 1, b = 2}. This option is turned on by default for some interpreters and can be explicitly enabled using debugger.redirect configuration option.

This is all good, but what if you have a long running process and want to be able to use this "remote" printing as a log file. The plugin below allows you to do just that: it will dump all the "remote" output to a file (output.log by default) in the current project folder. It also limits the number of records in the Output window (100 by default) to allow you to generate a large number of records without taking more memory.

Continue reading Saving debugging output to a file

Lua ecosystem has two package managers: LuaDist and LuaRocks. Both managers allow users to install Lua and C modules and work on Windows, Mac OS X and Linux, but have some important differences in how they operate, which I'll briefly go over.


  • Unified build system for all modules based on CMake.
  • Mixed binary/source distribution that allows to use whatever dependency is available in the repository.
  • Everything is stored in git (using github as host) including the repository manifest. Tags are used for versions and branches for binary distributions.
  • Provides "batteries included" binary distributions (as a successor to Lua for Windows).
  • Relies on few Lua modules (luasocket, lfs, lua-git) for its implementation.
  • Allows for building the modules manually without using LuaDist.
  • Can be used from a command line or as a library (local ld = require "dist"; ld.install("luaexpat"))
  • Uses dist.info files for package specification information (mostly for dependency tracking, no build information).
  • Provides support for packaging modules for distribution.
  • Includes about 260 projects (as of November 2013; based on the number of sub-modules in the repository).
  • Includes a good number of pre-compiled binaries for Windows, but many for outdated module versions.


  • Supports local and remote repositories.
  • Distributed as a Lua scripts without dependencies, but relies on Unix tools for module deployment and installation.
  • Uses .rockspec files as a package specification file.
  • Uses "native" build instructions for each rock.
  • Includes rocks for 330 projects (as of November 2013).
  • Have several repositories: main one with manual curation and rocks.moonscript repository that supports (non-curated) rock submission and download statistics.

As we are talking about Lua module distribution, I'll also mention a nice project of Pierre Chapuis: lua toolbox. It provides a list of modules with short descriptions and their endorsement by various users (along with a simple tagging mechanism).

Both systems are easy to use as command-line tools. When you have one of the package managers installed, it's a matter of running luarocks install module or luadist install module commands to get the modules you need (assuming you have the tools available and don't run into compilation issues). It is certainly possible to setup LuaDist and LuaRocks to deploy modules to the directories you need and make those directories available to your project (see for example this nice write up by Thijs Schreijer on Setting up Lua installation on Windows using Lua Rocks and ZeroBrane Studio), but I'd prefer to have something simpler for users who may be new to programming and Lua.

I teach a semester long computer science class at a local high school during summer (using Lua and ZeroBrane Studio) and sometimes want to install Lua modules like penlight to my students' computers and use them from ZeroBrane Studio. I have 18 students using their own laptops running different systems and want to be able to say "install penlight" and then make "require 'pl.strict'" to work in their Lua scripts. The coming version (v0.40) of ZeroBrane Studio (and the current master branch) integrates with LuaDist and allows you to do just that.

Continue reading Lua package managers and integration with ZeroBrane Studio

After ZeroBrane Studio for Vera was released, I received several questions whether it is possible to load files from the device and edit them. The product already allows to upload files to Vera devices and to download log files, but it doesn't support editing of remote files and I thought it would be useful and interesting to implement this.

What you see below is the plugin that does just that. It adds a new menu item (File | Open Remotely...) that asks for a file name and then loads that file in a new editor tab. You can edit and save that file as you'd do with any other file. The main difference is that it only works when a debugging session is in progress as it uses the debugging mechanism to retrieve and save the files.

Continue reading Remote file editing while debugging

ZeroBrane Studio has already been used to debug Lua in various applications, from game engines to medical systems. Several months ago one of the ZeroBrane Studio users asked if it would be possible to debug Lua application running on Vera home automation devices. It turned out to be possible, but not trivial and I decided to release this integration as a separate product that allows Vera users to debug their Lua applications while they are running on Vera devices.

These devices look like network routers with additional functionality to control various devices and access sensors using z-wave protocol. This integration allows you to write a Lua script that may start a sprinkler system at a specific time, but only if it wasn't raining that day. Or to turn lights on when a motion detector is triggered. Or to turn the heating system on before you come home. You can probably come up with many other interesting uses that are only limited by the devices you may have (and your budget).

As you can see in the demo (you may want to switch to 720p for better quality), ZeroBrane Studio for Vera allows Vera users to not only debug their Lua scripts, but also provides auto-complete for luup (Lua Universal PnP API) calls, ability to upload files and download logs, restart the Lua engine and some other device-specific functions.

The documentation page for the project provides links to Vera resources and detailed descriptions for debugging of Lua scripts started the IDE and scripts in plugins and scenes that are triggered from the device itself.

ZeroBrane LLC, the company behind ZeroBrane Studio, has applied for a small business grant from Chase. We now need 250 votes to get to the second round where applications are being considered by a panel of judges and would appreciate your help.

Please cast your vote and spread the word to help us be considered for the grant! The grant will allow us to provide more educational content, enable collaborative editing, add version control integration, and more.

The voting is only available through Facebook Connect; if you don't see your vote accepted, try enabling popups and disabling Facebook filters you may have. Thank you!

It's expected to be able to watch an expression in the debugger and ZeroBrane Studio provides that functionality. You can specify an expression and it will be evaluated when the application is stopped in the debugger.

This is all good, but the application needs to be stopped to refresh the values and there are situations when you want to see the values while your application is running. ZeroBrane Studio supports redirecting of program output to the Output window in the IDE (when debugging) and (with a bit of magic) this can be leveraged to send the values you want to appear in the Watch window.

What does it give you? You can then include in your code print statements of the form print("foo=", someValue) and print("bar=", someOtherValue) and those values will be shown in the Watch window as foo and bar. The values can be complex values that will be pretty-printed for you (this is the same functionality that "prints" complex values to the Output window during debugging). For example, the script below will show values for a, b, c, and d as defined in the print expressions:

for i = 1, 1000 do
  print("a=", {i, i*2})
  if 0 == i % 10 then print("b=", {i, i*3}, collectgarbage("count")) end
  if 0 == i % 100 then print("c=", {i, i*4}, os.clock()) end
  print("d=", math.random())

Since the "printed" output is sent over sockets, this also works when you debug your application remotely, for example, when you debug something running on a mobile device from ZeroBrane Studio running on a desktop.

For simple values (like d in the example above) the plugin will also calculate min, max, avg, and count values. The result may look similar to this (if you run it you will see that the numbers are updated while your app is running):

Continue reading Real-time watches with ZeroBrane Studio

The latest version of ZeroBrane Studio includes several recent updates: LuaJIT is now a default interpreter instead of Lua 5.1, Lua 5.2 is included for all supported platforms (just select "Lua 5.2" from the list of interpreters), and luasocket has been upgraded to v3.0.

Note that "normal" Lua5.1 interpreter is no longer included, but as before you can continue using the IDE to debug your Lua 5.1 applications (you can also use your own Lua 5.1 interpreter if you want).

LuaJIT is compiled with LUAJIT_ENABLE_LUA52COMPAT, which enables some of Lua5.2 features (see this link for details) and allows to do syntax checks for "goto" and other features. The local console is using LuaJIT as well.

All these changes are going to be included in the coming release (0.39), so please report any issues or incompatibilities you notice.

Note that while Lua 5.2 (and luasocket compiled against Lua 5.2) are included, you may still run into issues if you debug your own Lua 5.2 applications that statically link the interpreter (at least on Windows). The reason for that is that when you load luasocket, it loads lua52.dll and you end up with multiple VMs (and may get "PANIC: unprotected error in call to Lua API (multiple Lua VMs detected)" message). There are (at least) two ways to resolve this: (1) compile luasocket into your app the same way you include lua interpreter itself; you won't need anything else except one mobdebug.lua file to debug your app, or (2) use proxy dll; it will look like lua52.dll, but will actually proxy your calls to your statically compiled lua library, avoiding problems with multiple VMs. The proxy dll is for Lua 5.1, but you can tweak the script to make it work for Lua 5.2. See this SO answer for related discussion.

I received several questions about whether it's possible to add ability to see the same file in different editor tabs in ZeroBrane Studio and thought it would be a good test for the current plugin interface.

The Scintilla editor component that is used in ZeroBrane Studio includes a nice feature that allows two editors to share the same document, with changes made in one editor being immediately seen in the other one. The code is very simple ('e1' is the editor you are cloning and 'e2' is the new editor):

 local docpointer = e1:GetDocPointer()

I wrapped this code in a plugin that allows users to clone an editor tab vertically or horizontally. Save this plugin as cloneview.lua to packages/ folder, restart ZeroBrane Studio, and right click on one of editor tabs to select 'Clone Vertically' and 'Clone Horizontally'.

return {
  name = "Clone view plugin",
  description = "Clones the current editor tab.",
  author = "Paul Kulchenko",
  version = 0.11,

  onMenuEditorTab = function(self, menu, notebook, event, index)
    local idvert = ID(self.fname..".clone.vert")
    local idhorz = ID(self.fname..".clone.horz")

    local cloner = function(event)
      local e1 = ide:GetEditor(index)
      local e2 = NewFile("clone: "..ide:GetDocument(e1):GetFileName())
      local docpointer = e1:GetDocPointer()
        event:GetId() == idhorz and wx.wxRIGHT or wx.wxBOTTOM)

    menu:Append(idhorz, "Clone Horizontally")
    menu:Append(idvert, "Clone Vertically")
    notebook:Connect(idvert, wx.wxEVT_COMMAND_MENU_SELECTED, cloner)
    notebook:Connect(idhorz, wx.wxEVT_COMMAND_MENU_SELECTED, cloner)

[Updated on 09/21/2013] The plugin code has been updated to use index parameter that refers to a correct index in split notebook situations. This functionality requires using v0.39 of ZeroBrane Studio (when released) or the current master.

There has been recent interest in getting ZeroBrane Studio to work with Cocos2d-x, so I decided to put my notes together on how this can be accomplished.

Debugging with ZeroBrane Studio requires using luasocket and because it can be integrated with a Cocos2d-x project in different ways, you may have several options to consider.

Continue reading Cocos2d-x simulator and on-device debugging with ZeroBrane Studio

[Update 10/18/2013] The bounty was for a specific issue with ZeroBrane Studio IDE (as documented below) and not for any problem related to this website.

[Update 10/04/2013] The bounty has been withdrawn as the issue appears to be fixed. If you can still reproduce it with the current master, please leave a comment.

Bug bounty programs are nothing new; Google, Mozilla, Microsoft and many others use them to find security vulnerabilities and bugs (and these program are reported to be cost effective). There has been an issue in ZeroBrane Studio that have been bugging me for almost two months, so I decided to offer a bounty for it.

I offer $250 dollars to the first person who can figure out what's causing the bug and I'll add $150 if you can provide a fix for it (so $400 USD total for a fix), payable via PayPal or as an Amazon giftcard. All the source code for ZeroBrane Studio is available on github and the code for wxwidgets and wxlua is available as well.

The details of the crash as well as associated stack traces are available in this ticket. Please use the ticket for discussion.

The bug only happens under Windows 7 64bit. I have received several reports of the same crash happening on different computers, all running Windows 7 64bit. I also have several users who use the same system, but have never experienced this crash. The crash most likely happens when typing text and is likely to be related to auto-complete, but I have so far been unable to reproduce it.

There are some strange things showing up on the stack trace that I've discussed with John Labenski (the author of wxlua). I can provide wx.dll built with debug information (it's rather large, 186M) or you can build one yourself using this build script (run it as bash build-win32.sh wxwidgets lua wxlua debug). Note that you don't need to build anything else and can run ZeroBrane Studio from a cloned repository.

The fix has to include code that can be applied to ZeroBrane Studio or upstream (wxlua or wxwidgets) to eliminate the issue. The bounty will not be awarded if it is illegal to do so.

ZeroBrane Studio is now available in seven languages! Thanks to all who contributed translations:

Starting from v0.38 ZeroBrane Studio includes experimental support for scope aware variable indicators. These indicators are added to mark local, global, masked, and masking variables and are calculated in real-time as the code is being written. Having this ability changes the way you write code, and does catch a lot of errors and 'wrong thinking' cases.

ZeroBrane Studio provides default indicators that can be updated; both the colors and the appearance can be changed as described in the documentation. For example, styles.indicator.varmasked = nil will disable masked indicator.

In addition to providing real-time indicators, the IDE uses the same mechanism to provide "Go To Definition" and "Rename All Instances" options available from the popup menu in the editor. The items in the popup menu also show the number of instances detected and the line where the definition is found. "Go To Definition" item is enabled for local variables/functions, function parameters, and loop variables.

You can quickly select instances of a variable by doing Ctrl/Cmd-DblClick on it. All instances get selected with the main one having slightly darker background and can be edited to update the name. In addition to that you can navigate selected instances using Find Next/F3 and Find Previous/Shift-F3; it will move the selection to the next/previous instance (and scroll the editor to make it visible).

From its very first version ZeroBrane Studio supported debugging of embedded Lua code; it was only a matter of adding require('mobdebug').start() (when running on the same computer) and it would start a debugging session in the IDE.

There was one case though when it didn't work: if the environment that loads some Lua code doesn't provide a file name, the IDE doesn't have information about what resource to load for debugging. The simplest example to see this to try to try to do something like loadstring("print(1); print(2)"). When this code is executed under the debugger, the source of this code is shown as print(1); print(2). One workaround for this was to specify the second parameter to loadstring: chunkname, which is then used by the Lua debug interface where it reports the source.

This workaround only works when you can modify the fragment that loads Lua code and in those cases where this is not an option (for example, when you need to use luaL_loadstring, which provides no way to label the chunk with its file path) you were out of luck.

This situation has changed now. Starting from v0.38, ZeroBrane Studio provides a way to debug these code chunks without any additional configuration. When it gets a request that has a code fragment instead of a file name as its source, it will try to find an open editor with the content that matches that source and if there is no match will open a new editor and load the fragment in it.

This allows to use the debugger to "step into" calls to functions returned by loadstring and also debug Lua scripts executed in environments like LuaJava. You can also look at the stack trace, set breakpoints, and use local console as you can normally do in the debugger.

Marmalade SDK is a cross-platform toolkit for developing games and mobile applications on a variety of desktop and mobile platforms. It also provides Marmalade Quick, a flexible programming environment based on Cocos2d-x with Lua scripting, which makes it a good fit to support in ZeroBrane Studio. Starting from v0.35, ZeroBrane Studio provides integration with Marmalade Quick and implements debugging support for Quick scripts; the video below demonstrates these capabilities (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...
or using Project | Project Directory | Set From Current File.

To enable the integration shown in the demo, you need to select Marmalade Quick as an interpreter in ZeroBrane Studio by going to Program | Lua Interpreters | Marmalade Quick. If you installed Marmalade in the default location on OSX (/Developer/Marmalade) or on Windows (C:\Marmalade or D:\Marmalade, or in \Program Files\Marmalade), it will be found and used by the IDE. The IDE will also check for the Marmalade .MKB file in the project folder or its parent folder and will use the information from that file to set the environment for running your project.

After this is done, you can use Project | Run command to run the application. If there is a problem with finding the Marmalade Quick environment, you will see an error message in the Output window.

Enabling debugging

Add require("mobdebug").start() line to your main.lua script. This will allow you to use Project | Start Debugging to debug your application.

Continue reading Marmalade Quick debugging with ZeroBrane Studio

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...
or using 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.

Enabling debugging

Add require("mobdebug").start() line to your main.lua script. This will allow you to use Project | Start Debugging to debug your application.

Continue reading Debugging and live coding with Corona SDK

I received several reports of files being loaded empty in ZeroBrane Studio and it turned out that it is caused by malformed UTF-8 code; the most frequent offenders are quotes copied from text with other encodings. For example, ISO 8859-1 has grave and acute accents with codes 0x91 and 0x92 and Windows CP1250 has single and double quotation marks with codes 0x91-0x94, with all these codes being invalid in UTF8 ("an unexpected continuation byte"). You can check ASCII and Unicode quotation marks for some details on various types of quotation marks).

There is no shortage of recommendations on how to detect malformed UTF-8 code, but most of them are based on using iconv and I was looking for something Lua-based. There is a StackOverflow answer that provides a clever way to iterate over UTF-8 code points, but it only works correctly over valid UTF-8 strings.

So I turned to other languages and found exactly what I was looking for in Test::utf8: a regexp to detect a valid UTF-8 sequence. The rest was easy; here is the fixUTF8 method that takes a string and "fixes" it:

function fixUTF8(s, replacement)
  local p, len, invalid = 1, #s, {}
  while p <= len do
    if     p == s:find("[%z\1-\127]", p) then p = p + 1
    elseif p == s:find("[\194-\223][\128-\191]", p) then p = p + 2
    elseif p == s:find(       "\224[\160-\191][\128-\191]", p)
        or p == s:find("[\225-\236][\128-\191][\128-\191]", p)
        or p == s:find(       "\237[\128-\159][\128-\191]", p)
        or p == s:find("[\238-\239][\128-\191][\128-\191]", p) then p = p + 3
    elseif p == s:find(       "\240[\144-\191][\128-\191][\128-\191]", p)
        or p == s:find("[\241-\243][\128-\191][\128-\191][\128-\191]", p)
        or p == s:find(       "\244[\128-\143][\128-\191][\128-\191]", p) then p = p + 4
      s = s:sub(1, p-1)..replacement..s:sub(p+1)
      table.insert(invalid, p)
  return s, invalid

The logic is very simple: it checks for all valid code points of various length and replaces those characters that do not match.

The reason to have replacement is that you wouldn't want to silently remove malformed characters; ideally you'd replace them with some infrequent, but valid character that would be easy to find if needed. I picked "\022" as it is a control character that is rarely seen in texts and is usually shown as [SYN] glyph. Now ZeroBrane Studio will generate a message like this: "Replaced an invalid UTF8 character with [SYN]."

This is not the fastest way, but works well if there are few replacements. If you expect a large number of replacements, you can store all fragments in an array and concatenate them all at once using table.concat function to avoid repeated memory allocation to store a modified string.

[Updated 10/01/2013] Fixed an issue with UTF8 sequences; thanks to Enrique García for the fix.
[Updated 10/29/2013] Fixed an issue with one of the sequences that allowed for some invalid characters to pass as valid; thanks to Vadim Zeitlin for bringing this up.

I added a documentation section to the project website that covers various aspects of the ZeroBrane Studio IDE:

I also updated the screenshots page and added a community page with information about an IRC channel and a maillist.

Recent Comments


I am Paul Kulchenko.
I live in Kirkland, WA with my wife and three kids.
I do consulting as a software developer.
I study robotics and artificial intelligence.
I write books and open-source software.
I teach introductory computer science.
I develop a slick Lua IDE and debugger.