radFormatter / docs / config-options
Configuration options reference
radFormatter is configured with a JSON document. Every key is optional; any key you omit keeps the value from the active profile (see Profiles). A missing or empty config therefore applies the chosen profile's defaults — with no profile selected, that is the built-in Default profile.
There are 57 options across seven sections:
casing, spacing, indent,
lineBreaks, reshaping, alignment, and
output.
Generate a fully populated config with the current defaults using the CLI:
> radFormatter -writeDefaultConfig radFormatter.json
See the CLI reference for how the CLI loads and overlays configuration.
casing
Casing changes are the only non-whitespace edits radFormatter makes; every other change is whitespace or line breaks.
| Option | Type | Default | Effect |
|---|---|---|---|
| casing.keywords | case mode | "asis" | Reserved words (begin, end, if, …) |
| casing.numbers | case mode | "asis" | Letters in numeric literals: hex digits A–F and the float exponent marker E |
| casing.directives | case mode | "asis" | Compiler-directive keyword ({$IFDEF}, {$DEFINE}); the directive body is preserved |
| casing.identifiers | ident case mode | "asis" | Identifiers |
spacing
asis reproduces the original inter-token
whitespace verbatim. At the Default profile (every spacing option
asis) radFormatter makes no inter-token spacing
changes at all — it only changes indentation. The opinionated profiles
set spacing options to concrete values.| Option | Type | Default | Effect |
|---|---|---|---|
| spacing.assignment | spacing option | "asis" | Space around := |
| spacing.comma | spacing option | "asis" | Space around , |
| spacing.colon | spacing option | "asis" | Space around : |
| spacing.semicolon | spacing option | "asis" | Space around ; |
| spacing.insideParens | tri-state | "asis" | Space just inside ( ) |
| spacing.insideBrackets | tri-state | "asis" | Space just inside [ ] |
| spacing.beforeParens | tri-state | "asis" | Space before an opening ( (calls / declarations) |
| spacing.beforeBracket | tri-state | "asis" | Space before an opening [ (index / bounds) |
| spacing.aroundRange | tri-state | "asis" | Space around the range operator .. |
| spacing.genericBrackets | tri-state | "asis" | Space just inside generic angle brackets < > |
| spacing.aroundUnaryOperators | tri-state | "asis" | Space around unary -, +, @ |
| spacing.aroundBinaryOperators | tri-state | "asis" | Space around symbol binary operators (=, <>, +, -, *, /, …) |
| spacing.maxConsecutiveSpaces | integer | -1 | -1/0 = no limit; N = collapse any interior run of spaces longer than N down to N. Never widens a 0- or 1-space gap; leading indentation is unaffected |
aroundBinaryOperators. Word operators such as and,
or, xor, div, mod,
shl, shr, in, is,
as are never tightened, because removing their spaces would
produce invalid code.indent
| Option | Type | Default | Effect |
|---|---|---|---|
| indent.size | integer | 2 | Spaces per depth level. Applies to space indentation only — ignored when the effective style is tabs (the editor's tab stop owns the visual width). 0 disables reindentation |
| indent.style | "spaces" | "tabs" | "asIs" | "asIs" | Indent character: spaces always uses spaces; tabs uses one tab per structural level (continuation/alignment stay spaces); asIs (Default) preserves the source's indent character — the first line with leading indentation decides (leading tab → tabs, leading space → spaces), none → spaces. Depth is always recomputed; only the character is preserved |
| indent.directives | "asIs" | "column0" | "structural" | "asIs" | Compiler-directive indentation: asIs preserves source indent (Default); column0 forces the left margin (FormatterExe/Embarcadero); structural indents to surrounding depth |
| indent.continuationSize | integer | 2 | Extra spaces added to wrapped / continuation lines |
| indent.anchorBased | bool | false | When wrapping, align continuation lines under the column after the opening delimiter instead of using a fixed continuation indent |
| indent.maxColumn | integer | 0 | 0 = no cap; >0 = clamp any computed indent to this column |
| indent.caseLabels | bool | true | Indent case arm labels one level under the case keyword |
| indent.caseContent | bool | true | Indent a case arm body one level under its label |
| indent.caseSingleLine | bool | true | true = allow a single-statement case arm body to stay on the label line; false = force it onto its own line |
| indent.caseElseAlignment | "withLabels" / "withCase" | "withLabels" | Align a case's else with the arm labels, or with the case keyword |
lineBreaks
| Option | Type | Default | Effect |
|---|---|---|---|
| lineBreaks.keepUser | bool | true | When true, radFormatter only adds line breaks and never removes ones you placed. Set false for full reflow |
| lineBreaks.beforeSingleInstr | tri-state | "asis" | Newline before a single-statement control body (if/while/for/…) |
| lineBreaks.beforeBegin | tri-state | "asis" | Newline before begin |
| lineBreaks.betweenElseAndIf | bool | false | true = put else and if on separate lines; false = keep else if together |
| lineBreaks.afterBegin | bool | false | Force a line break after begin |
| lineBreaks.afterSectionKeyword | bool | false | Force a line break after a section keyword (uses, type, var, const, interface, implementation) |
| lineBreaks.afterLabel | tri-state | "asis" | Newline after a statement label's colon |
| lineBreaks.lineAfterSemicolon | bool | false | Force a line break after every statement-terminating semicolon, so each statement lands on its own line. Add-only (never removes user breaks) and CST-aware — parameter-list and declaration separators are left untouched |
| lineBreaks.usesMode | "preserve" / "singleLine" / "onePerLine" | "preserve" | How uses clauses are laid out: unchanged, collapsed to one line, or one unit per line |
reshaping
Structural rewrites of a construct's layout. All default off / conservative.
| Option | Type | Default | Effect |
|---|---|---|---|
| reshaping.oneParamPerLineInCalls | bool | false | Put each call argument on its own line |
| reshaping.collapseEndElse | bool | false | Collapse end + newline + else onto one line |
| reshaping.collapseEndElseBegin | bool | false | Collapse end + else + begin onto one line |
| reshaping.joinMultilineParens | bool | false | Collapse a multi-line parenthesized expression to a normalized inline form (output.rightMargin may then rewrap it) |
| reshaping.arrayInitPerLine | bool | false | Put each array-initializer element on its own line |
| reshaping.inheritancePerLine | bool | false | Put each class/interface inheritance-list entry on its own line |
| reshaping.enumPerLine | bool | false | Put each enum value on its own line |
| reshaping.delimitedGroupStyle | "compact" / "allman" | "compact" | Bracket/grouping style for delimited groups: opening delimiter trailing (compact) or on its own line (Allman) |
alignment
Column alignment across consecutive, structurally similar lines. All off by default. Alignment runs after indentation and only inserts interior padding.
| Option | Type | Default | Effect |
|---|---|---|---|
| alignment.assignments | bool | false | Align := operators |
| alignment.colons | bool | false | Align : type annotations in declarations (parameter lists excluded) |
| alignment.consts | bool | false | Align = in const declarations |
| alignment.trailingComments | bool | false | Align end-of-line // comments |
| alignment.maxPadWidth | integer | 0 | 0 = no limit; >0 = if aligning a group would require inserting more than N spaces of padding, that group is left unaligned |
output
| Option | Type | Default | Effect |
|---|---|---|---|
| output.lineEnding | "auto" / "crlf" / "lf" / "cr" | "auto" | auto uses the platform default line ending (CRLF on Windows); the others force CR+LF, LF, or CR |
| output.rightMargin | integer | 0 | Wrap column. 0 = disabled. When >0, lines longer than this are wrapped at their declared soft-break points (call arguments, parameter lists, uses commas, binary operators, inheritance lists, and so on) |
| output.maxEmptyLines | integer | -1 | -1 = unlimited; 0+ = maximum consecutive blank lines |
| output.strictMode | bool | true | When true, an unclassifiable feature is a validation error; when false, unknown constructs pass through untouched |
output.emptyLines
Integer counts for blank lines at structural boundaries. -1
(default) means “leave as-is”; a value N >= 0 ensures
exactly N blank lines there.
| Option | Effect |
|---|---|
| output.emptyLines.beforeVisibility | Before private / protected / public / published inside a class |
| output.emptyLines.aroundSections | Around interface / implementation / initialization / finalization |
| output.emptyLines.betweenDeclarations | Between routine declarations |
| output.emptyLines.beforeTypeKeyword | Before a type section |
Full default configuration
This is exactly what -writeDefaultConfig emits (the
Default profile).
{
"casing": {
"keywords": "asis",
"numbers": "asis",
"directives": "asis",
"identifiers": "asis"
},
"spacing": {
"assignment": "asis",
"comma": "asis",
"colon": "asis",
"semicolon": "asis",
"insideParens": "asis",
"insideBrackets": "asis",
"beforeParens": "asis",
"aroundRange": "asis",
"beforeBracket": "asis",
"genericBrackets": "asis",
"aroundUnaryOperators": "asis",
"aroundBinaryOperators": "asis",
"maxConsecutiveSpaces": -1
},
"indent": {
"size": 2,
"tabWidth": 0,
"style": "asIs",
"directives": "asIs",
"continuationSize": 2,
"anchorBased": false,
"maxColumn": 0,
"caseLabels": true,
"caseContent": true,
"caseSingleLine": true,
"caseElseAlignment": "withLabels"
},
"lineBreaks": {
"keepUser": true,
"beforeSingleInstr": "asis",
"beforeBegin": "asis",
"betweenElseAndIf": false,
"afterBegin": false,
"afterSectionKeyword": false,
"afterLabel": "asis",
"lineAfterSemicolon": false,
"usesMode": "preserve"
},
"reshaping": {
"oneParamPerLineInCalls": false,
"collapseEndElse": false,
"collapseEndElseBegin": false,
"joinMultilineParens": false,
"arrayInitPerLine": false,
"inheritancePerLine": false,
"enumPerLine": false,
"delimitedGroupStyle": "compact"
},
"alignment": {
"assignments": false,
"colons": false,
"consts": false,
"trailingComments": false,
"maxPadWidth": 0
},
"output": {
"lineEnding": "auto",
"rightMargin": 0,
"maxEmptyLines": -1,
"emptyLines": {
"beforeVisibility": -1,
"aroundSections": -1,
"betweenDeclarations": -1,
"beforeTypeKeyword": -1
},
"strictMode": true
}
}
Safety guarantees
radFormatter is non-destructive. No token is ever lost: it only adds, removes, or replaces whitespace and line endings, and recases keyword, directive, number, and identifier text. Every format is checked two ways — a non-whitespace content hash and a re-lexed token fingerprint. If any rule would alter non-whitespace content, the change is discarded and your original source is returned unchanged.
Appendix: value types
The value types referenced in the Type columns above. Each entry in an option table links back here.
Case mode (casing.keywords, casing.numbers, casing.directives)
| Value | Effect |
|---|---|
| "asis" | Leave as written (default) |
| "lower" | lowercase |
| "upper" | UPPERCASE |
| "title" | Title case (first letter upper, rest lower) |
Identifier case mode (casing.identifiers)
| Value | Effect |
|---|---|
| "asis" | Leave as written (default) |
| "lower" | all lowercase |
| "upper" | all UPPERCASE |
| "firstOccurrence" | Normalize every occurrence to the casing of the first one seen |
Spacing option (spacing.assignment, spacing.comma, spacing.colon, spacing.semicolon)
Controls whitespace on each side of a token. String values only.
| Value | Before token | After token |
|---|---|---|
| "asis" | unchanged | unchanged |
| "none" | remove | remove |
| "before" | ensure one space | remove |
| "after" | remove | ensure one space |
| "both" | ensure one space | ensure one space |
Tri-state (yes / no / asis)
Used by the toggle-style spacing options and several line-break options.
Accepts a JSON boolean (true = yes,
false = no) or a string
("yes", "no", "asis").
| Value | Effect |
|---|---|
| "asis" | Preserve the source spacing/break (default for most) |
| "yes" / true | Ensure the space/break |
| "no" / false | Remove the space/break |