whitehall format
One canonical style. No config, no options to argue about.
Usage
whitehall format [target] [options] target defaults to . and can also be a single .wh file:
whitehall format
whitehall format src/lib/components/Header.wh Options
| Flag | What it does |
|---|---|
--check | Exit 1 if any file needs formatting. Writes nothing. For CI |
--diff | Show what would change, without writing it |
# GitHub Actions
- name: Check formatting
run: whitehall format --check fmt is an alias for format, cargo's own shorthand.What it will not touch
Whitespace is the formatter's job. Everything else is yours, and it keeps it:
- Comments, wherever they are — attached to the declaration after them
- Declaration order — a
data classwritten above the store that uses it stays above it - Annotations as written —
@store(persist)comes back as@store(persist)
It also refuses to write a file it cannot read back: the output is parsed again before being written, and a mismatch is an error naming the file, with nothing written — never a formatted file that no longer builds.
Indentation and line width
2 spaces, always. 100 characters, wrapped past that:
<Column>
<Text>Indented with 2 spaces</Text>
<Row>
<Text>Nested: 4 spaces</Text>
</Row>
</Column> <TextField
bind:value={email}
label="Email Address"
helperText="We'll never share your email"
/> Components
Single-line when props fit, one prop per line when they do not, and children always on their own line:
<Button onClick={handleClick}>Click</Button>
<Button
color="primary"
fillMaxWidth
onClick={handleSave}
>
Save Changes
</Button>
<Spacer h={16} /> Prop order
Props are reordered by category:
- Binding (
bind:value,bind:checked) - Transitions (
in:,out:,transition:,animate:) - Core (
label,value,src,icon,title,name,id,placeholder) - Styling (
color,fontSize,fontWeight) - Spacing (
p,gap,w,h) - Layout (
fillMaxWidth, alignment and arrangement props) - Event handlers (any
on*prop) - Everything else, alphabetically
// Before
<TextField onClick={handler} p={8} label="Name" bind:value={text} />
// After
<TextField bind:value={text} label="Name" p={8} onClick={handler} /> Control flow
@if (isLoading) {
<CircularProgressIndicator />
} else {
<LazyColumn>
@for (item in items) {
<Text>{item}</Text>
}
</LazyColumn>
} Kotlin code
Standard Kotlin formatting applies to imports, functions, and data classes — one that fits stays on one line, one that does not wraps with a trailing comma:
import $lib.models.Post
import $lib.models.User
import $lib.stores.UserStore
data class User(val id: String, val name: String)
data class DetailedUser(
val id: String,
val name: String,
val email: String,
val avatarUrl: String?,
) Double quotes for strings, triple quotes preserved for multi-line ones:
val message = "Welcome"
val json = """{
"name": "Alice"
}""" Ignored files
.gitignore is respected automatically. build/, node_modules/ and generated .kt files are always skipped.
Editor integration
The VS Code extension spawns whitehall lsp, which formats the buffer
in-process on save through textDocument/formatting — the same formatter this
command runs, over LSP instead of a file write. A file that does not parse is left as it
is.
| Setting | Default | Meaning |
|---|---|---|
whitehall.path | "whitehall" | Path to the binary the extension runs lsp on |
Format on save is VS Code's own setting, on by default for .wh files. To turn it off:
// settings.json
{
"[whitehall]": {
"editor.formatOnSave": false
}
} Pre-commit hook
repos:
- repo: local
hooks:
- id: whitehall-format
name: Whitehall Format
entry: whitehall format --check
language: system
files: \.wh$ Philosophy
No configuration file, no rule to turn off. One style removes the debate rather than settling it in the project's favor.
Troubleshooting
A file that keeps coming back the way it was is not unformatted — the formatter follows
strict rules, and output that looks wrong is usually the canonical style winning over a
habit. --check writes nothing; plain whitehall format applies
changes.
See Also
- whitehall lint — catch errors and style issues
- whitehall build — build after formatting