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

🆕 since August 2022: LuaX is a Lua eXtended interpretor/cross compiler providing a bunch of useful modules (statically linked, no dependency). Nice integration with upp (new functions and modules available to extend upp macros) and also with a soon released but yet confidential project about actor oriented programming!
💣 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 ;-)

LuaX: Lua eXtended

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

LuaX in Lua

The script lib/luax.lua is a standalone Lua package that reimplements some LuaX modules. It can be used in Lua projects without any other LuaX dependency.

These modules may have slightly different and degraded behaviours compared to the LuaX modules. Especially fs and ps may be incomplete and less accurate than the same functions implemented in C in LuaX.

require "luax"

changes the package module such that require can load fun, fs, sh and sys.

Functional programming utilities

local F = require "fun"

fun provides some useful functions inspired by functional programming languages, especially by these Haskell modules:

Operators

F.op.land(a, b)             -- a and b
F.op.lor(a, b)              -- a or b
F.op.lxor(a, b)             -- (not a and b) or (not b and a)
F.op.lnot(a)                -- not a

Logical operators

F.op.band(a, b)             -- a & b
F.op.bor(a, b)              -- a | b
F.op.bxor(a, b)             -- a ~ b
F.op.bnot(a)                -- ~a
F.op.shl(a, b)              -- a << b
F.op.shr(a, b)              -- a >> b

Bitwise operators

F.op.eq(a, b)               -- a == b
F.op.ne(a, b)               -- a ~= b
F.op.lt(a, b)               -- a < b
F.op.le(a, b)               -- a <= b
F.op.gt(a, b)               -- a > b
F.op.ge(a, b)               -- a >= b

Comparison operators

F.op.ueq(a, b)              -- a == b  (†)
F.op.une(a, b)              -- a ~= b  (†)
F.op.ult(a, b)              -- a < b   (†)
F.op.ule(a, b)              -- a <= b  (†)
F.op.ugt(a, b)              -- a > b   (†)
F.op.uge(a, b)              -- a >= b  (†)

Universal comparison operators ((†) comparisons on elements of possibly different Lua types)

F.op.add(a, b)              -- a + b
F.op.sub(a, b)              -- a - b
F.op.mul(a, b)              -- a * b
F.op.div(a, b)              -- a / b
F.op.idiv(a, b)             -- a // b
F.op.mod(a, b)              -- a % b
F.op.neg(a)                 -- -a
F.op.pow(a, b)              -- a ^ b

Arithmetic operators

F.op.concat(a, b)           -- a .. b
F.op.len(a)                 -- #a

String/list operators

Basic data types

F.maybe(b, f, a)

Returns f(a) if f(a) is not nil, otherwise b

F.default(def, x)

Returns x if x is not nil, otherwise def

F.case(x) {
    { t1, v1 },
    ...
    { tn, vn }
}

returns the first vi such that ti == x. If ti is a function, it is applied to x and the test becomes ti(x) == x. If vi is a function, the value returned by F.case is vi(x).

F.when {
    { t1, v1 },
    ...
    { tn, vn }
}

returns the first vi such that ti is true. If ti is a function, the test becomes ti(). If vi is a function, the value returned by F.when is vi().

F.otherwise

F.otherwise is used with F.case and F.when to add a default branch.

Tuples

F.fst(ab)

Extract the first component of a list.

F.snd(ab)

Extract the second component of a list.

F.thd(ab)

Extract the third component of a list.

Basic type classes

F.comp(a, b)

Comparison (-1, 0, 1)

F.ucomp(a, b)

Comparison (-1, 0, 1) (using universal comparison operators)

F.max(a, b)

max(a, b)

F.min(a, b)

min(a, b)

F.succ(a)

a + 1

F.pred(a)

a - 1

Numbers

Numeric type classes

F.negate(a)

-a

F.abs(a)

-a

F.signum(a)

sign of a (-1, 0 or +1)

F.quot(a, b)

integer division truncated toward zero

F.rem(a, b)

