Lua Small scripting language

Version 5.4 · source

Start here

lua <file.lua>
Run a script
lua
Start the REPL
lua -e "<code>"
Run a string
local x = 10
Local variable
for i = 1, 10 do ... end
Numeric loop
for k, v in pairs(<t>) do
Iterate a table
string.format("%d", n)
Format text
pcall(<f>, ...)
Catch an error

Concepts

  1. Table your data
  2. Metatable __index, __add...
  3. Metamethod function or table
  4. Value returned

Run the interpreter

lua <file.lua> [<args>]
Run a script with arguments
lua
Start the interactive REPL
lua -e "<code>"
Execute a string
lua -i <file.lua>
Run a script, then drop into the REPL
arg[0]
Script name; arguments are arg[1..n]

Compile with luac

luac -o <out.luac> <file.lua>
Compile to bytecode
luac -p <file.lua>
Check syntax only

Types and variables

local <name> = <value>
Declare a local variable
type(<v>)
Name of the value's type
<a> and <b> or <c>
Ternary idiom (breaks if b is falsy)
tostring(<v>) / tonumber(<s> [, <base>])
Convert values
#<t_or_s>
Length of table (sequence) or string
<a> .. <b>
Concatenate strings

Operators

<a> // <b>
Floor division
<a> % <b>
Modulo, sign follows divisor
<a> ^ <b>
Power, always a float

Control flow

if <c> then ... elseif <c> then ... else ... end
Conditional
for i = <a>, <b> [, <step>] do ... end
Numeric loop, end inclusive
for i, v in ipairs(<t>) do ... end
Array loop, stops at first nil
for k, v in pairs(<t>) do ... end
All keys, unspecified order
while <c> do ... end
While loop
goto <label> ... ::<label>::
Jump; the only way to continue

Functions

function <name>(<args>) ... end
Define a function
local function <name>(<args>) ... end
Local, can recurse
function <name>(...) local a = {...} end
Variadic function
select("#", ...)
Count varargs, nils included
select(<n>, ...)
Varargs from position n

Tables and metatables

local t = {1, 2, 3}
Array constructor
local t = {name = "x", ["k k"] = 1}
Record constructor
<t>.<key> <t>[<expr>]
Field access
setmetatable(<t>, <mt>)
Attach a metatable, returns t
mt.__index = <table_or_fn>
Fallback for missing keys, inheritance
mt.__call = <fn>
Make a table callable
mt.__tostring = <fn>
Custom tostring/print output
rawget(<t>, <k>) / rawset(<t>, <k>, <v>)
Bypass metamethods
obj:method(<args>)
Sugar for obj.method(obj, args)
function Class:method() ... end
Define a method with self

Strings

#<s>
Length in bytes
<s>:sub(<i> [, <j>])
Substring, 1-based, negatives from end
<s>:upper() <s>:lower()
Change case
<s>:rep(<n> [, <sep>])
Repeat
<s>:find(<pat> [, <init> [, true]])
Start and end index; true = plain text
<s>:match(<pat>)
First match or captures
<s>:gmatch(<pat>)
Iterator over all matches
<s>:gsub(<pat>, <repl> [, <n>])
Replace; returns string and count
string.format(<fmt>, ...)
printf-style formatting
utf8.char(<cp>) utf8.len(<s>)
UTF-8 helpers

Patterns

. %a %d %l %u %s %w %p %x
Any, letter, digit, lower, upper, space, alnum, punct, hex
%A %D %S %W
Uppercase class = complement
[abc] [a-z] [^0-9]
Set, range, negated set
* + - ?
0+, 1+, 0+ shortest, 0 or 1
^ $
Anchor to start / end of subject
( )
Capture; () returns the position
%b()
Balanced pair
%f[%w]
Frontier: word boundary
%. %% %-
Escape a magic character
"^%s*(.-)%s*$"
Trim whitespace

Format specifiers

%d %i
Integer
%5.2f
Float, width 5, 2 decimals
%s
String (any value via tostring)
%x %X %o
Hex and octal

Table library

table.insert(<t>, <v>)
Append
table.insert(<t>, <pos>, <v>)
Insert, shifting up
table.remove(<t> [, <pos>])
Remove last or at pos, returns it
table.concat(<t> [, <sep>])
Join strings
table.sort(<t> [, <cmp>])
Sort in place; cmp(a, b) returns a < b
table.unpack(<t> [, <i> [, <j>]])
Array to multiple values
table.pack(<values>)
Values to table with n

Math

math.floor(<x>) math.ceil(<x>)
Round down / up
math.max(<a>, ...) math.min(<a>, ...)
Largest / smallest
math.abs(<x>) math.sqrt(<x>)
Absolute value, square root
math.random(<m>, <n>)
Random integer in range
math.random()
Float in [0, 1)
math.tointeger(<x>)
Integer or nil (fail)
math.huge math.pi
Infinity, pi

Errors

error(<msg> [, <level>])
Raise an error; level 2 blames the caller
assert(<v> [, <msg>])
Raise if v is falsy, else return args
pcall(<f>, ...)
Protected call: true, results or false, err
xpcall(<f>, <handler>, ...)
Protected call with handler
xpcall(<f>, debug.traceback)
Catch and keep a stack trace

Modules

local m = require("<name>")
Load a module once, cached
return M
End a module file with its table
package.path
Lua search templates, ; separated
package.loaded[<name>] = nil
Force reload on next require
dofile(<file>)
Run a file, no caching

Coroutines

coroutine.create(<f>)
New suspended coroutine
coroutine.resume(<co>, ...)
Run until yield; true/false plus values
coroutine.yield(...)
Suspend, hand values to resume
coroutine.wrap(<f>)
Coroutine as a plain function
coroutine.status(<co>)
running, suspended, normal, dead

OS and I/O

print(<values>)
Print tab-separated with newline
io.write(<values>)
Write without newline
io.read("l")
Read a line (a: all, n: number, L: with newline)
io.open(<path>, "r")
Open a file; nil, err on failure
f:read("a")
Read the whole file
f:write(<values>)
Write to the file
f:lines()
Iterate lines of the file
f:close()
Close the file
io.lines(<path>)
Iterate lines, auto-closes
io.stderr:write(<msg>)
Write to standard error
os.getenv(<name>)
Environment variable or nil
os.time()
Seconds since the epoch
os.date("%Y-%m-%d %H:%M" [, <t>])
Format a time; "*t" gives a table
os.execute(<cmd>)
Run a shell command
os.exit([<code>])
Exit the program

LuaRocks

luarocks install <rock>
Install a package
luarocks install --local <rock>
Install into the user tree
luarocks list
Show installed rocks
luarocks search <text>
Search the repository
luarocks remove <rock>
Uninstall
luarocks path
Print LUA_PATH and LUA_CPATH settings

Recipes

Class with inheritance
local Animal = {}Animal.__index = Animalfunction Animal.new(name) return setmetatable({name = name}, Animal) endfunction Animal:speak() return self.name .. " ..." endlocal Dog = setmetatable({}, {__index = Animal})Dog.__index = Dogfunction Dog.new(name) return setmetatable(Animal.new(name), Dog) end
Split a string
local parts = {}for w in (s .. ","):gmatch("(.-),") do parts[#parts + 1] = w end
Read a file safely
local f, err = io.open(path, "r")if not f then error(err) endlocal text = f:read("a")f:close()
Generator with a coroutine
local gen = coroutine.wrap(function()  for i = 1, 3 do coroutine.yield(i) endend)print(gen(), gen(), gen())