LuaFy – a free Lua scripting plug-in for FileMaker Pro®

Integrating LuaFy with FileMaker

Passing Different FileMaker Field Types as Arguments
Returning Calculated Values to FileMaker
Lua Maintains Its State Across External Function Calls
Unicode and Multi-byte Languages
Line Ending Convention
Handling Quotes and Carriage Returns When Passing FileMaker Strings
 
Download and Feature List
Purchase a License to LuaFy Plus
Functions Provided by LuaFy
Lua Libraries Provided by LuaFy
Lua Integration with FileMaker
Usage Examples
What is Lua?
Origin Story
Version History & Old Versions

Passing Different FileMaker Field Types as Arguments

Arguments to LuaFy_RunScript()/RunFile()/CallFunction()/ResumeFunction() can be any FileMaker type except Container. The argument will be converted automatically to a Lua string, Lua number, or a luafy.timestamp as appropriate. If you pass a Container value, it will get to Lua as a 'nil' value. The result of a FileMaker boolean expression becomes a Lua number (0 or 1).

In LuaFy_RunScript() and LuaFy_RunFile() you access the FileMaker values passed as arguments using Lua's "vararg" construct (...). That means you can simply write in Lua
arg1, arg2, arg3 = ... to have the first three values passed as FileMaker function arguments be assigned to the (global) variables arg1, arg2, and arg3. If you only pass one argument, arg2 and arg3 will be assigned nil. If you pass more than three arguments, only the first three will be assigned to arg1, arg2, and arg3, and the arguments after the third will be ignored. Use
local arg1, arg2, arg3 = ...
if you want those variables to be local to that Lua script and not be globally defined across multiple Lua script invocations in FileMaker Pro.

As you would expect, LuaFy_CallFunction() and LuaFy_ResumeFunction() will automatically populate the arguments of the function you call with the values you pass in the FileMaker function.

Returning Calculated Values to FileMaker

The result of running LuaFy_RunScript(), LuaFy_RunFile(), LuaFy_CallFunction(), or LuaFy_ResumeFunction() is returned to FileMaker using the Lua "return" keyword. Only one value is returned. It must be a Lua string, a Lua number, or a luafy.timestamp. All other Lua value types are discarded. The Lua return keyword can return a list of values, but only the first value in the list is returned to FileMaker.

A Lua string becomes a FileMaker Text value. Lua number comes back as a FileMaker Number. A luafy.timestamp value becomes a FileMaker Timestamp.

If you need to return multiple values to FileMaker from your Lua script, you can either package them together in a delimited string (e.g. a FileMaker list) or leave them in Lua variables or a Lua table for you to access later, e.g. LuaFy_RunScript("return x[2]").

Since Lua's stdout is not defined in the context of LuaFy, print() and io.write() will not output anything since they use stdout.

Instead of sending the outut to stdout as you go, you can accumulate the lines of ouput in a string variable (e.g. ret = ret .. 'another line\r') and send it back to FileMaker with "return" (e.g. return ret). You can do something similar and possibly with better performance by accumulating the values into a table, e.g. table.insert(retTab, 'Another line of text.') then return the table as text, e.g. return table.concat(retTab, '\r') or use the utility function luafy.tolist(retTab).

Instead of using printf() to format and output a string directly you can use string.format() to format the string and then return the value with "return".

Lua Maintains Its State Across External Function Calls

When the LuaFy plug-in is initialized at startup, a Lua environment state is created. This state is preserved throughout the lifetime of the session and only cleared when FileMaker is exited. This means that functions, global variables, and global tables are all preserved and can be referenced and reused for the duration of the FileMaker session.

If you want variables or tables to be available only temporarily and within the scope of the single call to the LuaFy external function, use the "local" keyword in front of the Lua variable or table.

Unicode and Multi-byte Languages

