Lua

Lua Quick Guide

This quick guide is aimed primarily at people who have developed plugins, programs or macros previously using other macro, script or programming languages. Newcomers to plugins should first see How to Write Plugins.

Some Basics...

Keywords

and       break   do     else    elseif    end   false   for
function  if      in     local   nil       not   or    repeat
return    then    true   until   while

Note: keywords are case sensitive so you can define a variable called For and it will not be treated as a keyword.

Comments

Comments starts with a double hyphen (--) anywhere outside a string.  If the text immediately after a double hyphen (--) is not two opening square brackets ([[), the comment is a short comment, which runs until the end of the line. Otherwise, it is a long comment, which runs until the corresponding closing pair of square brackets (]]). Long comments are frequently used to disable code temporarily.

Example:

fhMessageBox("Hello Family Historian !") -- this is a line with a comment at the end

Variables

There are three kinds of variables in Lua: global variables, local variables, and table fields.

Strings

Structures

Lua supports a range of control structures including

if then else
if bCondition then
  -- condition true
else
  -- condition
end      
if bCondition then
  -- condition true
elseif bCondition2
  -- condition false and condition 2 true
end  
for
for i=1,10 do
  -- loops 10 times
end 
while
i = 1
while i < 10 do
  -- loops 10 times
  i = i + 1
end 
repeat
i = 10
repeat
  print(i)
  i = i-1
until i==0

Tables

  • tables are declared using curly brackets (e.g. tblSurnames = {})
  • they can contain values of all types, including other tables
  • To iterate over the elements contained in a table, the operators ipairs() or pairs() can be used:
ipairs() iterates only over the indices in a table (only outputs the numerically indexed content)
pairs() iterates over the keys in a table
for i,strdata in ipairs(tbldata) do
   print(i,strdata)
end

Tables as arrays

Tables can be used to hold arrays of information. Table constructors can contain a comma separated list of objects to create an array. The array elements can be accessed using square brackets, table[index].
t = { 1,1,2,3,5,8,13 }
  print( t[1] )        -- returns:  1
  print( t[0] )        -- returns:  nil
  print( t[4] )        -- returns:  3
Notice that the indexing into the array starts at 1, not at zero. t[0] has the value nil , i.e. there is no element at position 0.

Tables as dictionaries

Tables can also be used to store information which is not indexed numerically, or sequentially, as arrays are.
In this dictionary usage, each element pair has a key and a value.  The key is used to identify the element (either for setting the value or for retrieving it).
A key need not be a number.  It can be a string - or a value of any other Lua variable type (but not nil).
t = { apple="green", orange="orange", banana="yellow" }
  for k,v in pairs(t) do print(k,v) end
returns:  apple   green
          orange  orange
          banana  yellow

Note: that there's no guarantee as to the order in which keys will be stored in a table when using dictionaries so the order of retrieval of keys using pairs() is not defined.

A single tables can be used as both an array and as a dictionary.  You are not restricted to using table constructors as just sequentially indexed lists, or as dictionaries.  You can mix the two together.

More information and table examples can be found here: lua-users.org/wiki/Tablestutorial

functions

functions are defined using the following syntax:

           function functionname(parameters)
               -- function action
               return variable
           end
      

Recommended Script header

It is recommended, although not essential, to include a comment header in your scripts in the format illustrated by this example:

--[[
@title: test script
@author: Fred Blogs
@lastupdated: June 2010
@description: 
This is a Test Script which provides an example header layout.
It displays a message box saying "Hello World"
]]
 
fhMessageBox("Hello Family Historian !") -- this is a line with a comment at the end

If you add a header such as the one above, the Plugin List window will display the information in it, when you select the script - making it much easier to identify the required script. To quickly add a script header, select Insert Script Header from the Edit menu.

Modules

Lua makes it easy to create and use modules of functions.  Modules are libraries of functions which are stored in their own plugin script file.  They can be included within any script, using the require statement.

require "module"

Modules are saved and stored in the plugin area, like any other plugin.  Although not essential, it is recommended that all modules should start with the following code:

if ... == nil then error('This is a Module') end
module(..., package.seeall)
--------------------------------

This code will throw an error, stating that the plugin is a module, if the module is run directly (instead of being called from another plugin). The use of modules makes it easy to re-use code.  However, it is a requirement of the Family Historian plugin store that each plugin can be run independently, and has no dependencies - i.e. makes no use of modules.  So if you have a plugin and you wish to submit it for inclusion in the plugin store, all module functions called by the plugin must be moved "inline", prior to submission.

For More Information

Lua links are provided on the Help menu of the Plugin Editor.  See also:  Lua Reference Manual 5.3.