< Lua
Jump to navigation Jump to search

How to use this tutorial[edit]

This tutorial is from 2012 and rather incomplete. For the time being, w:en:Help:Lua for beginners might be a better resource.

It is supposed to focus on established MediaWiki template developers who are new to Lua. If you are new to templates on MediaWiki, but have Lua experience, you may want to find out more about templates first. Note that some things in Scribunto do not apply to the Lua distribution.

Introduction to Lua[edit]

Brad Jorsch’s short presentation for a basic example of how to convert a wikitext template into a Lua module.
  • Lua scripting general information and brief historical context of its planned use in MediaWiki.
    • What is Lua? Check out the demo if you don't want to download Scribunto just yet.
  • What is different from JavaScript and object-oriented languages we could have used?
    • Scribunto: how is the Lua implementation in MediaWiki different? Wikitext is not parsed the way you would normally expect. Parser frames are arguments in Scribunto templates. Strip markers replace certain markup, which, if it is passed, will result in placeholders instead of markup. You will need to use the Namespace:Module.
  • How you adapt for these differences.

Hands-on Lua scripting[edit]

local p = {}
function p.hello(frame)
    return 'Hello'
return p
Explanation of Code 
local this tells lua the "scope" of the variable that follows. It can only be accessed right here, locally. The opposite is "global".
p this is a (local) object (variable) we are creating. We have decided to call it p. We could call it anything we wanted. We will address it as p later, whenever we want to do something with it.
= {} The equal sign means we're assigning what comes after it to what came before it. The {} means "object", in this and many other script languages like JavaScript. It could have had stuff inside it like {foo = 'bar'}, but we're making it empty and will assign stuff inside it later.
function Now we're creating a function, which like in calculus is a piece of code that takes values and returns other values. The function will include all code until we get to a keyword "end". This is similar to most popular programming languages.
p.hello Remember when we made the object "p"? Now we are creating a property inside of that object, called "hello", which is this function. The dot means "property inside" in this and many other script languages.
(frame) The parens() wrap whatever values we are passing to the function we are creating, the one called "hello". "frame" is the name we give a container of all parameters we'll pass to it. We could call it anything, as long as we consistently refer to it by that name later.
return 'Hello' "return" says we send this back out of the function we're in, which is called p.hello, and it will be returned to the object we created, p. 'Hello' is the thing we're returning. The single quotes around it mean it's a string, not a variable named Hello that contains some value.
end Remember when we said that the function would go on until we got to a keyword end? This is that keyword.
return p Remember the other "return" that sent 'Hello' out of the function called p.hello? Well THIS return takes whatever happened inside the entire object (which we called p) and sends it outside of that object. In this case, it'll end up being printed to the screen for the user to see or wiki server to parse.

  • Go to the module talk page.
  • Put a #invoke in it to call that new module:
{{#invoke: Sandbox/your username/my_module | hello }}

Accessing template parameters[edit]

Here's a simple example of a function that uses the parameters:

local p = {}
function p.hello(frame)
    return 'Hello, my ' .. frame.args[1] .. ' is ' .. frame.args[2]
return p

Such a function can access the frame object to get access to the parameters that the template was invoked with. For example, let's change the previous module so that it takes two arguments, like this:

{{#invoke: Sandbox/your username/my_module | hello | hair | brown }}

Our Lua function can use the parameters "hair" and "brown" in either of two ways:

  1. Access them directly as frame.args[1] and frame.args[2], respectively.
  2. Iterate them using the pairs( frame.args ) function, which returns a (name, value) pair for each; this is the best way to code a template that can take a variable number of parameters.
  1. Named arguments can also be used, such as frame.args['title'] or frame.args.title in this example:
{{#invoke: Sandbox/your username/my_module | hello | hair | brown | title=Mister }}

A few pitfalls to avoid:

  1. A parameter value that includes non-ASCII characters (such as clé) cannot be written frame.args.clé; you must use the form frame.args['clé'].
  2. The parameter values are always strings, even if they are numeric in form; you can use the Lua function tonumber() if you need to treat a value as a number.
  3. However, numbered parameter keys are numbers, even if they are given explicitly in the template invocation (for example, the parameters in both {{#invoke:Sandbox/your username/my_module | hello | world}} and {{#invoke:Sandbox/your username/my_module | hello | 1=world}} are indexed by the number 1, not the string '1'.
  4. With explicitly named (or numbered) parameters, leading and trailing whitespace is stripped from name and value. This is similar to template parameters.
  5. An empty string value is not the same as a missing value, which is nil; for example,
    {{#invoke:Sandbox/your username/my_module | hello | world }}
    results in frame.args[2] being nil (which will cause a script error in the example code hereinbefore), but
    {{#invoke:Sandbox/your username/my_module | hello | world | }}
    results in frame.args[2] being an empty string (which will not, although the resulting text will look odd). One way to work around this is to assign the desired parameters to a local variable, and replacing nils with empty strings at this step; e.g.,
    local arg2 = frame.args[2] or ''

External resources for general/non-wiki Lua scripting[edit]