Lil Terminal is a command-line interface for the Lil programming language, allowing easy experimentation outside of Decker. Lilt also includes bindings for basic CLI and filesystem IO, making it potentially usable for shell scripting and other applications.


The source code for Lilt is available On GitHub.

Lilt depends upon the C standard library and some POSIX extensions. It should work on OSX or most Linux distros. To build and install Lilt, run the included make script. By default, a binary is installed in /usr/local/bin.

make lilt && make install

Invoking Lilt

$ lilt [FILE.lil...] [-e EXPR...]
 if present, execute a FILE and exit
 -e : evaluate EXPR and exit
 -h : display this information

Executing a FILE or EXPR argument will not automatically produce any output. Use show[] or print[] to produce results on stdout:

$ lilt -e "show[100+range 5]"

$ lilt -e "print[sys.version]"

If a FILE or EXPR argument has not been provided, Lilt will run in interactive "REPL" mode, which can be exited with Ctrl+C or the exit[] function.

$ lilt

For convenience, after each line is executed at the REPL, the result will be stored in a variable named _:


You can write reasonably portable shell scripts by starting a file with a "shebang" something like:

#!/usr/bin/env lilt

If an environment variable named LIL_HOME is set, Lilt will search that directory path at startup, executing any .lil files. These could in turn easily load datasets or other useful definitions every time you open a REPL. Startup scripts are always loaded prior to executing FILE or EXPR arguments.

Global Variables

Name Description
args List of CLI arguments to Lilt as strings.
env Dictionary of POSIX Environment variables.
sys An Interface which exposes information about the Lilt runtime.
rtext An Interface with routines for working with rich text.
bits An Interface with routines for bit-wise manipulation of numbers.
pi The ratio of a circle's circumference to its diameter. Roughly 3.141.
e Euler's number; the base of the natural logarithm. Roughly 2.718.
colors A dictionary of named pattern indices.

Built-in Functions

Name Description Purpose
input[x] Read a line from stdin as a string, optionally displaying x as if with print[], without the newline. Gets 0 on EOF. Console
show[x...] Print a human-comprehensible representation of the value x to stdout followed by a newline, and return x. Console
print[x...] Print a string x to stdout followed by a newline. If more args are provided, format all but the first using x.(0) Console
error[x...] Print a string x to stderr followed by a newline. If more args are provided, format all but the first using x.(0) Console
dir[x] List the content of a directory as a table.(1) Files
path[x y] Canonical path x (joined with y, if given) via realpath(). Files
read[x hint] Read a file x using hint as necessary to control its interpretation.(2) Files
write[x y] Write a value y to a file x. Returns 1 on success.(3) Files
exit[x] Stop execution with exit code x. System
shell[x] Execute string x as a shell command and block for its completion.(4) System
eval[x y z] Parse and execute a string x as a Lil program, using any variable bindings in dictionary y.(5) System
import[x] Execute a .lil script x in an isolated scope and return a dictionary of definitions made within that script. System
random[x y] Choose y random elements from x. In Lilt, sys.seed is always pre-initialized to a constant. System
readcsv[x y d] Turn a RFC-4180 CSV string x into a Lil table with column spec y.(5) Data
writecsv[x y d] Turn a Lil table x into a CSV string with column spec y.(5) Data
readxml[x] Turn a useful subset of XML/HTML into a Lil structure.(5) Data
writexml[x fmt] Turn a Lil structure x into an XML string, formatted with whitespace if fmt is truthy.(5) Data
readdeck[x] Produce a deck interface from a file at path x. If no path is given, produce a new deck from scratch. Decker
writedeck[x y] Serialize a deck interface y to a file at path x. Returns 1 on success.(6) Decker
array[x y] Create a new array with size x and cast string y, or decode an encoded array string x. Decker
image[x] Create a new image interface with size x ((width,height)) or decode an encoded image string. Decker
sound[x] Create a new sound interface with size x (sample count) or decode an encoded sound string. Decker

0) If print[] or error[] are given a single array interface as an argument, the raw bytes of that array will be sent to stdout or stderr, respectively, with no trailing newline added. In this way it is possible to print characters which do not have a valid representation as Lil strings, like Unicode block characters.

1) dir[] of a file results in an empty table. Directory tables contain:

2) read[x hint] recognizes several types of file by extension and will interpret each appropriately:

There are several possible hint arguments to control the interpretation of colors in an image:

The "frames" or "gray_frames" hints will cause read[] of a GIF to return a dictionary containing the following keys:

If an image contains transparent pixels, they will be read as pattern 0.

The WAV file format is much more complex than one might imagine. For this reason, and in order to avoid drawing in large dependencies, read[] in Lilt accepts only a very specific subset of valid WAV files corresponding to the output of write[]: monophonic, 8khz, with 8-bit unsigned PCM samples and no optional headers. Any other format (or an altogether invalid audio file) will be read as a sound with a size of 0. For reference, you can convert nearly any audio file into a compatible format using ffmpeg like so:

ffmpeg -i input.mp3 -bitexact -map_metadata -1 -ac 1 -ar 8000 -acodec pcm_u8 output.wav

3) write[] recognizes several types of Lil value and will serialize each appropriately:

4) shell[] returns a dictionary containing:

5) See the Decker Manual for details of eval[], readcsv[], writecsv[], readxml[], and writexml[].

6) If the path given to writedeck[] ends in a .html suffix, the deck will be written as a "standalone" deck with a bundled HTML+JS runtime. Otherwise, the deck will be written as a "bare" deck, which is smaller.

Working With Decks

The readdeck[] and writedeck[] functions allow Lilt to operate on Decker documents. Lilt can load, create, and manipulate multiple decks simultaneously, providing options for automated testing, data import/export, accessibility, and interacting with other technology from outside the Decker ecosystem.

Just as in Decker, you can simulate "injecting" events into widgets, cards, or the deck with the x.event[name args...] function they provide, running the appropriate scripts to completion and producing any appropriate side-effects on the deck. For example, clicking on the first widget on the active card:

(first d.card.widgets).event["click"]