integer remainder satisfying quot(a, b)*b + rem(a, b) == a, 0 <= rem(a, b) < abs(b)

F.quot_rem(a, b)

simultaneous quot and rem

F.div(a, b)

integer division truncated toward negative infinity

F.mod(a, b)

integer modulus satisfying div(a, b)*b + mod(a, b) == a, 0 <= mod(a, b) < abs(b)

F.div_mod(a, b)

simultaneous div and mod

F.recip(a)

Reciprocal fraction.

F.pi
F.exp(x)
F.log(x), F.log(x, base)
F.sqrt(x)
F.sin(x)
F.cos(x)
F.tan(x)
F.asin(x)
F.acos(x)
F.atan(x)
F.sinh(x)
F.cosh(x)
F.tanh(x)
F.asinh(x)
F.acosh(x)
F.atanh(x)

standard math constants and functions

F.proper_fraction(x)

returns a pair (n,f) such that x = n+f, and:

F.truncate(x)

returns the integer nearest x between zero and x.

F.round(x)

returns the nearest integer to x; the even integer if x is equidistant between two integers

F.ceiling(x)

returns the least integer not less than x.

F.floor(x)

returns the greatest integer not greater than x.

F.is_nan(x)

True if the argument is an IEEE “not-a-number” (NaN) value

F.is_infinite(x)

True if the argument is an IEEE infinity or negative infinity

F.is_normalized(x)

True if the argument is represented in normalized format

F.is_denormalized(x)

True if the argument is too small to be represented in normalized format

F.is_negative_zero(x)

True if the argument is an IEEE negative zero

F.atan2(y, x)

computes the angle (from the positive x-axis) of the vector from the origin to the point (x,y).

F.even(n)
F.odd(n)

parity check

F.gcd(a, b)
F.lcm(a, b)

Greatest Common Divisor and Least Common Multiple of a and b.

Miscellaneous functions

F.id(x)

Identity function.

F.const(...)

Constant function. const(…)(y) always returns …

F.compose(fs)

Function composition. compose{f, g, h}(…) returns f(g(h(…))).

F.flip(f)

takes its (first) two arguments in the reverse order of f.

F.curry(f)

curry(f)(x)(…) calls f(x, …)

F.uncurry(f)

uncurry(f)(x, …) calls f(x)(…)

F.partial(f, ...)

F.partial(f, xs)(ys) calls f(xs..ys)

F.call(f, ...)

calls f(...)

F.until_(p, f, x)

yields the result of applying f until p holds.

F.error(message, level)
F.error_without_stack_trace(message, level)

stops execution and displays an error message (with out without a stack trace).

F.prefix(pre)

returns a function that adds the prefix pre to a string

F.suffix(suf)

returns a function that adds the suffix suf to a string

F.memo1(f)

returns a memoized function (one argument)

Converting to and from string

Converting to string

F.show(x, [opt])

Convert x to a string

opt is an optional table that customizes the output string:

Converting from string

F.read(s)

Convert s to a Lua value

Table construction

F(t)

F(t) sets the metatable of t and returns t. Most of the functions of F will be methods of t.

Note that other F functions that return tables actually return F tables.

F.clone(t)
f:clone()

F.clone(t) clones the first level of t.

F.deep_clone(t)
f:deep_clone()

F.deep_clone(t) recursively clones t.

F.rep(n, x)

Returns a list of length n with x the value of every element.

F.range(a)
F.range(a, b)
F.range(a, b, step)

Returns a range [1, a], [a, b] or [a, a+step, … b]

F.concat{xs1, xs2, ... xsn}
F{xs1, xs2, ... xsn}:concat()
xs1 .. xs2

concatenates lists

F.flatten(xs)
xs:flatten()

Returns a flat list with all elements recursively taken from xs

F.str({s1, s2, ... sn}, [separator])
ss:str([separator])

concatenates strings (separated with an optional separator) and returns a string.

F.from_set(f, ks)
ks:from_set(f)

Build a map from a set of keys and a function which for each key computes its value.

