Wit

Reuse: components & multi-file

Name a piece of content once, use it by name anywhere, and change it in one place. Hash defines, at-sign uses. This page covers your own nodes, captures, the parameter forms at a glance, splitting a document across files, and the draft workflow that ties it together.

Define your own node

Three body shapes, from shortest to fullest. Each is a definition with a #; each is recalled later with a bare @name.

A single-line value — a colon, then the value on one line:

source
#year: 1965

The bridge opened in @year and has not closed since.
result

The bridge opened in 1965 and has not closed since.

That renders The bridge opened in 1965 and has not closed since.Write the year once; every mention follows the definition.

A value block, for content that runs longer — a colon, then indented lines, then a !! fence:

source
#epigraph:
The river keeps no record of the boats.
— dock proverb
!!

@epigraph
result

The river keeps no record of the boats. — dock proverb

The block form, for a wrapper whose body has a slot. Open with just the hash-name, mark the slot with ..., close with the name and a hash. The caller's body drops in where the dots are:

source
#note
@hr hr@
...
note#

@note
Deliveries pause for the harvest week.
note@
result

Deliveries pause for the harvest week.

Captures: parameters for your own node

Declare parameters between double bars on the definition, drop each one into the body with a ::field:: wrapper, and pass them at the call:

source
#chapter ||number, title||
@h2 Chapter ::number::::title:: h2@
...
chapter#

@chapter |number I| |title The Arrival|
The road climbed for an hour before the house appeared.
chapter@
result

Chapter I — The Arrival

The road climbed for an hour before the house appeared.

The call supplies I and The Arrival; the definition places them in the heading and splices the body where the dots are. One template, consistent chapters.

The capture list is optional — leave it off and Wit infers the parameters by scanning the body for ::name:: holes. A ::field:: resolves only inside a definition body; in ordinary prose it renders literally. To put a value into a sentence, define it and reference it by name instead.

Parameter forms at a glance

The same definition can be filled several ways. The governing rule: content goes in the body, metadata in parameters. Pick by shape — the full grammar is in the syntax reference.

  • Pipes|key value|; the only form that also carries a body.
  • Parens@badge(tone good); self-closing, good for one or two inline params.
  • Record{ key - value } or { key: value }; self-closing, structured, no body.
  • Form-fill — the body is the params, one key: value per line; best when there are many fields.
  • Colon-scatterkey:value tokens lifted from a one-line body, for tagging a node mid-sentence.

Every value is type-probed, so a number, record, or collection passed through any form arrives as a real typed value you can iterate or reach into.

Split a document across files

A long work does not want one enormous file. Put shared definitions — a citation format, a schema, recurring values — in their own file, and pull them in with a reference directive at the top of a line:

reference ./shared/sources.wit
reference ./shared/schema.wit

Everything defined in those files is now available here, as if typed in place. The namespace is flat and definitions hoist, so import order does not matter.

Wrap each chapter in a block definition so it emits nothing on its own, then let a thin master file place the parts in order:

reference ./chapters/one.wit
reference ./chapters/two.wit

@chapter_one chapter_one@
@chapter_two chapter_two@

Reorder the uses and the chapters reorder; add a third and it slots in. The master file is the table of contents made executable.

The draft workflow

The source is plain .wit text in a git repository, so every draft is a readable diff — you see which sentences moved, not an opaque blob:

git commit -am "Tighten the opening; cut the second epigraph"

Tag or branch a draft the way you would any code, and rebuild to share:

wit build manuscript.wit -o draft.pdf

Run wit fmt manuscript.wit -w before committing to re-indent to the real structure and keep diffs clean; it parses the file first, so it doubles as a sanity check.

See also