Fence handler reference

Per-name compile-time transliteration for triple-backtick fenced literals. Motivation and the “when does a format earn a fence” framing are in Fences; the dispatch special is compile/apply-fence.

Fence expansion

A triple-backtick fence is read into a compile/apply-fence form:

(apply-fence NAME RAW META)

NAME is the fence format, RAW is the captured body text, and META is a keyword plist carrying the payload origin (filename:, line:, col:) and the opener-line options:. The compile/apply-fence special resolves fence/<name> in the module namespace and invokes the handler as (handler RAW META-DICT), where META-DICT is META converted to a plain dict (name, filename, line, col, options). The handler returns ordinary Koskari source, which is compiled – and passed through apply_layout – in place of the fence.

Handler resolution (find_fence in koskari.fences): a bare-name binding resolves only when it is a FenceHandler; a fence/-prefixed binding resolves when it is a FenceHandler or any callable, so a module may define its own fence by binding a two-argument function to fence/<name>. Handlers run at compile time and must not suspend.

Self-contained expansions

Fence handlers lower to source that references only universal builtins – never a helper that must already be bound in the compiling module. fence/bash lowers onto the run-process builtin, so a bash fence works in any module without imports or setup. The built-in handlers are authored the same way, in Koskari, through define-fence.

Writing a fence handler

Define the handler with define-fence: (define-fence fence/<name> [raw meta] BODY ...), returning Koskari source – usually a quasiquoted template.

Keep the expansion self-contained. Reference only universal builtins, so the fence needs no pre-existing bindings at the use site.

Validate opener-line options from (meta.get "options") and raise FenceError for ones the handler does not accept.

A fence earns its place when the format it carries is genuinely awkward to write as native Koskari; see Fences.

>>> define-fence fence/shout [raw meta]:
...   `(.upper ,(raw.strip))