So far we have only used the Plugin Editor as a simple text editor, to allow you to type in your scripts. But there is much more to it than that. As well as being an editor, it is also a debugger. 'Debugging' is the process of locating and correcting errors in your script. And the Plugin Editor has various tools and capabilities to help with this process. One of these tools is the Variable Pane - pane in the bottom-right corner of the editor window - which can be used to show the values of variables in your script, even while you are running the script.
A common problem when developing any sort of script is that it often
does what you told it to do, but not necessarily what you wanted
it to do. This is where debugging comes in. The debugger
allows you to step through the code a line at a time and check that
processing proceeds as you wanted and expected it to do. You can
also check the values of variables as you go, in the Variable
Pane.
For example, the code below will never end.
i = 1 while i < 10 do print(i) end
It's easy to see why this will never end. The problem in this case is that the value of i never changes inside the loop. So the code will continue to loop forever. But with more complex scripts, sometimes 'stepping' through the script, one line at a time, may be the only way to find the problem.
To see how the debugger works, enter the code shown above and press the button on the toolbar.The first time you press the button, nothing actually happens except that a small yellow arrow appears in the margin, to the left of the first line of code. The arrow indicates the line of code that is about to be executed. Press the button again. When you do so, the first line of code is executed, and the arrow is moved to the next line of code. At this point, you should see 'i' appear in the Variable Pane with a value of 1. Press the button several times to move around the loop. Finally select Stop Debugging from the Debug menu, to stop the debugger and the script.
As plugins get longer it becomes impractical to step through every line. For this reason the Plugin Editor allows breakpoints to be set in the script. Using the example, above click in the margin to the left of the line "print (i)", to set a breakpoint. A small red disc will appear in the margin. Press the button to run the script. When the script reaches the breakpoint line it will stop and the values will be displayed in the Variable Pane. If you wish, you can now revert to stepping through the script as before.
There are two additional Step commands: Step Over and Step Out. Both of these are used when your script includes script functions of its own. To illustrate their use, enter the code below into the editor (replacing the previous code if you entered that):
function addone(ii) ii = ii + 1 return ii end i = 1 while i < 10 do print(i) i = addone(i) end
The three different Step buttons operate as follows.
Experiment with the script you entered above using the three step buttons to move through the script. Notice when you stop within the addone function, both 'i' and 'ii' are listed in the Variable Pane. But 'ii' disappears when the script exits the function. This is because the 'ii' variable is local to the addone function and ceases to exist when the function exits.
Hint: When running scripts for the first time, especially ones with loops, it's a good idea to add a variety of breakpoints (by clicking in the margin) just in case any of the loop logic is incorrect. Once you are confident that the loop logic is correct you can remove the breakpoints. To remove a breakpoint, simply click on its red disc breakpoint icon.
The Variable Pane is used when you are debugging – and more
specifically, when you are stepping through the code, or at a
breakpoint. At the top of the Variable Pane is a dropdown list called
‘Call Stack’. To understand the purpose of this list, you must first
appreciate that with Lua scripts, not only can you call pre-defined
functions, such as Lua functions or Family Historian API functions -
you can also define and call your own functions. Writing functions in
Lua is not complicated (see the Lua Quick Guide for a very brief
introduction, or see the Lua Online Reference Manual for more
information). When you first start executing a Lua script you are not
initially ‘within’ a function. Let us suppose that your script defines
two functions, called (say) ‘start’ and ‘process’. Let us now suppose
that the first thing your script does, after defining these two
functions, is to call the ‘start’ function. And let us suppose that
‘start’ calls ‘process’. If you set a breakpoint within ‘process’, the
Call Stack dropdown list will contain 3 items (in order): ‘main’,
‘start’, and ‘process’. The last of these, ‘process’, will be the
currently selected value. What this tells you is that, at the current
breakpoint, you are now in a function called ‘process’, which was
called by a function called ‘start’ which was called from outside any
other function. Lua refers to the ‘topmost’ part of a script
which is not within a function as ‘main’.
This ‘stack’ of functions, with one calling another, is the ‘call stack’. There is no limit to the number of functions which can be stacked up in this way .
To view the variables that are accessible within each function,
select the function you want, or ‘main’, in the 'Call Stack' list. The
list of variables (below 'Call Stack') is updated appropriately. The
variable list has 4 columns. The first column, ‘Variable’, displays
the name of the variable. The ‘Object’ column is only used when a
variable contains a Family Historian object, in which case it shows
the type of object. The ‘Scope’ column indicates whether the variable
is ‘Local’ or ‘Global’. Notice that you can always see global
variables whatever function you pick in the call stack. Local
variables, however, are local to the chosen function. Lua variables
are global by default, but it is a good idea to use local variables as
much as possible as this will ensure that your functions cannot be
affected by anything that happens elsewhere in the script, and are
therefore much more resilient and less prone to error.
The final column shows the value of the variable. If the variable stores a table (see the Lua reference manual to learn more about tables which fulfil a very important role in Lua), the value will be given simply as the word ‘table’ in brackets. As well as the word table, you should see either a dot followed by a number (e.g. “(table .3)”), or a hash followed by a number (e.g. “(table #4)”, or both (e.g. “table #6, .7”). A number preceded by a dot gives the number of elements in the table (e.g. ‘.3’). In Lua tables can be used as arrays. If a given table is being used as an array (as long as it is what Lua calls a 'regular' array) the number of array elements is given as a number preceded by the hash character (e.g. ‘#4’). Where a table is shown with both a dot value and a hash value, this means that the table has both array elements and non-array elements. The hash value gives the number of array elements, whereas the dot value gives the total number of elements.
To view the contents of a table, double-click on its row in the list of variables, or select it and click ‘Inspect Variable’ on the Debug menu. You can inspect any variable, but it is particularly useful for tables.
By default, the Plugin Editor will hide some types of global
variables. You can override this however by clicking on Options
on the Debug menu, and choosing which variables you want to hide.