F.from_list(kvs)
kvs:from_list()

Build a map from a list of key/value pairs.

Iterators

F.pairs(t, [comp_lt])
t:pairs([comp_lt])
F.ipairs(xs, [comp_lt])
xs:ipairs([comp_lt])

behave like the Lua pairs and ipairs iterators. F.pairs sorts keys using the function comp_lt or the universal <= operator (F.op.ult).

F.keys(t, [comp_lt])
t:keys([comp_lt])
F.values(t, [comp_lt])
t:values([comp_lt])
F.items(t, [comp_lt])
t:items([comp_lt])

returns the list of keys, values or pairs of keys/values (same order than F.pairs).

Table extraction

F.head(xs)
xs:head()
F.last(xs)
xs:last()

returns the first element (head) or the last element (last) of a list.

F.tail(xs)
xs:tail()
F.init(xs)
xs:init()

returns the list after the head (tail) or before the last element (init).

F.uncons(xs)
xs:uncons()

returns the head and the tail of a list.

F.unpack(xs, [ i, [j] ])
xs:unpack([ i, [j] ])

returns the elements of xs between indices i and j

F.take(n, xs)
xs:take(n)

Returns the prefix of xs of length n.

F.drop(n, xs)
xs:drop(n)

Returns the suffix of xs after the first n elements.

F.split_at(n, xs)
xs:split_at(n)

Returns a tuple where first element is xs prefix of length n and second element is the remainder of the list.

F.take_while(p, xs)
xs:take_while(p)

Returns the longest prefix (possibly empty) of xs of elements that satisfy p.

F.drop_while(p, xs)
xs:drop_while(p)

Returns the suffix remaining after take_while(p, xs).

F.drop_while_end(p, xs)
xs:drop_while_end(p)

Drops the largest suffix of a list in which the given predicate holds for all elements.

F.span(p, xs)
xs:span(p)

Returns a tuple where first element is longest prefix (possibly empty) of xs of elements that satisfy p and second element is the remainder of the list.

F.break_(p, xs)
xs:break_(p)

Returns a tuple where first element is longest prefix (possibly empty) of xs of elements that do not satisfy p and second element is the remainder of the list.

F.strip_prefix(prefix, xs)
xs:strip_prefix(prefix)

Drops the given prefix from a list.

F.strip_suffix(suffix, xs)
xs:strip_suffix(suffix)

Drops the given suffix from a list.

F.group(xs, [comp_eq])
xs:group([comp_eq])

Returns a list of lists such that the concatenation of the result is equal to the argument. Moreover, each sublist in the result contains only equal elements.

F.inits(xs)
xs:inits()

Returns all initial segments of the argument, shortest first.

F.tails(xs)
xs:tails()

Returns all final segments of the argument, longest first.

Predicates

F.is_prefix_of(prefix, xs)
prefix:is_prefix_of(xs)

Returns true iff xs starts with prefix

F.is_suffix_of(suffix, xs)
suffix:is_suffix_of(xs)

Returns true iff xs ends with suffix

F.is_infix_of(infix, xs)
infix:is_infix_of(xs)

Returns true iff xs caontains infix

F.has_prefix(xs, prefix)
xs:has_prefix(prefix)

Returns true iff xs starts with prefix

F.has_suffix(xs, suffix)
xs:has_suffix(suffix)

Returns true iff xs ends with suffix

F.has_infix(xs, infix)
xs:has_infix(infix)

Returns true iff xs caontains infix

F.is_subsequence_of(seq, xs)
seq:is_subsequence_of(xs)

Returns true if all the elements of the first list occur, in order, in the second. The elements do not have to occur consecutively.

F.is_submap_of(t1, t2)
t1:is_submap_of(t2)

returns true if all keys in t1 are in t2.

F.map_contains(t1, t2, [comp_eq])
t1:map_contains(t2, [comp_eq])

returns true if all keys in t2 are in t1.

F.is_proper_submap_of(t1, t2)
t1:is_proper_submap_of(t2)

returns true if all keys in t1 are in t2 and t1 keys and t2 keys are different.

F.map_strictly_contains(t1, t2, [comp_eq])
t1:map_strictly_contains(t2, [comp_eq])

returns true if all keys in t2 are in t1.

Searching

F.elem(x, xs, [comp_eq])
xs:elem(x, [comp_eq])

Returns true if x occurs in xs (using the optional comp_eq function).

F.not_elem(x, xs, [comp_eq])
xs:not_elem(x, [comp_eq])

Returns true if x does not occur in xs (using the optional comp_eq function).

F.lookup(x, xys, [comp_eq])
xys:lookup(x, [comp_eq])

Looks up a key x in an association list (using the optional comp_eq function).

F.find(p, xs)
xs:find(p)

Returns the leftmost element of xs matching the predicate p.

F.filter(p, xs)
xs:filter(p)

Returns the list of those elements that satisfy the predicate p(x).

F.filteri(p, xs)
xs:filteri(p)

Returns the list of those elements that satisfy the predicate p(i, x).

F.filtert(p, t)
t:filtert(p)

Returns the table of those values that satisfy the predicate p(v).

F.filterk(p, t)
t:filterk(p)

Returns the table of those values that satisfy the predicate p(k, v).

F.restrictKeys(t, ks)
t:restrict_keys(ks)

Restrict a map to only those keys found in a list.

F.without_keys(t, ks)
t:without_keys(ks)

Restrict a map to only those keys found in a list.

F.partition(p, xs)
xs:partition(p)

Returns the pair of lists of elements which do and do not satisfy the predicate, respectively.

F.table_partition(p, t)
t:table_partition(p)

Partition the map according to a predicate. The first map contains all elements that satisfy the predicate, the second all elements that fail the predicate.

F.table_partition_with_key(p, t)
t:table_partition_with_key(p)

Partition the map according to a predicate. The first map contains all elements that satisfy the predicate, the second all elements that fail the predicate.

F.elemIndex(x, xs)
xs:elem_index(x)

Returns the index of the first element in the given list which is equal to the query element.

F.elem_indices(x, xs)
xs:elem_indices(x)

Returns the indices of all elements equal to the query element, in ascending order.

F.find_index(p, xs)
xs:find_index(p)

Returns the index of the first element in the list satisfying the predicate.

F.find_indices(p, xs)
xs:find_indices(p)

Returns the indices of all elements satisfying the predicate, in ascending order.

Table size

F.null(xs)
xs:null()
F.null(t)
t:null("t")

checks wether a list or a table is empty.

#xs
F.length(xs)
xs:length()

Length of a list.

F.size(t)
t:size()

Size of a table (number of (key, value) pairs).

Table transformations

F.map(f, xs)
xs:map(f)

maps f to the elements of xs and returns {f(xs[1]), f(xs[2]), ...}

F.mapi(f, xs)
xs:mapi(f)

maps f to the elements of xs and returns {f(1, xs[1]), f(2, xs[2]), ...}

F.mapt(f, t)
t:mapt(f)

maps f to the values of t and returns {k1=f(t[k1]), k2=f(t[k2]), ...}

F.mapk(f, t)
t:mapk(f)

maps f to the values of t and returns {k1=f(k1, t[k1]), k2=f(k2, t[k2]), ...}

F.reverse(xs)
xs:reverse()

reverses the order of a list

F.transpose(xss)
xss:transpose()

Transposes the rows and columns of its argument.

F.update(f, k, t)
t:update(f, k)

Updates the value x at k. If f(x) is nil, the element is deleted. Otherwise the key k is bound to the value f(x).

Warning: in-place modification.

F.updatek(f, k, t)
t:updatek(f, k)

Updates the value x at k. If f(k, x) is nil, the element is deleted. Otherwise the key k is bound to the value f(k, x).

Warning: in-place modification.

Table reductions (folds)

F.fold(f, x, xs)
xs:fold(f, x)

Left-associative fold of a list (f(...f(f(x, xs[1]), xs[2]), ...)).

