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.

Prefer a visual editor? The IDE plugin includes a split-screen configuration editor that reads and writes this same file, with a live before/after preview of every option against real source — included even in the free Community Edition, so CLI users can edit configs visually too.

casing

Casing changes are the only non-whitespace edits radFormatter makes; every other change is whitespace or line breaks.

OptionTypeDefaultEffect
casing.keywordscase mode"asis"Reserved words (begin, end, if, …)
casing.numberscase mode"asis"Letters in numeric literals: hex digits AF and the float exponent marker E
casing.directivescase mode"asis"Compiler-directive keyword ({$IFDEF}, {$DEFINE}); the directive body is preserved
casing.identifiersident case mode"asis"Identifiers

spacing

AsIs means “do not touch”. For any spacing option, 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.
OptionTypeDefaultEffect
spacing.assignmentspacing option"asis"Space around :=
spacing.commaspacing option"asis"Space around ,
spacing.colonspacing option"asis"Space around :
spacing.semicolonspacing option"asis"Space around ;
spacing.insideParenstri-state"asis"Space just inside ( )
spacing.insideBracketstri-state"asis"Space just inside [ ]
spacing.beforeParenstri-state"asis"Space before an opening ( (calls / declarations)
spacing.beforeBrackettri-state"asis"Space before an opening [ (index / bounds)
spacing.aroundRangetri-state"asis"Space around the range operator ..
spacing.genericBracketstri-state"asis"Space just inside generic angle brackets < >
spacing.aroundUnaryOperatorstri-state"asis"Space around unary -, +, @
spacing.aroundBinaryOperatorstri-state"asis"Space around symbol binary operators (=, <>, +, -, *, /, …)
spacing.maxConsecutiveSpacesinteger-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
Keyword operators are excluded from 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

OptionTypeDefaultEffect
indent.sizeinteger2Spaces 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.continuationSizeinteger2Extra spaces added to wrapped / continuation lines
indent.anchorBasedboolfalseWhen wrapping, align continuation lines under the column after the opening delimiter instead of using a fixed continuation indent
indent.maxColumninteger00 = no cap; >0 = clamp any computed indent to this column
indent.caseLabelsbooltrueIndent case arm labels one level under the case keyword
indent.caseContentbooltrueIndent a case arm body one level under its label
indent.caseSingleLinebooltruetrue = 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

OptionTypeDefaultEffect
lineBreaks.keepUserbooltrueWhen true, radFormatter only adds line breaks and never removes ones you placed. Set false for full reflow
lineBreaks.beforeSingleInstrtri-state"asis"Newline before a single-statement control body (if/while/for/…)
lineBreaks.beforeBegintri-state"asis"Newline before begin
lineBreaks.betweenElseAndIfboolfalsetrue = put else and if on separate lines; false = keep else if together
lineBreaks.afterBeginboolfalseForce a line break after begin
lineBreaks.afterSectionKeywordboolfalseForce a line break after a section keyword (uses, type, var, const, interface, implementation)
lineBreaks.afterLabeltri-state"asis"Newline after a statement label's colon
lineBreaks.lineAfterSemicolonboolfalseForce 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.

OptionTypeDefaultEffect
reshaping.oneParamPerLineInCallsboolfalsePut each call argument on its own line
reshaping.collapseEndElseboolfalseCollapse end + newline + else onto one line
reshaping.collapseEndElseBeginboolfalseCollapse end + else + begin onto one line
reshaping.joinMultilineParensboolfalseCollapse a multi-line parenthesized expression to a normalized inline form (output.rightMargin may then rewrap it)
reshaping.arrayInitPerLineboolfalsePut each array-initializer element on its own line
reshaping.inheritancePerLineboolfalsePut each class/interface inheritance-list entry on its own line
reshaping.enumPerLineboolfalsePut 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.

OptionTypeDefaultEffect
alignment.assignmentsboolfalseAlign := operators
alignment.colonsboolfalseAlign : type annotations in declarations (parameter lists excluded)
alignment.constsboolfalseAlign = in const declarations
alignment.trailingCommentsboolfalseAlign end-of-line // comments
alignment.maxPadWidthinteger00 = no limit; >0 = if aligning a group would require inserting more than N spaces of padding, that group is left unaligned

output

OptionTypeDefaultEffect
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.rightMargininteger0Wrap 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.maxEmptyLinesinteger-1-1 = unlimited; 0+ = maximum consecutive blank lines
output.strictModebooltrueWhen 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.

OptionEffect
output.emptyLines.beforeVisibilityBefore private / protected / public / published inside a class
output.emptyLines.aroundSectionsAround interface / implementation / initialization / finalization
output.emptyLines.betweenDeclarationsBetween routine declarations
output.emptyLines.beforeTypeKeywordBefore 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)

ValueEffect
"asis"Leave as written (default)
"lower"lowercase
"upper"UPPERCASE
"title"Title case (first letter upper, rest lower)

Identifier case mode (casing.identifiers)

ValueEffect
"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.

ValueBefore tokenAfter token
"asis"unchangedunchanged
"none"removeremove
"before"ensure one spaceremove
"after"removeensure one space
"both"ensure one spaceensure 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").

ValueEffect
"asis"Preserve the source spacing/break (default for most)
"yes" / trueEnsure the space/break
"no" / falseRemove the space/break