RGP Lua is compatible with any external text editor or IDE. The only requirement is that the script you are developing has to have been configured in the RGP Lua Configuration Window and be visible in Finale’s plugin menu. This can be done before you have actually added any code to the script.
One of the effects of the “Enable Debugging” option in RGP Lua is to pre-embed the luasocket
library in the Lua machine before calling the script. Many of the solutions for debugging embedded Lua over the years have used this library for communicating between the host program and the IDE.
Two common development environments for Lua are Visual Studio Code and ZeroBrane Studio. Both have their advantages and drawbacks, and both were useful in the development of RGP Lua. Each has extensive documentation pages that need not be replicated here. Instructions for setting up a development environment in each application appear below.
The debugging solution presented here uses the script mobdebug.lua
within ZeroBrane Studio.
Download and install ZeroBrane Studio from the website. The installation includes a version of mobdebug.lua
, but it may be out of date and incompatible with the version of luasocket
embedded in RGP Lua. Instead, download the latest version of mobdebug.lua
from its github repository.
To debug a script:
mobdebug.lua
to the script directory. (RGP Lua ignores it.)require('mobdebug').start()
Project->Start Debugger Server
.require
.Any changes you make to the script in the IDE editor are recognized by RGP Lua the next time you execute the script from Finale. This allows for fast iteration of the test, debug, and correct cycle. However, be aware that ZeroBrane Studio does not permit editing of a script while it is being debugged. (See below for more information.)
The IDE for ZeroBrane Studio offers many customization options. You set them on a per-user basis by selecting Edit->Preferences->Settings: User
.
To capture print()
output from the remote script:
debugger.redirect = "c" -- "c" copies the output to ZeroBrane; "r" redirects it
To change your tab width to 4 instead of the default 2:
editor.tabwidth = 4 -- the default is 2. If you like 2, you don't need this line.
ZeroBrane Studio does not permit editing a script while a Debugger session is in progress. This becomes particularly an issue if you are using the finenv.RetainLuaState=true
option. For these scripts, once the Debugger session starts, it is not possible to edit the file until Finale exits unless you build in a way for the script to set finenv.RetainLuaState=false
before it exits.
One effective way to do this is to detect modifier keys. If your script has a dialog box, you might use
dialog:QueryLastCommandModifierKeys(finale.CMDMODKEY_SHIFT)
to detect the shift key as you close the window and request a new Lua state there. If your script has no dialog box, you could use
finenv.QueryInvokedModifierKeys(finale.CMDMODKEY_SHIFT)
to detect the shift key and request a new Lua state when the script is invoked. In either case, exiting the script with finenv.RetainLuaState=false
ends the Debugger session in ZeroBrane Studio. You can then edit your script file.
There are several different VS Code extensions for Lua debugging, each with different pros and cons. Here is one setup that gives satisfactory results.
Install the extensions Lua (language server) and Lua MobDebug adapter.
For a development folder, it can be convenient to fork and clone the Finale Lua repo and put any new scripts in the src
folder. This lets you include existing things from the library
and mixin
folders. You can also set up a development folder somewhere else, if you prefer.
Open your development folder in VS Code.
Add the following lines to your lua script:
local home = os.getenv("HOME") or os.getenv("HOMEDRIVE") .. os.getenv("HOMEPATH")
package.path = home .. "/.vscode/extensions/alexeymelnichuk.lua-mobdebug-0.0.5/lua/?.lua"
.. ";" .. package.path
require("vscode-mobdebug").start('127.0.0.1', 8172)
Type Ctrl+Shift+D or click on the “Run and Debug” icon in the side bar to bring up the “Run and Debug” panel. The process for adding the Lua MobDebug launch configurations to your launch.json
file depends on whether or not you already have a launch.json
in your workspace.
launch.json
file yet, you’ll see a link to “create a launch.json file”; click it. If you have a Lua file open in the editor, VS Code will automatically create the appropriate launch.json
file for you. Otherwise, from the dropdown that appears, select Lua MobDebug
. Your launch.json
should include these elements as part of the configurations
array:{
"name": "Lua MobDebug: Listen",
"type": "luaMobDebug",
"request": "attach",
"workingDirectory": "${workspaceFolder}",
"sourceBasePath": "${workspaceFolder}",
"listenPublicly": false,
"listenPort": 8172,
"stopOnEntry": true,
"sourceEncoding": "UTF-8"
},
{
"name": "Lua MobDebug: Current File",
"type": "luaMobDebug",
"request": "launch",
"workingDirectory": "${workspaceFolder}",
"sourceBasePath": "${workspaceFolder}",
"listenPort": 8172,
"stopOnEntry": true,
"sourceEncoding": "UTF-8",
"interpreter": "lua",
"arguments": [
"${relativeFile}"
]
}
launch.json
, click on the gear icon at the top of the “Run and Debug” panel to bring it up. You can then either click the “Add Configuration” button in the lower left and select the two Lua MobDebug
items one after the other, or add the above elements to the configurations
array directly.Launch the Lua MobDebug: Listen
configuration by selecting it from the dropdown at the top of the “Run and Debug” panel and clicking the arrow next to it (or hitting F5). This tells VS Code to listen for messages from remote execution of your script.
Run your script from Finale. Any breakpoints you have set in VS Code will be hit, and then you can use VS Code’s debugging capabilities. Note that the line "stopOnEntry": true
in the launch configuration will cause the debugger to stop at the top of your script even if you have no breakpoints set. If you don’t like this behavior, you can change the value to false
.
The extension collects any print
statements and outputs them all at the end of the script. In order to work around this and print values while your script is running, you’ll need to define a local function:
local print = function(...) print(...); io.flush() end
When the script exits, your debug session will end; you’ll need to launch a new session from VS Code before invoking the script from Finale again.