Consistent Indentation
4-space indentation, everywhere, automatically.
Zeus ships with a built-in code formatter. zeus fmt rewrites a source file into a
single, canonical style — so you never have to think about indentation, spacing, or
where the braces go.
It’s inspired by Prettier: it parses your code, throws away the original whitespace, and re-prints it, fitting each construct to an 80-column width.
Format a file in place:
zeus fmt app.zsThat’s it. The file is rewritten with the canonical style. If the file is already formatted, nothing is written.
Consistent Indentation
4-space indentation, everywhere, automatically.
Canonical Spacing
Spaces around operators, after commas and keywords, normalized.
Smart Line Breaking
Long argument lists wrap one-per-line; short ones stay inline.
Comments Preserved
Line and block comments are kept in place.
Given this messy input:
// Point in 2D spaceclass Point{public x:i32; // x coordinatepublic y:i32; // y coordinateconstructor(x:i32,y:i32){this.x=x;this.y=y;}}function main():i32{let p:Point=new Point(3,4); // make a point// verifyif(p.x==3){return 0;}return 1;}Running zeus fmt produces:
// Point in 2D spaceclass Point { public x: i32 // x coordinate public y: i32 // y coordinate constructor(x: i32, y: i32) { this.x = x this.y = y }}function main(): i32 { let p: Point = new Point(3, 4) // make a point // verify if (p.x == 3) { return 0 } return 1}When a call is short, it stays on one line. When it would exceed the print width, the formatter breaks it — one argument per line, with a trailing comma:
function main(): i32 { let result: i32 = computeSomething( argumentNumberOne, argumentNumberTwo, argumentNumberThree, argumentFour, ) return result}Both comment styles are preserved:
// a line commentlet x: i32 = 1 // a trailing comment
/* a block comment */let y: i32 = 2JSDoc-style block comments are re-indented with their * lines aligned (other
multi-line block comments — tables, ASCII art — are kept exactly as written):
/* * Computes the answer. */function answer(): i32 { return 42}Blank lines you write between statements are preserved (collapsed to at most one).
The formatter ships with sensible defaults and a small set of flags to override them:
| Setting | Default | Flag |
|---|---|---|
| Indentation | 4 spaces | --indent-width |
| Tabs | off | --use-tabs |
| Print width | 80 columns | --print-width |
| Semicolons | off | --semicolons |
| Control-flow | Always braced | — |
By default statement terminators are omitted — Zeus’s automatic semicolon
insertion makes them redundant. Opt back in with --semicolons=true:
# semicolon-free (default)zeus fmt app.zs
# keep semicolons, tabs, and a wider rulerzeus fmt app.zs --semicolons=true --use-tabs --print-width=100Zeus inserts a semicolon at a line break after any token that can end a statement — a
value (identifier, number, ), ], …) or a type keyword (i32, void, …). So the
formatter drops the ; from statements, class fields, and interface members, and only
keeps it where automatic insertion can’t help: a bare return, break, or continue,
which end in a keyword.
The same formatter is built into the language server, so
Format Document and format-on-save work in any LSP client. The VS Code
extension turns on format-on-save for .zs files by default — no extra setup.
The zeus fmt command is there for scripts, pre-commit hooks, and CI.
new allocations of function-type arrays (new ((x: i32) => i32)[]) are left
as-is.