How To Write A Plugin

Debugging

Introduction

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.

Using the Debugging Tools in the Editor

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 Step Into button on the toolbar.The first time you press the Step Into 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 Step Into 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 Step Into button several times to move around the loop. Finally select Stop Debugging from the Debug menu, to stop the debugger and the script.

Breakpoints

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 Go 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.

Step Into
Executes the selected line, moving down into any script function called.
Step Over
Executes the selected line, but does not debug any functions called within the line.
Step Out
Only available when inside a script function.  Executes the rest of the current function and then breaks after the function returns.

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 (and A Brief Introduction to functions)

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.