This is Maui, the Mau Independent Fabricator.

Fabricator is a literate programming engine with an unobtrusive, wiki-like syntax. Modern Fabricator lives normally inside Mau, a PIM-oriented wiki engine, but Maui makes it available through a command line interface or a Ruby API without requiring a full Mau installation.

Inline markup

Fabricator’s markup can be viewed as a particular wiki markup with literate programming extensions. Here are the inline markup elements:

  • Bold text is marked by surrounding stars: [[foo]]

  • /Italic/ text is marked by surrounding slashes: [[/foo/]]

  • Underlined text is marked by surrounding underscores:

    [foo]
  • <Links|www.techterms.com/definition/hyperlink> are marked by surrounding brokets: [[<link face|URL>]]. Note that the order of the aspects of the link matches that commonly used in paper encyclopedias rather than that used HTML.

Narrative structure

/Paragraphs/ are separated from each other and other input by blank lines.

Two adjacent blank lines separate /sections/.

An indented block of text will be treated as a piece of /sample code/, like this:

These lines were indented.  Note that a block can contain
blank lines,

but only one at a time.  Two consecutive blank lines would be
parsed as a section break, and the new section would contain a
new block.

Like this.

Items in a /bullet list/ are marked by leading dash and space, and can be nested:

- 1
  - 1.1
  - 1.2
    - 1.2.1
- 2

will produce:

  • 1

    • 1.1

    • 1.2

      • 1.2.1

  • 2

A document can be divided into /chapters/, /subchapters/, and /subsubchapters/ by /titles/. A title should be separated with preceding and following with a blank line and is marked, correspondingly, with a leading [[==]], [[===]], or [[====]] together with a following separating space.

Furthermore, the document structure can be presented with the use of /rubrics/, which correspond to Knuth WEB’s /starred chunks/. A rubric is marked similarly to a title except with a leading [[*]] instead of equal signs. The star must be separated from the rubric’s name with a space lest the parser think it’s just a bold text marker. Because rubrics are, if a paragraph follows, embedded into the paragraph by Fabricator’s weaving subsystem, it’s a good idea to formulate rubric names as full sentences, together with a trailing period or other punctuation.

Chunks and transclusion

Each section can contain one or more /chunks/, with the following notation:

<< Chunk name >>:
  Chunk content, possibly on many lines,
  including single blank lines.

Note that the declaration must be unindented, and the chunk’s content must be indented.

Some programming languages make use of [[<<]] and [[>>]] for other purposes. In order to make the plain Fabricator input easy to read, no escaping for double brokets is provided. You’ll have to structure the input in such a way as to avoid false transclusion references.

A chunk can be marked as a /root/ chunk by prepending a

[.file]

or [[.script]] to directive, like this:

<< .script hello.rb >>:
  #! /usr/bin/ruby -rubygems

  puts "<< Friendly, familiar greeting >>"

The (mechanical) power of literate programming comes from /transclusion/, which is notated by adding the target chunk’s name into another chunk, as seen above.

<< Friendly, familiar greeting >>:
  Hello, world!

It is permitted to define multiple chunks with the same name. When the name is referred in a transclusion, all these chunks will then be processed, separated with a single blank line. In cases when the separating blank line is undesirable, it can be suppressed by the [[.dense]] directive:

@cat_names = qw(
  << The names of cats .dense >>
)

Normally, Fabricator obeys indentation in a nested manner. In certain cases — most importantly, the ‘here-documents’ in shell scripts and languages borrowing their notation —, you may want to suppress this. This is achieved by the

[.clearindent]

directive:

<< ... >>:
  module Beast
    DATA = {
      :cows => << .clearindent Cows heredoc >>
    }

<< Cows heredoc >>:
  << 'END-OF-COWS',
  << Cows >>
  END-OF-COWS

The extra wrapper, [[<< Cows heredoc >>]], serves two purposes in this example:

  • It ensures that even the first line of the main transcludee, [[<< Cows >>]], follows a linebreak within the effect zone of [[.clearindent]]. This is necessary because the directive can only clear indentations that exist, and without a linebreak there is no indentation to suppress.

  • It also ensures that the terminating [[END-OF-COWS]] is flushed left together with the cows’ data, for otherwise the target language might not recognise it as the here-doc’s terminator.

It’s often useful to intersperse many chunks of the same name with a narrative explaining the actions taken. Mau facilitates this via /diversions/. The notation for a diversion is a chunk header without the chunk; the subsequent indented blocks — which would otherwise be interpreted as example code — are then treated as chunks of this name. A diversion is effect until another diversion replaces it or until a title begins a new narrative unit of the document. Note that a rubric does not cancel a diversion’s effect.

Postprocessing

Fabricator provides experimental support for /postprocessing/ text constructed using the standard LP transclusion mechanism. The notation for this is subject to change in future versions, and the available postprocessors are environment-dependent.

In the current version, Maui defines two postprocessors related to <Sass|sass-lang.com>, the preprocessor for CSS. These are [[|scss->css]] and [[|sass->css]], and they are invoked by attaching their names to the transclusion notation like this:

<< ... >>:
  ...
  puts << EOS
    Content-type: text/css; charset=UTF-8

    << stylesheet.sass |sass->css >>
  EOS
  ...

<< stylesheet.sass >>:
  .footer
    font-size: smaller

  ...

Invocation

Last but not least, the way to run [[maui]] goes like this:

$ maui foo.fab

By default, this outputs warnings about probable problems with the input to the standard error stream and both weaves the input into [[foo.html]] and [[foo.ctxt]] as well as tangles all the defined roots. It’s also possible to specify that only some of these files are to be written out, like this:

$ maui foo.fab hello.c foo.html

Note, however, that Fabricator necessarily tangles everything (into core memory) defined in the [[fab]] file while processing it, so such a command will not take significantly less runtime than a general [[maui]] command. It only suppresses writing the unwanted results as files.