# ─────────────────────────────────────────────────────────────
# fig authoring dialect — kitchen-sink example
# Exercises every feature in DESIGN.md, in ONE valid document.
#
# House style (settled): depth = count of leading `>`, written as a SPACED
# run (`> >`, not `>>`) with ZERO leading indentation — the spaced run
# rebuilds the visual ruler out of the markers themselves, so no second
# (indentation) signal needs to be kept in sync by hand. Meaning lives
# entirely in the `>` count; indentation is opt-in (`fig fmt --indent`) and
# is not used here. A couple of lines below deliberately use the glued
# (`>>>`) or unspaced (`>*`) spellings on purpose, to show the parser
# accepts both — see the note in the "Sequences" section.
# ─────────────────────────────────────────────────────────────
# === Containers, assignments, prefix-count depth ===
database # container header (bare word, no `=`)
> host = localhost # database.host
> port = 5432 # database.port (bare number)
> pool # nested container header
> > size = 10 # database.pool.size
> > timeout = 30 # database.pool.timeout
# === Dotted-key flattener (flatten within one line) ===
cache
> redis.host = 127.0.0.1 # cache.redis.host (IP → string, 3 dots)
> redis.port = 6379 # cache.redis.port
# A chain of single-child maps collapses to ONE dotted line under `fig fmt`
# (the printer's mirror of the flattener above — see "What fig fmt normalizes"):
deep.nested.single.value = 42 # deep.nested.single.value
# === Root-level assignments (zero markers, zero indent) ===
version = 2 # a plain key in the root map
title = My Application # bare string, spaces and all
# === Explicit typing: key: type = value (optional) ===
server
> port: int = 8080 # annotated (vs inferred)
> name: string = My Server # bare string with spaces
> mode: enum = creative # enum atom (explicit-typing-only)
> debug: bool = false
# === Values: literal-else-string ===
values
> answer = 42 # int
> ratio = 3.14 # float
> mask = 0xFF # hex int lexeme
> big = 1.5e3 # float with exponent
> sigfig = 1.10 # float — lexeme kept VERBATIM; not collapsed to 1.1
> exp = 1e2 # float — a distinct lexeme from 100.0 (numeric identity = lexeme identity)
> enabled = true # bool (lowercase only)
> missing = null # null
> flag = "true" # STRING — quotes override the bool literal
> movie = 12 monkeys # STRING — doesn't fully parse as a number
> semver = 1.2.3 # STRING — three components, not a clean number (so it's NOT mangled)
> norway = Yes # STRING — "Yes"/"on"/"TRUE" are never bools
> zip = 007 # STRING — leading zero != number; padding kept
> team = "99" # STRING — quote to override the int literal
> class: enum = minecraft # enum atom (explicit-typing-only)
> when = 2026-07-01T12:00:00Z # datetime (RFC-3339, self-identifying)
> day = 2026-07-01 # date (RFC-3339 full-date)
> clock = 07:30:00 # time (RFC-3339 partial-time, self-identifying)
> huge: float = inf # non-finite: explicit-typing-only
> nope: float = nan # bare inf/nan would be plain strings
# === Quotes: '' raw/literal "" escaped ===
strings
> raw = 'C:\Users\me\no-escapes' # single quotes: backslashes stay literal
> esc = "line1\nline2\ttabbed" # double quotes: \n \t \uXXXX honored
> snowman = "frozen ☃"
> "my.key" = present # key with a literal dot MUST be quoted
# === Comment marker (#) only after whitespace — URLs survive ===
links
> home = https://example.com # the // in the URL stays in the value
> docs = https://example.com/docs # comment starts here; value ends before it
> api = https://example.com/v1#stable # #stable has no leading space -> kept
# === Sequences — form A2 (`*` is an anonymous positional key) ===
# The element `*` sits in key position after the run: `> *` (normalized), `>*`
# (glued) — both appear below on purpose. YAML's `-` is a hard error.
servers
> * # first element (a map): fields one level deeper
> > host = a.com
> > port = 25565
> > backends # nested list field
> > > * # spaced form (normalized)
> > > > url = x
> > > > weight = 1
> > >* # glued form — parses identically to `> > > *`
> > > > url = y
> * # second element
> > host = b.com
ports # scalar elements
> * 25565
> * 25566
> * 25567
weights # typing composes with `*`
> *: int = 1
> *: int = 2
# === Dotted section header — re-anchors baseline (like TOML [a.b.c]) ===
services.web.frontend # selects/creates services.web.frontend
> replicas = 3 # services.web.frontend.replicas (depth is RELATIVE)
> image = nginx:latest # ':' in a value is fine -> bare string
# === Appending sequence headers — primary surface for nested lists of maps ===
# `a.b[]` appends an element to sequence a.b and re-anchors; fields stay 1 deep
# no matter how deep the LIST nests. Edit-stable (append, not index). A `+`
# line re-runs the most recent zero-marker `[]` header without retyping it.
jobs.test
> runs-on = ubuntu-latest
jobs.test.steps[] # append a step, re-anchor here
> uses = actions/setup-node@v4
> with.node-version = 20
+ # same as repeating `jobs.test.steps[]`
> run = npm test
# Nested lists of lists: a non-final `[]` means "the last element" — only the
# final `[]` in the path appends. So `spec.containers[].ports[]` appends a
# port to the LAST container, and `+` re-runs the whole path.
spec.containers[] # append a container
> name = app
spec.containers[].ports[] # last container -> append a port
> containerPort = 80
+ # same path again -> another port, same container
> containerPort = 443
spec.containers[] # a second container
> name = sidecar
# === Index addressing — for editing an EXISTING element (edit-fragile) ===
clusters[0].name = alpha # clusters is a sequence; element 0
clusters[0].size = 3
clusters[1].name = beta # element 1 (skipping [1] would be an error)
clusters[1].size = 5
# === Flow mode — value starting with [ or { (fig-inline OR pasted JSON) ===
flow
> tags = [a, b, c] # fig-inline: bare strings
> audience = [friends, Adam Harris, Makena Harris] # bare values keep spaces
> point = { x = 1, y = 2 } # fig-inline object: `=` pairs, bare keys
> pasted = { "x": 1, "y": [2, 3] } # JSON object: `:` pairs, quoted keys
> jsonc = [1, 2, 3,] # JSONC: trailing comma (and `#` comments) OK
> matrix = [[1, 2], [3, 4]] # nested
> records = [{ id = 1 }, { id = 2 }]
> empty_list = [] # required spelling for an empty sequence
> empty_map = {} # required spelling for an empty map
# === Multi-line flow for long lists (the frontmatter surface) ===
# A fully flow-representable sequence with no map elements stacks one element
# per line, trailing comma, when it overflows the width budget or exceeds the
# item-count threshold (default 6) — the terse spelling for frontmatter-style
# link/tag lists. Still one assignment, so it isn't blank-line separated.
frontmatter
> tags = [
rust,
zig,
parsing,
config,
yaml,
toml,
json,
]
# === Quote-avoidance: bare beats quoted when a broken list would need quotes ===
# Flow would force quotes here (each element has a top-level comma, which
# terminates a bare flow value); the `> *` block form keeps them bare instead,
# since a comma is ordinary text in a block bare string.
random
> * test of very long things in a list to see if it works
> * hello there, this is also a long test; hopefully it works
# === Multiline strings — two flavors ===
docs
> license = ''' # '' raw/verbatim: no escapes, whitespace exact
Copyright (c) 2026
All rights reserved. \n is literal here.
'''
# ^ raw content is flush-left ON PURPOSE: in a raw block leading indentation
# becomes part of the value, so it opts out of the file's spaced-marker style.
> banner = """ # "" escaped + smart-dedent
Welcome!
Enjoy your ☃ stay.
"""
# ^ escaped content CAN be indented: the common leading indent (6 spaces here,
# including the closing """) is stripped, so the value is "Welcome!\nEnjoy…".
# === Comments ===
# A run of #-lines is one logical block comment; a printer may downgrade a
# stored block comment to exactly this shape.
logging
> # a DEPTH-PREFIXED comment (note the `>`) attaches to the next sibling
> level = info # inline comment (after whitespace)
> format = json