Turmeric ships a built-in formatter that produces canonical, consistent style
for .tur source files. It is a pure pretty-printer: it reads source text,
walks the Form tree produced by the existing reader, and re-emits formatted
output. It never touches the elaborator or code generator, so it works on any
syntactically valid file regardless of type errors.
# Format a file and print to stdout
tur format myfile.tur
# Format stdin and print to stdout
tur format < myfile.tur
# Overwrite a file in-place
tur format myfile.tur > myfile.tur.tmp && mv myfile.tur.tmp myfile.tur
# Check whether a file is already formatted (exits 1 if not)
tur format --check myfile.tur
The --check flag is useful in CI:
# Fail the build if any .tur file is not canonically formatted
find stdlib -name '*.tur' | xargs -n1 tur format --check
The Try Turmeric web interface has a Format button in the editor toolbar
(between Clear and Share). It calls turi_wasm_format() from the WASM module
and replaces the editor contents with the formatted output.
Keyboard shortcut: Alt+Shift+F (or Option+Shift+F on macOS).
Two-space indentation by default. A form is emitted on one line if it fits within the configured line width (default 80 columns); otherwise it is broken into a block layout.
These forms have well-known argument roles and use custom layouts:
| Form | Layout |
|---|---|
defn |
(defn name params :ret\n body...) |
defmacro |
same as defn |
fn |
(fn params\n body...) |
let |
(let [bindings...]\n body...) -- each binding pair on its own line |
if |
(if test\n then\n else) |
when / unless |
(when test\n body...) |
do |
(do\n form...) |
case |
(case expr\n pat result...) -- each arm on its own line |
loop |
(loop [bindings]\n body...) |
handle |
(handle expr\n arm...) |
defclass |
(defclass Name [params]\n method...) |
definstance |
(definstance Name Class Type\n impl...) |
defeffect |
(defeffect Name [] :ret) |
[...] -- inline if total width fits; otherwise one element per line.#{...} maps -- inline if total width fits; otherwise one key-value pair
per line.#s(...) sets -- inline if total width fits; otherwise one element per line.;; and ;;; comments at the top level are emitted on their own line.; comments after an expression are preserved on the same line.;; section header.:keyword type annotations stay on the same line as the expression they
annotate and are never line-wrapped independently.
Sugar forms are preserved: 'x, `x, ,x, ,@x stay as-is rather
than being expanded to their (quote ...) equivalents.
```c ... ``` blocks are emitted verbatim; the formatter does not
reformat embedded C.
Before formatting:
(defn add [x :int y :int] :int (+ x y))
(defn factorial [n :int] :int (if (<= n 1) 1 (* n (factorial (- n 1)))))
After tur format:
(defn add [x :int y :int] :int
(+ x y))
(defn factorial [n :int] :int
(if (<= n 1)
1
(* n (factorial (- n 1)))))
src/fmt.h -- Public C API (fmt_print, FmtOptions)src/fmt.c -- Formatter implementation