radFormatter / docs / cli
radFormatter CLI
A non-destructive Delphi source code formatter.
radFormatter tokenizes your source, builds a full Concrete Syntax Tree, and runs an owned-decision pipeline that assigns spacing, line breaks, indentation, and alignment — then renders the result without ever losing or altering a token beyond whitespace and casing.
Key features
Non-destructive. Every format is validated with a non-whitespace content hash and a re-lexed token fingerprint. If anything beyond whitespace or casing would change, the output is discarded and your original source is returned untouched.
CST-aware. Indentation, case structure,
generic parameters, and nested control flow are driven by real parse data,
not line heuristics.
57 configuration options across seven sections (casing,
spacing, indent, line breaks, reshaping, alignment, output). Commit one
radFormatter.json and every developer and CI job formats
identically. See the
configuration options reference.
Built-in profiles. Start from Default,
FormatterExe (RAD Studio formatter compatibility),
Embarcadero, or NoOp, then override.
CI-ready. -check reports files that need
formatting and exits 1 when any do; -diff shows
the unified diff of what would change.
Supported file types
.pas.dpr.dpk.dpkw.inc
Usage
radFormatter <file|pattern> [<file|pattern> ...] [-w] [-b] [-profile <n>] [-config <file>]
radFormatter -d <directory> [-r] [-w] [-b] [-profile <n>] [-config <file>]
radFormatter <file|pattern> [...] -check [-profile <n>] [-config <file>]
radFormatter <file|pattern> [...] -diff [-profile <n>] [-config <file>]
radFormatter -writeDefaultConfig <file>
Running with no arguments prints usage.
Options
| Flag | Description |
|---|---|
| -w | Write formatted output back to the file (required when formatting more than one file) |
| -b | Create a .bak backup of each file before overwriting |
| -check | Report files that need formatting; exit code 1 if any do (does not modify files) |
| -diff | Print a unified diff of what formatting would change; exit code 1 if any (does not modify files) |
| -d <directory> | Format all supported files found in this directory |
| -r | Recurse into subdirectories (with -d or a glob pattern) |
| -exclude <patterns> | Semicolon-separated exclude patterns (file names or wildcards); cumulative across repeated -exclude flags |
| -profile <n> | Base profile: Default, FormatterExe, Embarcadero, or NoOp |
| -config <file> | JSON config file, overlaid on the selected profile |
| -writeDefaultConfig <file> | Write the default config JSON to <file> and exit |
Wildcards (*, ?) are supported in file arguments.
Output and safety rules
-w: the
formatted result is written to stdout (your original file
is untouched).-w is
required (stdout cannot represent more than one file). This restriction is
lifted for -check and -diff.-check and -diff are mutually
exclusive, and neither can be combined with -w.-config is
not given, radFormatter looks for a radFormatter.json next to
the executable and uses it if present.Examples
Format a single file to stdout using the Default profile:
> radFormatter source/MyUnit.pas
Format a whole tree in place:
> radFormatter -d source -r -w
Format matching files in place, with backups:
> radFormatter -d source -r -w -b *.pas
Check formatting in CI without modifying files:
> radFormatter -check -config radFormatter.json -d source -r
Show what would change:
> radFormatter -diff -config radFormatter.json source/MyUnit.pas
Format a tree, excluding generated and vendored code:
> radFormatter -d source -r -w -exclude "generated;vendor;*.g.pas" *.pas
Use a profile with project overrides:
> radFormatter -profile Embarcadero -config team.json -w source/MyUnit.pas
Generate a starter configuration:
> radFormatter -writeDefaultConfig radFormatter.json
Configuration
All formatting behavior is set through a JSON config overlaid on the
chosen profile. Generate a fully populated default with
-writeDefaultConfig and edit to taste. The sections are:
| Section | What it controls |
|---|---|
| casing | Keyword, number, directive, and identifier casing |
| spacing | Operator, punctuation, parenthesis, bracket, generic, and range spacing; max consecutive spaces |
| indent | Indent size, tabs, continuation indent, case indentation, max column |
| lineBreaks | Keep-user-breaks, breaks around begin / single-instruction bodies / labels / sections, uses layout |
| reshaping | Per-line reflow of call args, enums, arrays, inheritance; end/else collapsing; delimited group style |
| alignment | Column-align assignments, colons, consts, and trailing comments |
| output | Line endings, right margin, empty-line control, strict mode |
See the configuration options reference for the full option reference, value types, defaults, and a complete example.
Profiles
| Profile | Intent |
|---|---|
| Default | Conservative: reindents and applies case structure, but preserves spacing, casing, and user line breaks |
| FormatterExe | Approximates RAD Studio's built-in Formatter.exe |
| Embarcadero | The Embarcadero Delphi style guide |
| NoOp | Pass-through: output matches input byte-for-byte (modulo line endings) |
Omitting -profile uses Default. A
-config file is overlaid on the profile, so you only specify
the keys you want to change. See Profiles for a
side-by-side comparison with before/after examples.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success (and, for -check / -diff, no files needed changes) |
| 1 | Usage error, a file/config error, or — under -check / -diff — at least one file needs formatting |
Safety guarantees
Content-hash validation — a whitespace-excluded hash of the source is compared before and after formatting; any mismatch discards the change.
Token fingerprinting — the output is re-lexed and its token fingerprint compared to the original; a mismatch discards the change.
Graceful failure — when validation fails, the original source is returned unchanged. No data loss.
Backups — -b writes a
.bak copy before overwriting.
Integration
Pre-commit hook
#!/bin/sh
radFormatter -check -config radFormatter.json -d source -r
GitHub Actions
- name: Check formatting
run: radFormatter -check -config radFormatter.json -d source -r
Team workflow
Commit radFormatter.json to your repository. Every developer
and CI job uses the same configuration — formatting disputes are
settled once, in the config file.