lights FAQ Forum

Standard Libraries


everyday Lua functions

local glue = require'glue'

API Summary

glue.clamp(x, min, max) clamp x in range
glue.lerp(x, x0, x1, y0, y1) linear interpolation
glue.pack(...) -> t pack varargs
glue.unpack(t, [i] [,j]) -> ... unpack varargs
glue.count(t) -> n number of keys in table
glue.index(t) -> dt switch keys with values
glue.keys(t[,sorted|cmp]) -> dt make a list of all the keys
glue.update(dt, t1, ...) -> dt merge tables - overwrites keys
glue.merge(dt, t1, ...) -> dt merge tables - no overwriting
glue.sortedpairs(t [,cmp]) -> iter() -> k, v like pairs() but in key order
glue.attr(t, k1 [,v])[k2] = v autofield pattern
glue.indexof(v, t) -> i scan array for value
glue.extend(dt, t1, ...) -> dt extend a list
glue.append(dt, v1, ...) -> dt append non-nil values to a list
glue.shift(t, i, n) -> t shift list elements
glue.reverse(t) -> t reverse list in place
glue.gsplit(s,sep[,start[,plain]]) -> iter() -> e[,captures...] split a string by a pattern
glue.lines(s) -> iter() -> s iterate the lines of a string
glue.trim(s) -> s remove padding
glue.escape(s [,mode]) -> pat escape magic pattern characters
glue.tohex(s|n [,upper]) -> s string to hex
glue.fromhex(s) -> s hex to string
glue.collect([i,] iterator) -> t collect iterated values into a list
glue.pass(...) -> ... does nothing, returns back all arguments
glue.memoize(f) -> f memoize pattern
glue.inherit(t, parent) -> t set or clear inheritance
glue.object([super][, t]) -> t create a class or object (see description)
glue.autotable([t]) -> t autotable pattern
glue.canopen(filename[, mode]) -> filename | nil check if a file exists and can be opened
glue.readfile(filename[, format][, open]) -> s | nil, err read the contents of a file into a string
glue.readpipe(cmd[,format][, open]) -> s | nil, err read the output of a command into a string
glue.writefile(filename, s|t|read, [format], [tmpfile]) write data to file safely
glue.printer(out[, format]) -> f virtualize the print() function
glue.assert(v [,message [,format_args...]]) -> v assert with error message formatting
glue.protect(func) -> protected_func wrap an error-raising function
glue.pcall(f, ...) -> true, ... | false, traceback pcall with traceback
glue.fpcall(f, ...) -> result | nil, traceback coding with finally and except
glue.fcall(f, ...) -> result
glue.autoload(t, submodules) -> t autoload table keys from submodules
glue.autoload(t, key, module|loader) -> t autoload table keys from submodules
glue.bin get the script's directory
glue.luapath(path [,index [,ext]]) insert a path in package.path
glue.cpath(path [,index]) insert a path in package.cpath
glue.malloc([ctype, ]size) -> cdata allocate an array using system's malloc
glue.malloc(ctype) -> cdata allocate a C type using system's malloc free malloc'ed memory
glue.addr(ptr) -> number | string store pointer address in Lua value
glue.ptr([ctype, ]number|string) -> ptr convert address to pointer


glue.clamp(x, min, max)

Clamp a value in range. Implemented as math.min(math.max(x, min), max).


glue.pack(...) -> t

Pack varargs. Implemented as n = select('#', ...), ...}.

glue.unpack(t,[i][,j]) -> ...

Unpack varargs. Implemented as unpack(t, i or 1, j or t.n or #t).


glue.count(t) -> n

Count all the keys in a table.

glue.index(t) -> dt

Switch table keys with values.


Extract a rfc850 date from a string. Use lookup tables for weekdays and months.

local weekdays = glue.index{'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'}
local months = glue.index{'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'}

--weekday "," SP 2DIGIT "-" month "-" 2DIGIT SP 2DIGIT ":" 2DIGIT ":" 2DIGIT SP "GMT"
--eg. Sunday, 06-Nov-94 08:49:37 GMT
function rfc850date(s)
   local w,d,mo,y,h,m,s = s:match'([A-Za-z]+), (%d+)%-([A-Za-z]+)%-(%d+) (%d+):(%d+):(%d+) GMT'
   d,y,h,m,s = tonumber(d),tonumber(y),tonumber(h),tonumber(m),tonumber(s)
   w = assert(weekdays[w])
   mo = assert(months[mo])
   if y then y = y + (y > 50 and 1900 or 2000) end
   return {wday = w, day = d, year = y, month = mo, hour = h, min = m, sec = s}

for k,v in pairs(rfc850date'Sunday, 06-Nov-94 08:49:37 GMT') do


day   6
sec   37
wday  1
min   49
year  1994
month 11
hour  8

Copy-paste a bunch of defines from a C header file and create an inverse lookup table to find the name of a value at runtime.

--from ibase.h
info_end_codes = {
   isc_info_end             = 1,  --normal ending
   isc_info_truncated       = 2,  --receiving buffer too small
   isc_info_error           = 3,  --error, check status vector
   isc_info_data_not_ready  = 4,  --data not available for some reason
   isc_info_svc_timeout     = 64, --timeout expired
info_end_code_names = glue.index(info_end_codes)



glue.keys(t[,sorted|cmp]) -> dt

Make a list of all the keys of t, optionally sorted.


An API expects a list of things but you have them as keys in a table because you are indexing something on them.

For instance, you have a table of the form {socket = thread} but wants a list of sockets.

glue.update(dt,t1,...) -> dt

Update a table with elements of other tables, overwriting any existing keys.

  • nil arguments are skipped.


Create an options table by merging the options received as an argument (if any) over the default options.

function f(opts)
   opts = glue.update({}, default_opts, opts)

Shallow table copy:

t = glue.update({}, t)

Static multiple inheritance:

C = glue.update({}, A, B)

glue.merge(dt,t1,...) -> dt

Update a table with elements of other tables skipping on any existing keys.

  • nil arguments are skipped.


Normalize a data object with default values:

glue.merge(t, defaults)

glue.sortedpairs(t[,cmp]) -> iter() -> k,v

Like pairs() but in key order.

The implementation creates a temporary table to sort the keys in.

glue.attr(t,k1[,v])[k2] = v

Idiom for t[k1][k2] = v with auto-creating of t[k1] if not present. Useful for when an autotable is not wanted.


glue.indexof(v, t) -> i

Scan an array (up to #t) for a value and if found, return the index.

glue.extend(dt,t1,...) -> dt

Extend the list with the elements of other lists.

  • nil arguments are skipped.
  • list elements are the ones from 1 to #dt.


Accumulating values from multiple list sources.

glue.append(dt,v1,...) -> dt

Append non-nil arguments to a list.


Appending an object to a flattened list of lists (eg. appending a path element to a 2d path).

glue.shift(t,i,n) -> t

Shift all the list elements starting at index i, n positions to the left or further to the right.

For a positive n, shift the elements further to the right, effectively creating room for n new elements at index i. When n is 1, the effect is the same as for table.insert(t, i, t[i]). The old values at index i to i+n-1 are preserved, so #t still works after the shifting.

For a negative n, shift the elements to the left, effectively removing the n elements at index i. When n is -1, the effect is the same as for table.remove(t, i).


Removing a portion of a list or making room for more elements inside the list.

glue.reverse(t) -> t

Reverse a list in-place and return the input arg.


glue.gsplit(s,sep[,start[,plain]]) -> iter() -> e[,captures...]

Split a string by a separator pattern (or plain string) and iterate over the elements.

  • if sep is "" return the entire string in one iteration
  • if s is "" return s in one iteration
  • empty strings between separators are always returned, eg. glue.gsplit(',', ',') produces 2 empty strings
  • captures are allowed in sep and they are returned after the element, except for the last element for which they don't match (by definition).


for s in glue.gsplit('Spam eggs spam spam and ham', '%s*spam%s*') do

> "Spam eggs"
> ""
> "and ham"

glue.lines(s) -> iter() -> s

Iterate the lines of a string.

  • the lines are split at \r\n, \r and \n markers.
  • the line ending markers are included in the iterated strings.
  • if the string is empty or doesn't contain a line ending marker, it is is iterated once.
  • if the string ends with a line ending marker, one more empty string is iterated.

glue.trim(s) -> s

Remove whitespace (defined as Lua pattern "%s") from the beginning and end of a string.

glue.escape(s[,mode]) -> pat

Escape magic characters of the string s so that it can be used as a pattern to string matching functions.

  • the optional argument mode can have the value "*i" (for case insensitive), in which case each alphabetical character in s will also be escaped as "[aA]" so that it matches both its lowercase and uppercase variants.
  • escapes embedded zeroes as the %z pattern.


  • workaround for lack of pattern syntax for "this part of a match is an arbitrary string"
  • workaround for lack of a case-insensitive flag in pattern matching functions

glue.tohex(s|n[,upper]) -> s

Convert a binary string or a Lua number to its hex representation.

  • lowercase by default
  • uppercase if the arg upper is truthy
  • numbers must be in the unsigned 32 bit integer range

glue.fromhex(s) -> s

Convert a hex string to its binary representation.


glue.collect([i,]iterator) -> t

Iterate an iterator and collect its i'th return value of every step into a list.

  • i defaults to 1


Implementation of keys() and values() in terms of collect()

keys = function(t) return glue.collect(pairs(t)) end
values = function(t) return glue.collect(2,pairs(t)) end

Collecting string matches:

s = 'a,b,c,'
t = glue.collect(s:gmatch'(.-),')
for i=1,#t do print(t[i]) end

> a
> b
> c


glue.pass(...) -> ...

The identity function. Does nothing, returns back all arguments.


Default value for optional callback arguments:

function urlopen(url, callback, errback)
   callback = callback or glue.pass
   errback = errback or glue.pass

glue.memoize(f) -> f

Memoization for functions with any number of arguments and one return value. Supports nil and NaN args and retvals.

Guarantees to only call the original function once for the same combination of arguments, with special attention to the vararg part of the function, if any. For instance, for a function f(x, y, ...), calling f(1) is considered the same as calling f(1, nil), but calling f(1, nil) is not the same as calling f(1, nil, nil).


glue.inherit(t, parent) -> t
glue.inherit(t, nil) -> t

Set a table to inherit attributes from a parent table, or clear inheritance.

If the table has no metatable (and inheritance has to be set, not cleared) make it one.


Logging mixin:

AbstractLogger = glue.inherit({}, function(t,k) error('abstract '..k) end)
NullLogger = glue.inherit({log = function() end}, AbstractLogger)
PrintLogger = glue.inherit({log = function(self,...) print(...) end}, AbstractLogger)

HttpRequest = glue.inherit({
   perform = function(self, url)
      self:log('Requesting', url, '...')
}, NullLogger)

LoggedRequest = glue.inherit({log = PrintLogger.log}, HttpRequest)


> Requesting   ...

Defining a module in Lua 5.2

_ENV = glue.inherit({},_G)


  • to get the effect of static (single or multiple) inheritance, use glue.update.

  • when setting inheritance, you can pass in a function.

glue.object([super][, t]) -> t

Create a class or object from t (which defaults to {}) by setting t as its own metatable, setting t.__index to super and t.__call to super.__call. This simple object model has the following qualities:

  • the implementation is only 4 LOC (not a typo) and can thus be copy-pasted into any module to avoid a dependency on the glue library.
  • procedural instantiation with t(...) which calls t:__call(...).
  • small memory footprint (3 table slots and no additional tables).
  • subclassing from instances is allowed (prototype-based inheritance).
  • a stub class/instance constructor looks like this:
    • function t:__call(o) return glue.object(self, o) end.
  • a separate constructor to be used only for subclassing can be made with the same pattern:
    • function t:subclass(c) return glue.object(self, c) end.
  • virtual classes (i.e. nested inner classes whose fields and methods can be overridden by subclasses of the outer class): composite objects which need to instantiate other objects can be made extendable easily by exposing those objects' classes as fields of the container class with container_class.inner_class = inner_class and instantiating with self.inner_class(...) so that replacing inner_class in a sub-class of container_class is possible. Moreso, instantiation with self:inner_class(...) (so with a colon) passes the container object to inner_class's constructor automatically which allows referencing the container object from the inner object.

There are also some limitations:

  • when overriding, the super class must be referenced explicitly:
    • <super_class>.<method>(self, ...).

glue.autotable([t]) -> t

Set a table to create/return missing keys as autotables.

In the example below, t.a, t.a.b, t.a.b.c are created automatically as autotables.

local t = autotable()
t.a.b.c.d = 'hello'


glue.canopen(file[, mode]) -> filename | nil

Checks whether a file exists and it's available for reading or writing. The mode arg is the same as for [] and defaults to 'rb'.

glue.readfile(filename[,format][,open]) -> s | nil, err

Read the contents of a file into a string.

  • format can be "t" in which case the file will be read in text mode (default is binary mode).
  • open is the file open function which defaults to

glue.readpipe(cmd[,format][,open]) -> s | nil, err

Read the output of a command into a string. The options are the same as for glue.readfile.

glue.replace(oldpath, newpath)

Move or rename a file. If newpath exists and it's a file, it is replaced by the old file atomically. The operation can still fail under many circumstances like if newpath is a directory or if the files are in different filesystems or if oldpath is missing or locked, etc.

For consistent behavior across OSes, both paths should be absolute paths or just filenames.

NOTE: LuaJIT only.


Write the contents of a string, table or reader to a file.

  • format can be "t" in which case the file will be written in text mode (default is binary mode).
  • read can be a function to draw strings or numbers from.
  • if writing fails and tmpfile is not given, the file is removed and an error is raised; if tmpfile is given then the data is written that file first which is then renamed to filename and if writing or renaming fails the temp file is removed and filename is not touched.

glue.printer(out[, format]) -> f

Create a print()-like function which uses the function out to output its values and format to format each value. For instance glue.printer(io.write, tostring) returns a function which behaves like the standard print() function.



Like assert but supports formatting of the error message using string.format().

This is better than assert(v, string.format(message, format_args...)) because it avoids creating the message string when the assertion is true.

NOTE: Unlike standard assert(), this only returns the first argument to avoid returning the error message and it's args along with it.


glue.assert(depth <= maxdepth, 'maximum depth %d exceeded', maxdepth)

glue.protect(func) -> protected_func

In Lua, API functions conventionally signal errors by returning nil and an error message instead of raising errors. In the implementation however, using assert() and error() is preferred to coding explicit conditional flows to cover exceptional cases. Use this function to convert error-raising functions to nil,err-returning functions:

protected_function = glue.protect(function()
   return result_value

local ret, err = protected_function()

glue.pcall(f,...) -> true,... | false,traceback

With Lua's pcall() you lose the stack trace, and with usual uses of pcall() you don't want that. This variant appends the traceback to the error message.

NOTE: Lua 5.2 and LuaJIT only.

glue.fpcall(f,...) -> result | nil,traceback

glue.fcall(f,...) -> result

These constructs bring the ubiquitous try/finally/except idiom to Lua. The first variant returns nil,error when errors occur while the second re-raises the error.


local result = glue.fpcall(function(finally, except, ...)
  local temporary_resource = acquire_resource()
  finally(function() temporary_resource:free() end)
  local final_resource = acquire_resource()
  except(function() final_resource:free() end)
  ... code that might break ...
  return final_resource
end, ...)


glue.autoload(t, submodules) -> t
glue.autoload(t, key, module|loader) -> t

Assign a metatable to t such that when a missing key is accessed, the module said to contain that key is require'd automatically.

The submodules argument is a table of form {key = module_name | load_function} specifying the corresponding Lua module (or load function) that make each key available to t. The alternative syntax allows specifying the key - submodule associations one by one.


Module autoloading allows splitting the implementation of a module in many submodules containing optional, self-contained functionality, without having to make this visible in the user API. This effectively disconnects how an API is modularized from how its implementation is modularized, allowing the implementation to be refactored at a later time without changing the API.


main module (foo.lua):

local function bar() --function implemented in the main module

--create and return the module table
return glue.autoload({
   bar = bar,
}, {
   baz = 'foo_extra', --autoloaded function, implemented in module foo_extra

submodule (foo_extra.lua):

local foo = require'foo'

function foo.baz(...)

in usage:

local foo = require'foo'

foo.baz(...) -- foo_extra was now loaded automatically


Get the script's directory. This allows finding files in the script's directory regardless of the directory that Lua is started in.

For executables created with bundle, this is the executable's directory.


local foobar = glue.readfile(glue.bin .. '/' .. file_near_this_script)


This only works if glue itself can already be found and required (chicken/egg problem). Also, the path is relative to the current directory, so this stops working if the current directory is changed.


Insert a Lua search pattern in package.path such that require will be able to load Lua modules from that path. The optional index arg specifies the insert position (default is 1, that is, before all existing paths; can be negative, to start counting from the end; can be the string 'after', which is the same as 0). The optional ext arg specifies the file extension to use (default is "lua").


Insert a Lua search pattern in package.cpath such that require will be able to load Lua/C modules from that path. The index arg has the same meaning as with glue.luapath.



require'foo' --looking for `foo` in the same directory as the running script first


glue.malloc([ctype,]size) -> cdata

Allocate a ctype[size] array with system's malloc. Useful for allocating larger chunks of memory without hitting the default allocator's 2 GB limit.

  • the returned cdata has the type ctype(&)[size] so ffi.sizeof(cdata) returns the correct size (the downside is that size cannot exceed 2 GB).
  • ctype defaults to char.
  • failure to allocate results in error.
  • the memory is freed when the cdata gets collected or with

REMEMBER! Just like with, casting the result cdata further will get you weak references to the allocated memory. To transfer ownership of the memory, use ffi.gc(original, nil); ffi.gc(pointer,

NOTE: LuaJIT only.

glue.malloc(ctype) -> cdata

Allocate a ctype with system's malloc. The result has the type ctype&.

CAVEAT: For primitive types, you must specify a size, or will not work!

Free malloc'ed memory.


local data = glue.malloc(100)
assert(ffi.sizeof(data) == 100)

local data = glue.malloc('int', 100)
assert(ffi.sizeof(data) == 100 * ffi.sizeof'int')

local data = glue.malloc('struct S')
assert(ffi.sizeof(data) == ffi.sizeof'struct S')

glue.addr(ptr) -> number | string

Convert the address of a pointer into a Lua number (or possibly string on 64bit platforms). This is useful for:

  • hashing on pointer values (i.e. using pointers as table keys)
  • moving pointers in and out of Lua states when using luastate

glue.ptr([ctype,]number|string) -> ptr

Convert an address value stored as a Lua number (or possibly string on 64bit platforms) to a cdata pointer, optionally specifying a ctype for the pointer (defaults to void*).


String functions are also in the glue.string table. You can extend the Lua string namespace:

glue.update(string, glue.string)

so you can use them as string methods:

s = s:trim()


for syntax highlighting

glue.clamp, glue.pack, glue.unpack, glue.count, glue.index, glue.keys, glue.update, glue.merge, glue.sortedpairs, glue.attr, glue.indexof, glue.extend, glue.append, glue.shift, glue.reverse, glue.gsplit, glue.lines, glue.trim, glue.escape, glue.tohex, glue.fromhex, glue.collect, glue.pass, glue.memoize, glue.inherit, glue.object, glue.autotable, glue.canopen, glue.readfile, glue.readpipe, glue.writefile, glue.printer, glue.assert, glue.protect, glue.pcall, glue.fpcall, glue.fcall, glue.autoload, glue.bin, glue.luapath, glue.cpath, glue.malloc,, glue.addr, glue.ptr



Last updated: 13 days ago | Edit on GitHub

Pkg type:Lua+ffi
Version: r13-4-g4a417f1
Last commit:
License: PD
Requires: luajit 
Required by: bitmap  bmp  expat  fbclient  gfonts  giflib  hmac  imgui  libjpeg  libpng  luapower  minizip  nanojpeg  nw  obj_parser  openvg  path2d  sg  socketloop  svg_parser  thread  ui  unit  utf8  cplayer  winapi  imgui_nw_cairo  winapi.cairopanel  winapi.wglpanel  xlib  videoinput  imgui_nw_cairo