👨‍💻 about me home CV/Resume 🖊️ Contact Github LinkedIn I’m a Haskeller 📝 Blog Freedom, privacy, tutorials… 🏆 Best of LuaX Calculadoira panda upp Haskell todo pwd TPG Nextcloud Git BitTorrent

Boycott the Football World Cup in Qatar in 2022.
No to pollution and the non-respect for the environment (football in the desert is as fucking stupid as winter olympic games where the snow does not fall).
No to the dictatorship of money and the non-respect of basic human rights.

I implore you to boycott this threat against humanity:
It’s time to stop consuming and polluting for nothing. Earth is burning and there is no planet B (even Elon Musk won’t save you).

I’m so sad to see how stupid you human beings can be.
What about fighting together against the apocalypse that is coming very soon instead of shooting ourselves in the foot like fools?
Hey fucking dude, wake up! Look up!

If you’re ready to make some efforts, you’re welcome to my website. Otherwise there is no hope…

💣 Kick GAFAMs out (✔️ ǝlƃooפ, ✔️ ʞooqǝɔɐℲ, ✔️ uozɐɯ∀): Stop giving our soul and money to evils, be free and respectful!
📰 Friday 2. April 2021: upp is a panda companion. It’s a Lua-scriptable lightweight text preprocessor.
🆕 since December 2020: Playing with the actor model in an embedded multicore context. C imperative components become C stream pure functions with no side effect ➡️ C low level programming with high level pure functional programming properties 🏆
📰 Saturday 30. January 2021: Playing with Pandoc Lua filters in Lua. panda is a lightweight alternative to abp providing a consistent set of Pandoc filters (text substitution, file inclusion, diagrams, scripts, …).
🆕 Sunday 24. May 2020: Working at EasyMile for more than 5 years. Critical real-time software in C, simulation and monitoring in Haskell ➡️ perfect combo! It’s efficient and funny ;-)
🚌 And we are recruiting! Contact if you are interested in Haskell or embedded softwares (or both).

lapp: Lua Application packager

Christophe Delord - http://cdelord.fr/lapp

Lua Application packager

lapp packs Lua scripts together along with a Lua interpretor (Lua 5.4.4) and produces a standalone executable for Linux and Windows.

lapp runs on Linux and lapp.exe on Windows.

lapp can produce both Linux and Windows binaries. lapp.exe can produce Windows binaries only.

No Lua interpretor needs to be installed. lapp contains its own interpretor.

lapp also comes with luax which bundles lapp with a Lua REPL.


Get lapp sources on GitHub: https://github.com/CDSoft/lapp, download dependencies and submodules and run make:

$ git clone https://github.com/CDSoft/lapp
$ cd lapp
$ sudo make dep         # install make, gcc (musl-gcc), ...
$ make submodules       # retreive submodules (luasocket, lz4, ...)
$ make                  # compile and test


$ make install    # install lapp and luax to ~/.local/bin or ~/bin
$ make install PREFIX=/usr/bin  # install lapp and luax to /usr/bin

lapp and luax are single autonomous executables. They do not need to be installed and can be copied anywhere you want.

make install only install Linux binaries and is not meant to be used on Windows.

Precompiled binaries

It is usually highly recommended to build lapp from sources. Some precompiled binaries are available here: lapp release.

The Linux and Raspberry Pi binaries are linked statically with musl and are not dynamic executables. They should work on any Linux distributions.


Usage: lapp [-o OUTPUT] script(s)

    -o OUTPUT   set the name of the output executable

The main script shall be the first one. Other scripts are libraries that can be loaded by the main script.

The name of OUTPUT defines the target platform:


Host Target Command
Linux Linux lapp main.lua lib1.lua lib2.lua -o linux_executable
Linux Windows lapp main.lua lib1.lua lib2.lua -o windows_executable.exe
Linux Bytecode lapp main.lua lib1.lua lib2.lua -o bytecode.lc
Windows Windows lapp.exe main.lua lib1.lua lib2.lua -o windows_executable.exe
Windows Bytecode lapp.exe main.lua lib1.lua lib2.lua -o bytecode.lc

Running linux_executable is equivalent to running luax main.lua.

Running windows_executable.exe is equivalent to running luax.exe main.lua.

Running luax bytecode.lc is equivalent to running luax main.lua or luax.exe main.lua.


Building lapp requires some external softwares.

Built-in modules

The lapp runtime comes with a few builtin modules.

These modules are heavily inspired by BonaLuna.

"Standard" library

local fun = require "fun"

fun.id(...) is the identity function.

fun.const(...) returns a constant function that returns ....

fun.keys(t) returns a sorted list of keys from the table t.

fun.values(t) returns a list of values from the table t, in the same order than fun.keys(t).

fun.pairs(t) returns a pairs like iterator, in the same order than fun.keys(t).

fun.concat(...) returns a concatenated list from input lists.

fun.merge(...) returns a merged table from input tables.

fun.flatten(...) flattens input lists and non list parameters.

fun.replicate(n, x) returns a list containing n times the Lua object x.

fun.compose(...) returns a function that composes input functions.

