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][\123-\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)
        or p == s:find(       "\240[\144-\191][\128-\191]", p) then p = p + 3
    elseif 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
    else
      s = s:sub(1, p-1)..replacement..s:sub(p+1)
      table.insert(invalid, p)
    end
  end
  return s, invalid
end

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.

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.

Some of the users of ZeroBrane Studio had troubles running the live coding demo that Andy Bower put together, so I decided to post a very simple example that can be used as a starting point. I also packaged these files as a ZeroBraneEduPack project, so you can browse and download all these files together (they will also be packaged with the next release of ZeroBrane Studio).

Continue reading Gideros live coding: a simple example

About a year ago I released the first public version of ZeroBrane Studio. I would like to use this opportunity and thank many people who helped with this project and made it so much fun.

I'd like to first thank Christoph Kubisch who worked on Estrela Editor that ZeroBrane Studio originated from and continued contributing to ZBS. Thanks to the Kepler project for their work on RemDebug that MobDebug originated from, which is at the core of many capabilities that ZeroBrane Studio provides. I'd like to thank my son, Daniil Kulchenko for his feedback and his help with Linux and OSX builds.

I'd like to thank many users for their feedback, support, and contributions (including payments for ZBS). I'd like to thank those who helped with patches, improvements, and their time to test changes. This is an incomplete list in no particular order:

  • Srdjan Markovic for Corona auto-complete support and Zenburn color scheme.
  • Roland Yonaba for French translation.
  • Leo Bartoloni for Italian translation.
  • Inigo Sola for Spanish translation.
  • toiffel for Russian translation, Linux/OSX/Windows CMake-based launcher build, and several patches.
  • Fringale for spec and API files cleanup and update for Lua 5.2.
  • Marcel van Herk for assistance with scratchpad break/resume functionality.
  • Andy Bower and Atilim Cetin for their assistance with Gideros integration and live coding.
  • Jonathan Shieh for his work on project navigation and user settings.
  • Aidar Rakhmatullin for his help with unicode support on Windows.
  • John Labenski for his help with wxlua fixes and builds.
  • Students in the introductory computer science class I taught last summer for stress-testing the IDE. How else would I find out that the system had an issue with single quotes or exclamation marks in file names?
Continue reading ZeroBrane Studio is one year old

GSL Shell is an interesting project by Francesco Abbate that implements an interactive shell with access to a collection of mathematical methods for numerical computations in GNU Scientific Library (GSL). It's based on LuaJIT engine, which makes it very fast; it also includes extensive documentation with many examples.

One of ZeroBrane Studio users opened an issue asking about integration with GSL shell and I decided to take a look. After solving several problems with the help of GSL Shell author (Francesco Abbate) and enthusiastic users (coppolajj and Marcel van Herk), things started to work. Note that you need to download and install luasocket library compiled to work with GSL shell.

It is now possible and is (going to be) available in ZeroBrane Studio v0.34 to run and debug GSL shell scripts, like the one below, which plots the Moebius surface:

use 'math'
require 'plot3d'
x = |u,v| (1 + 1/2 * v *cos(u/2))*cos(u)
y = |u,v| (1 + 1/2 * v *cos(u/2))*sin(u)
z = |u,v| 1/2 * v * sin(u/2)

require('mobdebug').start()

graph.surfplot({x, y, z}, 0, -1, 2*pi, 1,
  {gridu= 60, gridv= 4, stroke= true})

There are several things that are interesting about this small example. First, you need to specify require('mobdebug').start() to start debugging (this is the same way you do it for Love2d, Gideros, and some other engines). You also need to select "GSL-shell" as the interpreter by going to Project | Lua Interpreter.

Second, one can debug functions x, y, and z, even though GSL shell provides an alternative non-standard (for Lua) syntax to define functions, which is used in this example. You can not only set breakpoints on lines where these functions are defined, but you can also split those one-line functions into multiple lines and step through them, inspect variables, modify them, and so on. This is possible because ZeroBrane Studio debugger (MobDebug) is using debugging facilities provided by Lua and GSL shell transforms this syntax into structures that LuaJIT can correctly report on.

