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

FlagDescription
-wWrite formatted output back to the file (required when formatting more than one file)
-bCreate a .bak backup of each file before overwriting
-checkReport files that need formatting; exit code 1 if any do (does not modify files)
-diffPrint 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
-rRecurse 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

Single file, no -w: the formatted result is written to stdout (your original file is untouched).
Multiple files: -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.
Auto config: when -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:

SectionWhat it controls
casingKeyword, number, directive, and identifier casing
spacingOperator, punctuation, parenthesis, bracket, generic, and range spacing; max consecutive spaces
indentIndent size, tabs, continuation indent, case indentation, max column
lineBreaksKeep-user-breaks, breaks around begin / single-instruction bodies / labels / sections, uses layout
reshapingPer-line reflow of call args, enums, arrays, inheritance; end/else collapsing; delimited group style
alignmentColumn-align assignments, colons, consts, and trailing comments
outputLine 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

ProfileIntent
DefaultConservative: reindents and applies case structure, but preserves spacing, casing, and user line breaks
FormatterExeApproximates RAD Studio's built-in Formatter.exe
EmbarcaderoThe Embarcadero Delphi style guide
NoOpPass-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

CodeMeaning
0Success (and, for -check / -diff, no files needed changes)
1Usage 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.