F.foldi(f, x, xs)
xs:foldi(f, x)

Left-associative fold of a list (f(...f(f(x, 1, xs[1]), 2, xs[2]), ...)).

F.fold1(f, xs)
xs:fold1(f)

Left-associative fold of a list, the initial value is xs[1].

F.foldt(f, x, t)
t:foldt(f, x)

Left-associative fold of a table (in the order given by F.pairs).

F.foldk(f, x, t)
t:foldk(f, x)

Left-associative fold of a table (in the order given by F.pairs).

F.land(bs)
bs:land()

Returns the conjunction of a container of booleans.

F.lor(bs)
bs:lor()

Returns the disjunction of a container of booleans.

F.any(p, xs)
xs:any(p)

Determines whether any element of the structure satisfies the predicate.

F.all(p, xs)
xs:all(p)

Determines whether all elements of the structure satisfy the predicate.

F.sum(xs)
xs:sum()

Returns the sum of the numbers of a structure.

F.product(xs)
xs:product()

Returns the product of the numbers of a structure.

F.maximum(xs, [comp_lt])
xs:maximum([comp_lt])

The largest element of a non-empty structure, according to the optional comparison function.

F.minimum(xs, [comp_lt])
xs:minimum([comp_lt])

The least element of a non-empty structure, according to the optional comparison function.

F.scan(f, x, xs)
xs:scan(f, x)

Similar to fold but returns a list of successive reduced values from the left.

F.scan1(f, xs)
xs:scan1(f)

Like scan but the initial value is xs[1].

F.concat_map(f, xs)
xs:concat_map(f)

Map a function over all the elements of a container and concatenate the resulting lists.

Zipping

F.zip(xss, [f])
xss:zip([f])

zip takes a list of lists and returns a list of corresponding tuples.

F.unzip(xss)
xss:unzip()

Transforms a list of n-tuples into n lists

F.zip_with(f, xss)
xss:zip_with(f)

zip_with generalises zip by zipping with the function given as the first argument, instead of a tupling function.

Set operations

F.nub(xs, [comp_eq])
xs:nub([comp_eq])

Removes duplicate elements from a list. In particular, it keeps only the first occurrence of each element, according to the optional comp_eq function.

F.delete(x, xs, [comp_eq])
xs:delete(x, [comp_eq])

Removes the first occurrence of x from its list argument, according to the optional comp_eq function.

F.difference(xs, ys, [comp_eq])
xs:difference(ys, [comp_eq])

Returns the list difference. In difference(xs, ys) the first occurrence of each element of ys in turn (if any) has been removed from xs, according to the optional comp_eq function.

F.union(xs, ys, [comp_eq])
xs:union(ys, [comp_eq])

Returns the list union of the two lists. Duplicates, and elements of the first list, are removed from the the second list, but if the first list contains duplicates, so will the result, according to the optional comp_eq function.

F.intersection(xs, ys, [comp_eq])
xs:intersection(ys, [comp_eq])

Returns the list intersection of two lists. If the first list contains duplicates, so will the result, according to the optional comp_eq function.

Table operations

F.merge(ts)
ts:merge()
F.table_union(ts)
ts:table_union()

Right-biased union of tables.

F.merge_with(f, ts)
ts:merge_with(f)
F.table_union_with(f, ts)
ts:table_union_with(f)

Right-biased union of tables with a combining function.

F.merge_with_key(f, ts)
ts:merge_with_key(f)
F.table_union_with_key(f, ts)
ts:table_union_with_key(f)

Right-biased union of tables with a combining function.

F.table_difference(t1, t2)
t1:table_difference(t2)

Difference of two maps. Return elements of the first map not existing in the second map.

F.table_difference_with(f, t1, t2)
t1:table_difference_with(f, t2)

Difference with a combining function. When two equal keys are encountered, the combining function is applied to the values of these keys.

F.table_difference_with_key(f, t1, t2)
t1:table_difference_with_key(f, t2)

Union with a combining function.