Another things is that if you run this example with and without the debugger, you will notice a significant difference in performance: on my windows laptop it is executed in about 3s with the debugger, but in 20ms without it. As I described earlier, MobDebug provides a mechanism to turn debugging on and off in your script. For example, if you add require('mobdebug').off() after require('mobdebug').start(), then the script will execute in 20ms instead of 3s, but all the debugging functionality will be turned off (you wont be able to step through the code and breakpoints will not fire). You can add require('mobdebug').on() line to your script and all commands executed after this on() call is executed will be again available for debugging. This gives you a flexible mechanism to specify what fragments of your code need to run with debugging on and what fragments need to run at full speed.

This GSL shell integration is available in ZeroBrane Studio v0.34; you can also get the latest code from GitHub to give it a try.

Live coding with Moai

Several people asked me during the last few days why Moai live coding is not supported by ZeroBrane Studio and I decided to take another look at why it has not been working as expected. After couple of hours of poking around I realized that the damage was self-inflicted: one of the options I added specifically for Moai (as requested by first beta users) was interfering with scratchpad logic. After resolving the conflict, live coding was back to live.

Just a bit of a background for those interested. Live coding works by continuously re-evaluating the code being edited in the running process. In order to do that, it needs to:

  1. abort or suspend the running process;
  2. re-evaluate the new code fragment in the context of the (suspended or aborted) process.

If your initial setup and the code you want to modify are in the same file, you may want to hide your setup code behind a check to avoid running it on subsequent evaluations (as I have done with if not initialized check). Here is the code I've used:

if not initialized then
  MOAISim.openWindow ( "test", 320, 480 )
  local viewport = MOAIViewport.new ()
  viewport:setSize ( 320, 480 )
  viewport:setScale ( 320, 480 )
  
  local gfxQuad = MOAIGfxQuad2D.new ()
  gfxQuad:setTexture ( "moai.png" )
  gfxQuad:setRect ( -64, -64, 64, 64 )

  prop = MOAIProp2D.new ()
  prop:setDeck ( gfxQuad )
  prop:setLoc ( 0, 80 )
  
  local font = MOAIFont.new ()
  font:loadFromTTF ( "arialbd.ttf",
    " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.?!",
    12, 163)

  textbox = textbox or MOAITextBox.new ()
  textbox:setFont ( font )
  textbox:setRect ( -160, -80, 160, 80 )
  textbox:setYFlip ( true )
  textbox:setAlignment ( MOAITextBox.CENTER_JUSTIFY )
  textbox:spool ()

  local layer = MOAILayer2D.new ()
  layer:setViewport ( viewport )
  layer:insertProp ( prop )
  layer:insertProp ( textbox )
  MOAISim.pushRenderPass ( layer )

  local thread = MOAIThread.new ()
  thread:run(function ()
      while true do
        update()
        coroutine.yield()
      end
    end)
  initialized = true
end

function update()
  textbox:setString("Moai live!")
  textbox:setLoc ( 0, -100 )
  prop:setLoc(0, 60)
end

You can copy this code as main.lua in one of your Moai projects (and use moai.png and arialbd.ttf from samples/hello-moai/ project) and go to Project | Run as Scratchpad in ZeroBrane Studio. This will run your project in Moai; if you are new to this process, you may want to check my earlier post on configuring and debugging Moai projects.

When your script is running you can make changes in the update() method: for example, you can update the string in the setString call and should see the new value in the Moai window. You can also update numbers (manually or using sliders) and see the objects repositioned on the screen.

To use this functionality you need to get the most recent code from Github (or wait for ZeroBrane Studio v0.34).

Zenburn is a low contrast color scheme that was originally created for Vim and then applied to many popular editors and environments. According to the author "it's easy for your eyes and designed to keep you in the zone for long programming sessions."

Tomorrow theme is a bright color theme that aids your programming "with easily identifiable colours that add meaning and enhance legibility" with several theme variations (Tomorrow, TomorrowNight, TomorrowNightBright, TomorrowNightBlue, and TomorrowNightEighties).

