Lua Scripting

Lua is a “powerful, fast, lightweight, embeddable scripting language” and is available for use in Trunk Notes.

How to program in Lua is best left to the Lua website, documentation and available books. Find out more from http://www.lua.org.

The version of Lua in Trunk Notes is 5.1.5.

Using Lua in Trunk Notes

Trunk Notes allows the use of functions for dynamic content on your wiki pages. For example /{{random Quotes}} will pick a line at random from the page Quotes and replace the /{{random Quotes}} with a quote. There are many other such functions - see [[Docs:Functions]] for full details.

The most powerful function available in Trunk Notes is a bridge to the Lua scripting language.

For example, in my wiki I have a page called DayNight.lua. The page has the contents:

hour = tonumber(os.date('%H'))
if hour < 7 or hour > 20 then
    return "{{stylesheet Night.css}}"
else
    return "{{stylesheet Day.css}}"
end

I can call the script from any page by writing /{{lua DayNight.lua}}. The script will run and insert either the text /{{stylesheet Night.css}} or /{{stylesheet Day.css}} depending on the time of day. That text will include a stylesheet - in the day time my page has a white background with black text, at night the colours are reversed.

Passing arguments to a Lua script

You can easily pass arguments to a Lua script. For example I might want to write /{{lua Multiply.lua, 5, 10}} and have the answer 50 appear in a page. Here is the Multiply.lua script:

number1 = args[1]
number2 = args[2]
answer = number1 * number2
return answer

Not a terribly useful script but you can see how the args array contains the arguments passed into the script.

NOTE: It is convention in Lua that arrays start at 1 not 0.

Manipulating the wiki

Already you can see how powerful Lua scripting can be.

Even better is how a Lua script can integrate even further with Trunk Notes.

A number of Trunk Notes functions have been defined in Lua:

  • wiki.get(page_name) - returns a page from the wiki. nil is returned if the page does not exist.
  • wiki.exists(page_name) - returns true if the page exists, otherwise false.
  • wiki.titles() - returns an array containing the names of all the pages in your wiki.
  • wiki.search(search_string) - returns an array containing the names of all pages whose name or contents include the search string.
  • wiki.new(page_name) - returns an empty page with the name page_name. If a page already exists with that name, or the name is invalid nil is returned. The page is not created in the wiki until it is saved.
  • wiki.save(page) - saves a page to the wiki.
  • wiki.tags() - returns a list of all the tags in the wiki.
  • wiki.expr(function_name, arg1, …) - returns a table with the key out containing the output of running the function.
  • wiki.exprl(function_name, arg1, …) - returns an array containing the result of running the function.

A wiki page is a Lua table (a little bit like a dictionary) describing the page. The following attributes are available:

  • title - the name of the wiki page
  • contents - the actual contents of the page
  • created - the date the page was created (as a UNIX timestamp)
  • updated - the date the page was last updated (as a UNIX timestamp)
  • accessed - the date the page was last accessed (as a UNIX timestamp)
  • hits - the number of times the page has been accessed
  • query - the query string from the URL used to access the page internally
  • id - the internal integer ID of the page
  • tags - an array of tags currently assigned to the page
  • metadata - a table (dictionary) of metadata assigned to the page
  • arguments - the list of arguments taken from the query string

The following of the attributes can be modified in the Lua script and saved - title, contents, created, updated, hits, id, tags and metadata. You should be very careful if changing the id of the page - you may accidentally overwrite another page in your wiki.

The current page (that is the page currently being rendered) is stored in the Lua variable page.

Here is an example which creates a new page (if the page MyNewPage already exists the script will fail):

-- Create a new wiki page (if this page already exists the new_page will be nil)
new_page = wiki.new('MyNewPage')
-- Put the date in the contents of the page
new_page.contents = os.date()
-- Tag this as Journal and Lua (tags are created if necessary)
new_page.tags = {'Journal', 'Lua'}
-- Save the page
wiki.save(new_page)
-- Return the page name
return new_page.title

Here is an example which adds the name of the page currently being access to a page called /PageLog:

-- Get the page PageLog. NOTE: If this page doesn't exist the script will fail)
page_log = wiki.get('PageLog')
-- The Lua operator .. concatenates strings
page_log.contents = page_log.contents .. page.title .. "\n"
-- Save the page back into the wiki
wiki.save(page_log)

expr and exprl

expr and exprl are powerful functions which allow you to run any Trunk Notes dynamic function from Lua.

Here is an example using expr:

-- The same as if {{random Tips}} had been added to a page
result = wiki.expr('random', 'Tips')
-- Return the line taken at random from the page Tips
return result.out

exprl is more useful if you want to do something with a list of pages returned from a dynamic function. For example:

-- Get a list of all pages tagged with Meeting
page_titles = wiki.exprl('tagged', 'Meeting')
-- Construct a string with the contents of all those pages
output = 'All meeting notes:\n\n'
-- Iterate through each page in the order in which they were returned
for n, page_title in ipairs(page_titles) do
    -- Get the page contents
    page = wiki.get(page_title)
    -- Add it to the string
    output = output .. page.contents .. '\n\n---\n\n'
end
-- Return the string so it can be displayed on the page
return output

Getting information about your device

Lua has access to some information about the device Trunk Notes is running on. This can be useful for customizing your wiki depending on whether it is running on your iPhone or iPad.

A device table in the global environment has the following fields:

  • name - e.g. Matt’s iPad
  • systemName - e.g. iPhone OS
  • systemVersion - e.g. 5.1.1
  • model - e.g. iPad
  • localizedModel - if your locale defines a different name for the device.

For example:

if device.model == "iPad" then
    return "This is an iPad!"
else
    return "This is not an iPad :o("
end

Using Lua in snippets

You can use Lua in your editing workflow by creating snippets which execute Lua code. For example you might have a snippet called Snippet:Title which contains the text:

!!{{lua PageTitle.lua}}

NOTE: The snippet starts with !! which tells Trunk Notes to evaluate what is contained in the snippet before inserting it into the editor.

The page PageTitle.lua contains the Lua script:

return "/" .. page.title

If the snippet execute text is set to xx and titlexx is typed when editing a page the current title of the page will be inserted into the editor.

NOTE: As the Snippet text gets executed and translated into HTML a “/” is prepended to the page title so that the page name is not expanded. This however only works for WikiWord page names. Extending this to cope with single word page names is left as an exercise for the reader!