F.table_intersection(t1, t2)
t1:table_intersection(t2)

Intersection of two maps. Return data in the first map for the keys existing in both maps.

F.table_intersection_with(f, t1, t2)
t1:table_intersection_with(f, t2)

Difference with a combining function. When two equal keys are encountered, the combining function is applied to the values of these keys.

F.table_intersection_with_key(f, t1, t2)
t1:table_intersection_with_key(f, t2)

Union with a combining function.

F.disjoint(t1, t2)
t1:disjoint(t2)

Check the intersection of two maps is empty.

F.table_compose(t1, t2)
t1:table_compose(t2)

Relate the keys of one map to the values of the other, by using the values of the former as keys for lookups in the latter.

F.Nil

F.Nil is a singleton used to represent nil (see F.patch)

F.patch(t1, t2)
t1:patch(t2)

returns a copy of t1 where some fields are replaced by values from t2. Keys not found in t2 are not modified. If t2 contains F.Nil then the corresponding key is removed from t1. Unmodified subtrees are not cloned but returned as is (common subtrees are shared).

Ordered lists

F.sort(xs, [comp_lt])
xs:sort([comp_lt])

Sorts xs from lowest to highest, according to the optional comp_lt function.

F.sort_on(f, xs, [comp_lt])
xs:sort_on(f, [comp_lt])

Sorts a list by comparing the results of a key function applied to each element, according to the optional comp_lt function.

F.insert(x, xs, [comp_lt])
xs:insert(x, [comp_lt])

Inserts the element into the list at the first position where it is less than or equal to the next element, according to the optional comp_lt function.

Miscellaneous functions

F.subsequences(xs)
xs:subsequences()

Returns the list of all subsequences of the argument.

F.permutations(xs)
xs:permutations()

Returns the list of all permutations of the argument.

Functions on strings

string.chars(s, i, j)
s:chars(i, j)

Returns the list of characters of a string between indices i and j, or the whole string if i and j are not provided.

string.head(s)
s:head()

Extract the first element of a string.

sting.last(s)
s:last()

Extract the last element of a string.

string.tail(s)
s:tail()

Extract the elements after the head of a string

string.init(s)
s:init()

Return all the elements of a string except the last one.

string.uncons(s)
s:uncons()

Decompose a string into its head and tail.

string.null(s)
s:null()

Test whether the string is empty.

string.length(s)
s:length()

Returns the length of a string.

string.intersperse(c, s)
c:intersperse(s)

Intersperses a element c between the elements of s.

string.intercalate(s, ss)
s:intercalate(ss)

Inserts the string s in between the strings in ss and concatenates the result.

string.subsequences(s)
s:subsequences()

Returns the list of all subsequences of the argument.

string.permutations(s)
s:permutations()

Returns the list of all permutations of the argument.

string.take(s, n)
s:take(n)

Returns the prefix of s of length n.

string.drop(s, n)
s:drop(n)

Returns the suffix of s after the first n elements.

string.split_at(s, n)
s:split_at(n)

Returns a tuple where first element is s prefix of length n and second element is the remainder of the string.

string.take_while(s, p)
s:take_while(p)

Returns the longest prefix (possibly empty) of s of elements that satisfy p.

string.dropWhile(s, p)
s:dropWhile(p)

Returns the suffix remaining after s:take_while(p).

string.drop_while_end(s, p)
s:drop_while_end(p)

Drops the largest suffix of a string in which the given predicate holds for all elements.

string.strip_prefix(s, prefix)
s:strip_prefix(prefix)

Drops the given prefix from a string.

string.strip_suffix(s, suffix)
s:strip_suffix(suffix)

Drops the given suffix from a string.

string.inits(s)
s:inits()

Returns all initial segments of the argument, shortest first.

string.tails(s)
s:tails()

Returns all final segments of the argument, longest first.

string.is_prefix_of(prefix, s)
prefix:is_prefix_of(s)

Returns true iff the first string is a prefix of the second.

string.has_prefix(s, prefix)
s:has_prefix(prefix)

Returns true iff the second string is a prefix of the first.

string.is_suffix_of(suffix, s)
suffix:is_suffix_of(s)

Returns true iff the first string is a suffix of the second.

string.has_suffix(s, suffix)
s:has_suffix(suffix)

Returns true iff the second string is a suffix of the first.

string.is_infix_of(infix, s)
infix:is_infix_of(s)

Returns true iff the first string is contained, wholly and intact, anywhere within the second.

string.has_infix(s, infix, s)
s:has_infix(infix)

Returns true iff the second string is contained, wholly and intact, anywhere within the first.

string.split(s, sep, maxsplit, plain)
s:split(sep, maxsplit, plain)

Splits a string s around the separator sep. maxsplit is the maximal number of separators. If plain is true then the separator is a plain string instead of a Lua string pattern.

string.lines(s)
s:lines()

Splits the argument into a list of lines stripped of their terminating \n characters.

string.words(s)
s:words()

Breaks a string up into a list of words, which were delimited by white space.

F.unlines(xs)
xs:unlines()

Appends a \n character to each input string, then concatenates the results.

string.unwords(xs)
xs:unwords()

Joins words with separating spaces.

string.ltrim(s)
s:ltrim()

Removes heading spaces

string.rtrim(s)
s:rtrim()

Removes trailing spaces

string.trim(s)
s:trim()

Removes heading and trailing spaces

string.cap(s)
s:cap()

Capitalizes a string. The first character is upper case, other are lower case.

String interpolation

string.I(s, t)
s:I(t)

interpolates expressions in the string s by replacing nil with the value of ... in the environment defined by the table t.

F.I(t)

returns a string interpolator that replaces nil with 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.

Shell

local sh = require "sh"
sh.run(...)

Runs the command ... with os.execute.

sh.read(...)

Runs the command ... with io.popen. When sh.read succeeds, it returns the content of stdout. Otherwise it returns the error identified by io.popen.

sh.write(...)(data)

Runs the command ... with io.popen and feeds stdin with data. When sh.read succeeds, it returns the content of stdout. Otherwise it returns the error identified by io.popen.

File System

fs is a File System module. It provides functions to handle files and directory in a portable way.

local fs = require "fs"
fs.getcwd()

returns the current working directory.

fs.dir([path])

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

fs.remove(name)

deletes the file name.

fs.rename(old_name, new_name)

renames the file old_name to new_name.

fs.copy(source_name, target_name)

copies file source_name to target_name. The attributes and times are preserved.

fs.mkdir(path)

creates a new directory path.

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.splitext(path)

return the name without the extension and the extension.

fs.realpath(path)

return the resolved path name 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). If a component is absolute, the previous components are removed.

fs.is_file(name)

returns true if name is a file.

fs.is_dir(name)

returns true if name is a directory.

fs.findpath(name)

returns the full path of name if name is found in $PATH or nil.

fs.mkdirs(path)

creates a new directory path and its parent directories.

fs.mv(old_name, new_name)

alias for fs.rename(old_name, new_name).

fs.rm(name)

alias for fs.remove(name).

fs.rmdir(path, [params])

deletes the directory path and its content recursively.

fs.walk([path], [{reverse=true|false, links=true|false, cross=true|false}])

returns a list listing directory and file names in path and its subdirectories (the default path is the current directory).

Options:

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.read(filename)

returns the content of the text file filename.

fs.write(filename, ...)

write ... to the text file filename.

fs.read_bin(filename)

returns the content of the binary file filename.

fs.write_bin(filename, ...)

write ... to the binary file filename.

sys: System module

local sys = require "sys"
sys.os

"linux", "macos" or "windows".

sys.arch

"x86_64", "i386" or "aarch64".

sys.abi

"lua".

sys.type

"lua"

ps: Process management module

local ps = require "ps"
ps.sleep(n)

sleeps for n seconds.

ps.time()

returns the current time in seconds

ps.profile(func)

executes func and returns its execution time in seconds.