ZeroBrane Studio always allowed for configuring colors used in the IDE, but it was not consistently applied to some of the areas in the Output/Console windows and some elements were not available for styling at all (like markers and their background). Now you can switch between color schemes (using cfg/scheme-picker.lua script) and see the immediate effect of your changes; you still need to update the cfg/user.lua configuration file after you settle on a particular scheme.

Here is the screenshot of an editor tab with Zenburn color scheme applied:

The number of colors used is set to 12 to provide some consistency across different color schemes; you can extend them to get more variety if you want. The current version of ZeroBrane Studio (get the most recent one from Github until v0.34 is out) supports Zenburn (thanks to Srdjan Marković for mapping Zenburn colors to the ZBS format) and six Tomorrow theme variations in addition to the default color scheme. Thanks to Christoph Kubisch for putting the original styling mechanism in place.

The version under development of ZeroBrane Studio now supports translations of its UI to multiple languages. French and Russian translations are already included (thanks to the contributions of Roland Yonaba and toiffel!) and can be enabled by adding language = "fr" or language = "ru" to cfg/user.lua configuration file. Those who want to provide translations to other languages can follow these instructions. Grab the code from GitHub.

Wireshark is a cross-platform network analyzer that conveniently supports scripting some of its functions in Lua. One of ZeroBrane Studio users asked if he could use ZBS to debug Wireshark scripts and I thought I would take a look. It turned out it is indeed possible; I'll describe how this can be done on Windows, but you can map these steps to your platform of choice.

Enable Lua support in Wireshark

Make sure your Wireshark version include Lua interpreter and enable processing of Lua scripts. Go to Help | About Wireshark and check if you see "with Lua 5.1" there (or run tshark -v and check its output). Then find init.lua in the wireshark folder and comment out the following line (this is only needed if you are using wireshark earlier than 1.4):

-- Lua is disabled by default, comment out the following line to enable Lua support.
--disable_lua = true; do return end;

Setup Wireshark environment for debugging

Create the following batch file in your wireshark folder; adjust the value of ZBS according to the location of ZeroBrane Studio.

set ZBS=D:\users\paul\ZeroBraneStudio
set LUA_PATH=.\?.lua;%ZBS%\lualibs/?/?.lua;%ZBS%\lualibs/?.lua
set LUA_CPATH=%ZBS%\bin/?.dll;%ZBS%\bin/clibs/?.dll
tshark -X lua_script:test.lua

This script points to libraries included with ZBS that are required for debugging (luasocket and mobdebug). tshark is the command-line version of wireshark and -X enables various extension options.

Continue reading Debugging Wireshark Lua scripts

The tragedy of the commons is "the depletion of a shared resource by individuals, acting independently and rationally according to each one's self-interest, despite their understanding that depleting the common resource is contrary to their long-term best interests." (from Wikipedia). The tragedy exists because of the asymmetry between costs and benefits to individuals using a shared resource: the advantage goes directly to the individual, while disadvantage is shared among all users of the resource. One popular example of the tragedy is a group of herders sharing a common parcel of land with each herder benefiting from putting a new cow it acquires on to the land (thus gaining direct advantage), even if the quality of the land is damaged as the result (with the disadvantage being equally shared by all participants).

What does it have to do with open-source projects? I have been recently running a small experiment to see how many people may be willing/interested to pay what they want for an open-source project (a Lua IDE; the payment/support page is here). This is similar to directly benefiting from using a shared resource, with the provider of the resource bearing the main cost. Adding more and more users increases this cost (which manifests itself in more opened issues, handling more corner cases, testing on multiple platforms, questions to answer, requests for documentation and new features, and so on), with each user directly benefiting from everything that goes into the resource. If the cost is not shared by the users (by contributing patches and documentation, answering user questions, and providing financial support), over-exploitation of the resource is inevitable until the resource is no longer able to support itself and is gone.

One obvious response to that is that it's not a problem for an open-source project; if the current author/team is not interested or is not able to continue with the project there will be someone else to continue working on it if the project is useful to other people. While this is true (and indeed something similar happened to another open-source project I worked on), this doesn't create a sustainable model for the current provider of the resource.