Lua was not designed to handle unicode. Its string library makes certain assumptions about the text being like ASCII with each letter being represented by a single-byte. LuaFy converts all of the strings passed from FileMaker into UTF-8 which is optimized for backward compatibility with ASCII while still being able to store all of the characters that FileMaker sends. This works out to be a pretty good compromise since UTF-8 was designed to break as few things as possible for legacy programs.

Lua has no problems storing strings with multiple bytes per character (UTF-8 can use up to 4 bytes per character). If you are careful then you should be able to handle any text string that FileMaker provides. Your strings can go round trip from FileMaker to Lua and back without losing any information. The only losses that could occur would be from your manipulation of the strings within Lua. As long as you are careful when handling strings that can't be represented by ASCII, you should be fine.

Line Ending Convention

In FileMaker the preferred line ending character ¶ is a carriage return (ASCII code 13). This is represented by \r in Lua. Thus a two line string would be written as "This is the first line.\rThe second line is here." instead of using \n (line feed, ASCII 10) as the line ending character. FileMaker follows the same convention on both Macintosh and Windows. The only difference in behavior is that \n will appear to work fine on Mac for string values returned from Lua wheras on Windows the \n will display as little boxes.

If you are generating the Lua string to be written to a file in Lua (e.g. using the io library), you should use \n instead so that the correct EOL will be automatically generated appropriate to the platform (\n for Mac, \r\n for Windows) when writing to the file. You may need to substitute the \r in the FileMaker-generated string with \n before writing the string to a file (e.g. myString:gsub('\r', '\n') ).

Handling Quotes and Carriage Returns When Passing FileMaker Strings

The easiest way to pass a long script from FileMaker into LuaFy_RunScript() is to store it in a FileMaker field, e.g. myTable::myScript and pass that field directly, e.g. LuaFy_RunScript(myTable::myScript). If you want to generate the script text via a calculation, there are a variety of options.

Lua treats double and single quotes separately but equally. You may use either to wrap your strings. If you use single quotes for your strings in Lua, e.g. x='Hello', you can avoid having to escape the double quotes when quoting the string in FileMaker.

Using ¶ Directly

Concatenate a long list of strings with ¶.

"-- Simple script to generate Hello World!" & "¶" &
"local x='Hello'" & "¶" &
"local y='World'" & "¶" &
"return x .. ' ' .. y"

Use List

Concatenate a long list of strings with List.

List(
"-- Simple script to generate Hello World!";
"local x='Hello'";
"local y='World'";
"return x .. ' ' .. y"
)

Quote Spanning Many Lines

Lua does not require you to have one statement per line so you can use a single set of double quotes for the entire Lua script. Even though it looks like multiple lines, FileMaker converts the quoted line breaks in the calc into spaces (ASCII 32). Despite appearances the entire quoted text comes out as one line.

Let(
[luaScriptText = "
local x='Hello'
local y='World'
return x .. ' ' .. y
"];
LuaFy_RunScript(luaScriptText)
)

Including short comments (--) in the script will require you to divide your script into multiple lines since the comment extends to the end of the line. Since Lua allows you to use semicolons between statements, this provides an opportunity for a workaround that lets you use a multi-line FileMaker quotation and short comments in your Lua script as long as you don't use semicolons anywhere else in your script. Simply replace the semicolons with ¶.

Let(
[luaScriptText = Substitute("
-- Simple script to generate Hello World!;
local x='Hello';
local y='World';
return x .. ' ' .. y
"; ";"; "¶")];
LuaFy_RunScript(luaScriptText)
)

A simpler choice may be to use Lua's long comments (--[[ ... ]]) instead of Lua's short comments.

Let(
[luaScriptText = "
--[[ Simple script to generate Hello World! ]]
local x='Hello'
local y='World'
return x .. ' ' .. y
"];
LuaFy_RunScript(luaScriptText)
)


LuaFy is a product of Cosmic Consulting
Tom Hays <trhays@luafy.com>