fun.map(f, xs) returns the list of f(x) for all x in xs.

fun.tmap(f, t) returns the table of {k = f(t[k])} for all k in keys(t).

fun.filter(p, xs) returns the list of x such that p(x) is true.

fun.tfilter(p, t) returns the table of {k = v} for all k in keys(t) such that p(v) is true.

fun.foreach(xs, f) executes f(x) for all x in xs.

fun.tforeach(t, f) executes f(t[k]) for all k in keys(t).

fun.prefix(pre) returns a function that adds a prefix pre to a string.

fun.suffix(suf) returns a function that adds a suffix suf to a string.

fun.range(a, b [, step]) returns a list of values [a, a+step, ... b]. The default step value is 1.

fun.I(t) returns a string interpolator that replaces nil by the value of ... in the environment defined by the table t. An interpolator can be given another table to build a new interpolator with new values.

lapp adds a few functions to the builtin string module:

string.split(s, sep, maxsplit, plain) splits s using sep as a separator. If plain is true, the separator is considered as plain text. maxsplit is the maximum number of separators to find (ie the remaining string is returned unsplit. This function returns a list of strings.

string.lines(s) splits s using '\n' as a separator.

string.words(s) splits s using '%s' as a separator.

string.ltrim(s), string.rtrim(s), string.trim(s) remove left/right/both end spaces

fs: File System module

local fs = require "fs"

fs.getcwd() returns the current working directory.

fs.chdir(path) changes the current directory to path.

fs.dir([path]) returns the list of files and directories in path (the default path is the current directory).

fs.walk([path], [reverse]) returns a list listing directory and file names in path and its subdirectories (the default path is the current directory). If reverse is true, the list is built in a reverse order (suitable for recursive directory removal)

fs.mkdir(path) creates a new directory path.

fs.mkdirs(path) creates a new directory path and its parent directories.

fs.rename(old_name, new_name) renames the file old_name to new_name.

fs.mv(old_name, new_name) alias for fs.rename(old_name, new_name).

fs.remove(name) deletes the file name.

fs.rm(name) alias for fs.remove(name).

fs.rmdir(path, [params]) deletes the directory path (recursively if params.recursive is true.

fs.copy(source_name, target_name) copies file source_name to target_name. The attributes and times are preserved.

fs.is_file(name) returns true if name is a file.

fs.is_dir(name) returns true if name is a directory.

fs.stat(name) reads attributes of the file name. Attributes are:

fs.inode(name) reads device and inode attributes of the file name. Attributes are:

fs.chmod(name, other_file_name) sets file name permissions as file other_file_name (string containing the name of another file).

fs.chmod(name, bit1, ..., bitn) sets file name permissions as bit1 or ... or bitn (integers).

fs.touch(name) sets the access time and the modification time of file name with the current time.

fs.touch(name, number) sets the access time and the modification time of file name with number.

fs.touch(name, other_name) sets the access time and the modification time of file name with the times of file other_name.

fs.basename(path) return the last component of path.

fs.dirname(path) return all but the last component of path.

fs.absname(path) return the absolute path name of path.

fs.join(...) return a path name made of several path components (separated by fs.sep).

fs.with_tmpfile(f) calls f(tmp) where tmp is the name of a temporary file.

fs.with_tmpdir(f) calls f(tmp) where tmp is the name of a temporary directory.

fs.sep is the directory separator (/ or \\).

fs.uR, fs.uW, fs.uX are the User Read/Write/eXecute mask for fs.chmod.

fs.gR, fs.gW, fs.gX are the Group Read/Write/eXecute mask for fs.chmod.

fs.oR, fs.oW, fs.oX are the Other Read/Write/eXecute mask for fs.chmod.

fs.aR, fs.aW, fs.aX are All Read/Write/eXecute mask for fs.chmod.

mathx: complete math library for Lua

local mathx = require "mathx"

mathx is taken from Libraries and tools for Lua.

This is a complete math library for Lua 5.3 with the functions available in C99. It can replace the standard Lua math library, except that mathx deals exclusively with floats.

There is no manual: see the summary below and a C99 reference manual, e.g. http://en.wikipedia.org/wiki/C_mathematical_functions

mathx library:

acos        cosh        fmax        lgamma      remainder
acosh       deg         fmin        log         round
asin        erf         fmod        log10       scalbn
asinh       erfc        frexp       log1p       sin
atan        exp         gamma       log2        sinh
atan2       exp2        hypot       logb        sqrt
atanh       expm1       isfinite    modf        tan
cbrt        fabs        isinf       nearbyint   tanh
ceil        fdim        isnan       nextafter   trunc
copysign    floor       isnormal    pow         version
cos         fma         ldexp       rad

imath: arbitrary precision integer and rational arithmetic library

local imath = require "imath"

imath is taken from Libraries and tools for Lua.

imath is an arbitrary-precision integer library for Lua based on imath.

imath library:

__add(x,y)          add(x,y)            pow(x,y)
__div(x,y)          bits(x)             powmod(x,y,m)
__eq(x,y)           compare(x,y)        quotrem(x,y)
__idiv(x,y)         div(x,y)            root(x,n)
__le(x,y)           egcd(x,y)           shift(x,n)
__lt(x,y)           gcd(x,y)            sqr(x)
__mod(x,y)          invmod(x,m)         sqrt(x)
__mul(x,y)          iseven(x)           sub(x,y)
__pow(x,y)          isodd(x)            text(t)
__shl(x,n)          iszero(x)           tonumber(x)
__shr(x,n)          lcm(x,y)            tostring(x,[base])
__sub(x,y)          mod(x,y)            totext(x)
__tostring(x)       mul(x,y)            version
__unm(x)            neg(x)
abs(x)              new(x,[base])

qmath: rational number library

local qmath = require "qmath"

qmath is taken from Libraries and tools for Lua.

qmath is a rational number library for Lua based on imath.

qmath library:

__add(x,y)          abs(x)              neg(x)
__div(x,y)          add(x,y)            new(x,[d])
__eq(x,y)           compare(x,y)        numer(x)
__le(x,y)           denom(x)            pow(x,y)
__lt(x,y)           div(x,y)            sign(x)
__mul(x,y)          int(x)              sub(x,y)
__pow(x,y)          inv(x)              todecimal(x,[n])
__sub(x,y)          isinteger(x)        tonumber(x)
__tostring(x)       iszero(x)           tostring(x)
__unm(x)            mul(x,y)            version

complex: math library for complex numbers based on C99

local complex = require "complex"

complex is taken from Libraries and tools for Lua.

complex is a math library for complex numbers based on C99.

complex library:

I       __tostring(z)   asinh(z)    imag(z)     sinh(z)
__add(z,w)  __unm(z)    atan(z)     log(z)      sqrt(z)
__div(z,w)  abs(z)      atanh(z)    new(x,y)    tan(z)
__eq(z,w)   acos(z)     conj(z)     pow(z,w)    tanh(z)
__mul(z,w)  acosh(z)    cos(z)      proj(z)     tostring(z)
__pow(z,w)  arg(z)      cosh(z)     real(z)     version
__sub(z,w)  asin(z)     exp(z)      sin(z)

ps: Process management module

local ps = require "ps"

ps.sleep(n) sleeps for n seconds.

sys: System module

local sys = require "sys"

sys.hostname() returns the host name.

sys.domainname() returns the domain name.

sys.hostid() returns the host id.

sys.platform is "Linux" or "Windows"

lz4: compression module

local lz4 = require "lz4"

lz4.compress(data) compresses data with LZ4 and returns the compressed string.

lz4.compress_hc(data) compresses data with LZ4HC and returns the compressed string.

lz4.decompress(data) decompresses data with LZ4 and returns the decompressed string.

crypt: cryptography module

local crypt = require "crypt"

Warning: the crypt package is a pure Lua package (i.e. not really fast).

crypt.hex.encode(data) encodes data in hexa.

crypt.hex.decode(data) decodes the hexa data.

crypt.base64.encode(data) encodes data in base64.

crypt.base64.decode(data) decodes the base64 data.

crypt.crc32(data) computes the CRC32 of data.

crypt.AES(password [,keylen [,mode] ]) returns an AES codec. password is the encryption/decryption key, keylen is the length of the key (128 (default), 192 or 256), mode is the encryption/decryption mode ("cbc" (default) or "ecb"). crypt.AES objects have two methods: encrypt(data) and decrypt(data).

crypt.BTEA(password) returns a BTEA codec (a tiny cipher with reasonable security and efficiency, see http://en.wikipedia.org/wiki/XXTEA). password is the encryption/decryption key (only the first 16 bytes are used). crypt.BTEA objects have two methods: encrypt(data) and decrypt(data). BTEA encrypts 32-bit words so the length of data should be a multiple of 4 (if not, BTEA will add null padding at the end of data).

crypt.RC4(password, drop) return a RC4 codec (a popular stream cypher, see http://en.wikipedia.org/wiki/RC4). password is the encryption/decryption key. drop is the numbre of bytes ignores before encoding (768 by default). crypt.RC4 returns the encryption/decryption function.

crypt.random(bits) returns a string with bits random bits.

lpeg: Parsing Expression Grammars For Lua

LPeg is a pattern-matching library for Lua.

local lpeg = require "lpeg"
local re = require "re"

The documentation of these modules are available on Lpeg web site:

luasocket: Network support for the Lua language

local socket = require "socket"

The socket package is based on Lua Socket and adapted for lapp.

The documentation of Lua Socket is available at the Lua Socket documentation web site.

lapp provides an additional package for higher level FTP functionalities:

local ftp = require "ftp" -- ftp is a function

ftp(url [, login, password]) creates an FTP object to connect to the FTP server at url. login and password are optional. Methods are:

rl: readline

rl.read(prompt) prints prompt and returns the string entered by the user.

Warning: rl is no longer related to the Linux readline library. If you need readline, you can use rlwrap on Linux.


lapp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

lapp is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with lapp.  If not, see <https://www.gnu.org/licenses/>.

For further information about lapp you can visit

lapp uses other third party softwares: