Opinionated code formatter for santa-lang, written in Zig.
santa-tinsel is a fast, opinionated code formatter that enforces a single canonical style for santa-lang code. It uses the Wadler-Lindig pretty printing algorithm for intelligent line-breaking decisions.
Key features:
- Fast - Written in Zig for optimal performance
- Opinionated - One canonical style, no configuration needed
- Idempotent - Running the formatter twice produces the same output
- Intelligent line-breaking - Uses the Wadler-Lindig pretty printing algorithm
- Comment-preserving - Keeps standalone and trailing comments intact
- Zero dependencies - Pure Zig with no external dependencies
Source Code → Lexer → Parser → Builder → Printer → Formatted Code
↓ ↓
AST Doc IR
| Component | Description |
|---|---|
| Lexer | Tokenizes source into keywords, operators, literals |
| Parser | Builds an Abstract Syntax Tree (AST) using Pratt parsing |
| Builder | Converts AST to Wadler-Lindig document IR |
| Printer | Renders document IR with intelligent line-breaking |
Download pre-built binaries from GitHub Releases:
| Platform | Artifact |
|---|---|
| Linux (x86_64) | santa-tinsel-{version}-linux-amd64 |
| Linux (ARM64) | santa-tinsel-{version}-linux-arm64 |
| macOS (Intel) | santa-tinsel-{version}-macos-amd64 |
| macOS (Apple Silicon) | santa-tinsel-{version}-macos-arm64 |
| WebAssembly (WASI) | santa-tinsel-{version}.wasm |
# Format stdin to stdout
echo 'let x=1+2' | santa-tinsel
# Format a file to stdout
santa-tinsel solution.santa
# Format a file in place
santa-tinsel -w solution.santa
# List files that differ from formatted (useful for CI)
santa-tinsel -l solution.santa
# Show diff of changes
santa-tinsel -d solution.santa
# Format all .santa files in a directory recursively
santa-tinsel -w src/| Flag | Description |
|---|---|
| -w | Write result to source file (format in place) |
| -l | List files whose formatting differs (exit 1 if any) |
| -d | Display diffs instead of rewriting files |
| -h | Display help and exit |
The formatter enforces consistent style:
# Input # Output
1+2 1 + 2
[1,2,3] [1, 2, 3]
|x|x+1 |x| x + 1
let x=1 let x = 1
#{"foo":foo} #{foo}
Two-element pipes stay inline, three or more expand vertically:
# Inline (2 elements)
[1, 2] |> sum
# Expanded (3+ elements)
input
|> lines
|> filter(is_valid?)
|> size
Single-expression lambdas stay inline, multi-statement expand:
# Inline
|x| x + 1
# Expanded
|x| {
let y = x + 1;
y
}
Requires Zig 0.15.x:
# Build CLI (debug)
make build
# Build CLI (release)
make release
# Run tests
make test
# Run all CI checks (lint + test)
make can-releaseThe executable will be at zig-out/bin/santa-tinsel.
Run make help to see all available targets:
make help # Show all targets
make fmt # Format Zig source code
make lint # Run zig fmt --check
make test # Run all tests
make can-release # Run before submitting PR (lint + test)├── src/
│ ├── token.zig # Token definitions
│ ├── lexer.zig # Tokenization
│ ├── ast.zig # AST node definitions
│ ├── parser.zig # Pratt parser
│ ├── doc.zig # Wadler-Lindig document IR
│ ├── builder.zig # AST to document IR
│ ├── printer.zig # Document IR to string
│ ├── lib.zig # Public API
│ ├── main.zig # CLI entry point
│ └── formatter_test.zig # Test suite
└── .github/workflows/ # CI/CD configuration
| Rule | Example |
|---|---|
| Operators with spaces | 1 + 2, x == y |
| Prefix operators tight | !true, -42 |
| Collections with comma | [1, 2, 3], {a, b} |
| Bindings with spaces | let x = 1 |
| 100-char line width | Lines break intelligently at 100 chars |
| 2-space indentation | Consistent indent level |
| Dict shorthand | #{"foo": foo} → #{foo} |
The language has been implemented multiple times to explore different execution models and technologies.
| Codename | Type | Language |
|---|---|---|
| Comet | Tree-walking interpreter | Rust |
| Blitzen | Bytecode VM | Rust |
| Dasher | LLVM native compiler | Rust |
| Donner | JVM bytecode compiler | Kotlin |
| Vixen | Embedded bytecode VM | C |
| Prancer | Tree-walking interpreter | TypeScript |
| Name | Description |
|---|---|
| Workbench | Desktop IDE |
MIT License - see LICENSE for details.