Continue reading Tragedy of the Commons and open source projects

Yesterday I enabled pay-what-you-want payments for ZeroBrane Studio (an open source Lua IDE) and went to bed. Today I found several payment confirmations (thank you to all who paid!) in my inbox and an email from Amazon (I'm using Amazon Simple Pay) saying that they disabled my account as they "do not support 'Pay what you want' business models" and "support business models selling services or products for a fixed dollar amount". I find this surprising as, while I couldn't find a definitive statement on this in Amazon's Use Policy, there are several popular sites that clearly follow "pay what you want" model and happily accept Amazon Payments (Humble Bundle and Indie Game Stand come to mind; Kickstarter can also be classified as using "pay what you want").

Amazon requires me to "remove the information related to 'donations' from your website", which I don't have anywhere on the support page or the project site. In fact, the site only accepts seven amounts and doesn't allow to enter an arbitrary amount, which (I thought) better matches "selling services or products for a fixed dollar amount".

Note that this is a business account registered for an LLC and not a personal account. I also find it puzzling, how selling a book I own for any amount I want through Amazon is different from selling a software product for any amount people want to pay. Here is Amazon's full email:

Continue reading Amazon Payments doesn't support "pay-what-you-want" models

Andy Bower did an amazing thing. He took Gideros SDK, ZeroBrane Studio, and inspiration from Bret Victor's Inventing on principle talk and created a wonderful live coding demo running on a real device. Some of you might have seen my short demonstrations of live coding in Lua and Löve2d using ZeroBrane Studio, but Andy went way beyond what was shown previously.

See it for yourself (you may need to switch the video to 720p/HD to see the code being typed):

What's remarkable about it is that Andy goes in front of your eyes from a white background to a simple yet funny application running on a real device in less than 25 minutes. Even more remarkably, all the tools (including his code) are available to you to play with. Integration with Gideros in ZeroBrane Studio that adds debugging and auto-complete support will be included in the next version, but you can still access it today from GitHub is available starting from version 0.33.

Gideros is a flexible framework for developing mobile applications for iOS and Android platforms. It is using Lua as its scripting language and after several people on Gideros forums expressed their interest in using ZeroBrane Studio IDE, I thought I would take a look at supporting Gideros in the IDE.

ZeroBrane Studio supports two ways to debug applications. One way is to launch the application from the IDE, which allows for tighter integration as the IDE can set the environment for the process and can kill the process when the user aborts debugging or running the application. Another way is to start the application externally and make it connect to the debugger in the IDE, thus allowing the IDE to control the application. This second way was my first recommendation and it took couple of hours to implement support for debugging in the IDE.

The video below demonstrates debugging support for Gideros scripts in ZeroBrane Studio (you may need to switch the video to 720p to make the text more readable):

To enable the integration shown in the demo, you need to do these three steps:

Continue reading Gideros debugging with ZeroBrane Studio

ZeroBrane Studio has been downloaded 500 times during the last 30 days after the previous release on September 3rd. While this may not sound like much, it's still more than the number of downloads for the preceding three months. The number of downloads per day was about 10 at the beginning of last month and is more than 20 for the last few days. This does not include repository clones and snapshot/tag downloads.

I take that as a sign that users like the product.

Twelve years ago, in September of 2000 I released the first public version of SOAP::Lite, a webservices (SOAP and XML-RPC) toolkit for Perl. I could not have imagined at the time that the module would have taken off as it has, being covered in a large number of books, and still being in use twelve years later. It's been a team effort along the way, and I'd like to thank the current maintainer of the module, Martin Kutter, who has been supporting and developing the module after the previous maintainer and lead developer, Byrne Reese, who supported the module from 2002 through 2007, found his passion in blogging and got tired fixing my bugs. As Byrne wrote in one of his posts:

The source code is notoriously complex, a mark of the seriously ingenious Paul Kulchenko who created SOAP:Lite. As a result [it] baffles most inexperienced Perl programmers, and indeed sends many of them running in shear terror. I myself am given the highest respect in my office for signing up to maintain the module for this fact alone - I work with some of the brightest and most experienced Perl programmers in the industry and they all look at SOAP::Lite in awe. And not the "good" kind of awe, the kind of awe that gives people a healthy, but fearful respect.

I wonder which of my current projects will still be in use 12 years later...

(This post is by Daniil Kulchenko who helped with many aspects of the ZeroBrane Studio project.)

Up until recently, ZeroBrane Studio (ZBS in the text that follows) was only available on Windows. But being a Lua and wxWidgets-based app has its benefits -- the code is inherently cross-platform, so distributing on other platforms ought to be only be a matter of figuring out the app packaging systems of each. This turned out to be quite the challenge, so I'll go over the roadbumps we hit along the way with each platform: first OS X, then Ubuntu/Debian. This is the first of a two-part post; this post will cover how we went from a set of Lua files to a complete, distributable .dmg for OS X users.

What constitutes an OS X ".app"

The main hurdle was figuring out how to package the libraries that ZBS depends along with the app, namely wxLua, wxWidgets, and Lua itself. OS X generally uses a system of "frameworks" to do so; for example, if you have Adium installed, navigate to /Applications/Adium.app/Contents/Frameworks to see a list of ~21 frameworks, which are collections of libraries and other resources needed to run Adium itself. But in the interest of keeping the code tree looking as similar as possible among platforms, we decided to instead keep the wx and wxLua .dylib (library) files in the 'bin' directory of ZBS, much like how the .dlls are kept on the Windows version of ZBS.

Continue reading Packaging ZeroBrane Studio as OSX app

Moai is an open-source 2D game engine for mobile development created by Zipline Games. The engine runs on various platforms (iOS, Android, Windows, Mac, and Linux) and is scripted in Lua, which makes it a natural fit to support in ZeroBrane Studio. The just released version of ZeroBrane Studio (v0.32) provides integration with Moai and implements debugging support for Moai scripts; the video below demonstrates these capabilities (you may need to switch the video to 720p to make the text more readable):

To enable the integration shown in the demo, you need to select Moai as an interpreter in ZeroBrane Studio by going to Program | Lua Interpreters | Moai. If your moai host executable is in one of the folders listed in PATH or is placed in MOAI_BIN folder, it will be found and used by the IDE. If the executable is in a different location, you may need to specify this location in cfg/user.lua file by adding path.moai = 'd:/lua/moai/moai.exe' (see cfg/user-sample.lua for details on how this is done). Make sure you include the name of the executable: if you specify a folder you are likely you get an "Access denied" error.

After this is done, you can use Project | Run command to run the application and Project | Start Debugging to debug your application. If there is a problem with finding the Moai executable, you will see an error message in the Output window.

Continue reading Moai debugging with ZeroBrane Studio

My earlier screencasts have shown live coding with simple Lua scripts and debugging of Löve scripts; the video below demonstrates live coding with Löve scripts using ZeroBrane Studio (you may need to switch the video to 720p to make the text more readable):

For those visiting for the first time, Löve is a simple and powerful framework for developing 2D games in Lua, and ZeroBrane Studio is a lightweight Lua IDE that provides code completion, syntax highlighting, live coding, remote debugger, code analyzer, and much more.

You may notice in the screencast that the paddle is moving quite slowly; you can run this without the debugger and the speed is likely to be about ten times faster. This may be okay for some situations, but in many cases when the game is complex, things can get very slow. How can you speed it up?

The debugger provides two methods that allow you to temporarily turn the debugging on and off. If you turn it on/off right around where the changes need to be applied, you can get almost the same performance you see without the debugger.

function love.update()
  require("mobdebug").on() --<-- turn the debugger on
  local angle = 45
  local speed = 75
  require("mobdebug").off() --<-- turn the debugger off
  points = calcTrajectoryPoints(speed, angle, 0.4)
  position = (position or 0) + 2
  if position > width-25 then position = 0 end
end

The code used in the screencast is available here. This is an experimental feature and may not work for some types of variables; for example, those local variables that are initialized outside of your draw and update methods (upvalues) may not be handled correctly. Right now your best bet is to store those variables you want to preserve as global variables.

Recent Comments

About

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.

Recommended

Close