User Manual


1 Introduction

Lilac originally started out as an extension to Emacs Orgmode, to fix most of the nondeterminism issues of Orgmode's weaving (aka "export") process.

Sometime later, it was determined that Orgmode's HTML export was simply too slow (it could take 10+ seconds on large documents). This project was then rewritten in Haskell, mainly for performance but also for maintainability.

2 Major differences with vanilla Org

This section may be useful for existing Orgmode users, to see at a glance what is and isn't supported.

Orgmode is quite complex. Some features have been purposely left out, mainly for simplicity or readability.

2.1 Compilation step

Orgmode tangles and weaves from Org files directly. There is no intermediate compilation step.

Lilac adds a compilation step in order to cache some computations. Basically, an Org doc must be compiled into a Lilac Object (*.lobj), and then one or more of these objects are archived into a Lilac Archive (*.larc). It is this archive file which is then tangled or woven as needed.

Figure 1. The relationship of Lilac subcommands.
The relationship of Lilac subcommands.
fig:lilac-subcommands.pikchr
🎯 image/lilac-subcommands.pikchr

2.2 List item spacing required

List items must be indented from the main text with two leading spaces, and also must have an empty blank line. See List items.

These spacing requirements were determined to be necessary in order to maximize readability in raw Org (plaintext) form.

2.4 No #+include support

The ability to declaratively copy/paste chunks of other files is not supported, because doing so results in unreadable raw Org files (you would have to open up the linked page separately to see what was actually included).

2.5 Headings must be linked via their ID (UUID)

You cannot link to headings by their name, or by a "search" of a file path. You must instead always use UUID links.

By the same token, all documents require a UUID, so that even if you don't have a heading, other documents can still reference a named code block in your doc via the top-level document UUID.

2.6 No implicit concatenation of multiple blocks sharing the same name when tangling

Orgmode allows multiple code blocks all sharing the same #+header: :noweb-ref bar metadata, where during tangling these code blocks will be concatenated together, in the order that they appear in the doc. However, we do not allow this style for the following reasons:

  1. Orgmode doesn't have good navigation support for it. org-babel-goto-named-src-block only supports #+name: ... metadata.

  2. Using this style can lead to anonymous blocks that don't have a name. IOW, avoiding this style forces us to provide a name for all code blocks, and naming everything is generally not a bad thing, because explicit is better than implicit.

  3. The order of concatenation is implicitly hardcoded to be top-to-bottom. When we only use #+name: ..., we can choose any order we want, not just top-to-bottom (by naming the children and choosing how to order the exposition of these child blocks).

2.7 Expandable code blocks

If you set #+header: :collapsed true for a code block, it will be collapsed in the woven output. You can then click on a button to expand it. This is useful when you have source code that generates figures (drawing), and you don't want the code to steal the attention away from the figure. fig:lilac-subcommands.pikchr is an example of this.

Below is an example of a collapsed anonymous block.

2.8 Other unsupported Org features

The features below are not supported (and are not planned to be supported).

3 Comparison with other LP tools

Table 1. Comparison of LP tools.
NameWritten inWritten with LP?
(Does it use itself?)
Markup language
(Input syntax)
Tangle-able languages
LilacHaskellYesOrgmodeAny
Emacs OrgmodeEmacs LispNoOrgmodeAny
EntangledPythonNoMarkdownAny
srcweaveCommon LispNoMarkdownAny
FunnelWebCNoFunnelWeb1Any
PortiaOCamlYesAnyAny
NowebC, Awk, IconYesNoweb1Any
NuwebCYesLaTeXAny
LiterateDYesMarkdownAny
CWEBCYesTeX1C, C++

4 Basic initial setup

The main requirement is that you must author Org files, because that's what Lilac understands. Emacs is perhaps the most popular application for authoring Org files, so using Emacs is highly recommended.

Clone this repo. Install Nix and Cabal. Run cabal install --overwrite-policy=always --enable-optimization=2 to install the lilac binary to disk.

Now go to your repo where you want to use Lilac. Run

lilac init

to generate a starter Lilac.toml and index.org. This will also give you a Makefile, which you can use to run make to start tangling and weaving. You can also do watch -n 1 make to constantly run make so that you don't have to keep running it yourself.

At this point your index.org is your source of truth, so have a read through it, and adjust as needed.

5 Using Lilac as a static site generator

Because Lilac weaves output to HTML, it makes it suitable for use as a static content generator. An example is https://funloop.org/build.html (source code at https://git.sr.ht/~listx/personal-website).

There are a couple flags for the weave subcommand which are worth mentioning for using Lilac as an SSG:

6 Footnotes

1. For CWEB, it has the cweave utility which then converts this to TeX, after which it can be converted as a PDF. However, both FunnelWeb and Noweb can support any documentation language, not just TeX --- although, you are still required to use that same documentation language directly in your input file. For example, Noweb input files with the *.nw file syntax can be processed by an HTML backend if you have HTML already inside the *.nw files. In a sense both FunnelWeb and Noweb are just text preprocessors --- they have no knowledge of the underlying documentation syntax (HTML, TeX, or otherwise) used in the input files. ↑ Table 1

Page metrics

Tangled files (1)

  1. image/lilac-subcommands.pikchr

Named cells (3)

  1. Footnote (fn:web-markup)
  2. fig:lilac-subcommands
  3. fig:lilac-subcommands.pikchr