[featured_image]
  • Version 0.7.0.22
  • Dateigrösse 3MB
  • Erstellungsdatum 3. Juli 2026
  • Zuletzt aktualisiert 17. August 2026
  • 1 file
    zip
    MSysFormatter_Setup_0.7.0.22.zip
    v0.7.0.223 mb2026-08-17

Changelog

v0.7.0.22 Latest2026-08-17

=======================================================================
MSys Delphi Formatter 0.7.0.22 — What's New
Maenken Systems · https://maenken.systems
Release 0.7.0.22 (from release 0.6.0.21)
=======================================================================

-----------------------------------------------------------------------
1. New
-----------------------------------------------------------------------

  • Every option explains itself. Hovering an option anywhere in the settings dialog brings up its help: what the option does, a short example and the default — laid out for reading instead of squeezed into a single line of tooltip. All 90 options are covered, in English and German. It runs through the IDE's own hint mechanism, so it can never end up as a second popup competing with the usual one.
  • The preview panes are syntax coloured and numbered. The Before and After panes used to paint their sample in one single colour. They now colour it per token — reserved words, strings, comments, numbers, directives — and the colours come from your own editor colour scheme, so the preview looks like the editor you actually work in. Both panes carry line numbers in a quiet gutter, which is what makes the two halves comparable: the same number on the left and on the right answers what the formatter did to that line. A scheme that cannot be read falls back to plain text on the correct background rather than to a guess.
  • Collapse a line break after an assignment when the statement fits. A new option on the Line Breaks page — off by default — removes the break directly after an assignment's := if the whole statement then still fits within the right margin, so Result := followed by a short expression on the next line becomes one line again. Like the end/else option it only ever merges: it never breaks a line, it only takes a break away. It stays out of the way where the layout was intentional — if the statement carries any further break, or the right-hand side is an anonymous method, it is left untouched. The statement is measured as though all its breaks were already gone, so the result does not depend on the current layout and reformatting again changes nothing. Requested by a user.

-----------------------------------------------------------------------
2. Fixed
-----------------------------------------------------------------------

Five defects in this release share one trigger: they only appear once the reflow of line breaks is switched on, and the standard Delphi 12 configuration switches it on. Anyone who imported their existing settings met several of them at once, which is why the import had a reputation for producing odd results. The import itself turned out to be faithful — it was applying the options exactly as given, and the engine mishandled them.

  • An inline variable is no longer mistaken for a goto label. With Line break after a label active, var a: Integer := 1; was torn in two after the colon, leaving var a: on one line and Integer := 1; on the next. The rule recognised any identifier followed by a colon; it now requires what a label actually is — the start of a statement. Real labels still get their line break, and for I: Integer := 0 to 3 do stays in one piece.
  • No more blank line before every inline variable. With Blank lines before a subsection set, a blank line was inserted ahead of any line starting with var, const or type — including an inline variable in the middle of a routine. In code written for Delphi 10.3 and later that put a blank line between nearly every statement. The separator now fires only where a declaration section can actually begin; genuine sections keep their blank line.
  • Local declarations keep their indentation. Switching on either of the two routine-body indentation options pushed a routine's own var, const and type declarations to column 0 — actively, even when they had been correctly indented beforehand, while the begin…end body kept indenting normally. Both options now leave the declarations one step under their keyword, for top-level and nested routines alike.
  • Conditional branch-swap tails survive reflow. A tail of the form else{$ELSE}begin{$ENDIF} has to stay on one line — both passes of the engine depend on it. With Line break after begin active, the begin was separated from the directive behind it, the structural bookkeeping went astray, and the file ended up with unbalanced blocks. The formatter then refused it outright, so the affected units silently stayed unformatted. Measured against a large open source library, six units were affected; now none are.
  • Variant records after a nested section no longer shift the rest of the file. When Indent type/const sections inside a class or record body was on, a record variant part (case Integer of without an end of its own) following a nested var, const or type section left an open block behind. Every declaration after that record — up to and including the final end. — stayed one level too deep and never returned to column 0. Because the result was stable across runs, reformatting never repaired it.
  • Inline variables in initialization and finalization are statements again. Those sections carry statements but open no block, so everything that asks "are we in executable code?" read them as declaration territory. An inline var there was taken for a declaration section: it pushed every following statement one level deeper, attracted the blank-line separator meant for real sections, and had the name list of var a, b: Integer; split at its comma. All three are gone, in both passes. A related case: a declaration written across two lines — var alone, the name below it — was read as a goto label and pulled to the label column.
  • Directive lines follow their code instead of freezing. With directive indentation switched off, a {$IFDEF} line kept its original column literally. That was invisible until the block settings moved the code around it — then the directive stayed behind and ended up stranded between lines it no longer lined up with, which reads as if the conditional had not been understood at all. It now moves with the code, keeping exactly the distance the author gave it. Where nothing moves, nothing changes.
  • Anonymous methods get their own indentation level again. An anonymous method passed as a call argument — TThread.Queue(nil, procedure begin … end) and every shape like it — had its whole contents pulled onto the column of its own begin. A for or if inside it lost its level as well, and its local var, const and type declarations sat on the same column as the keyword introducing them. The body now sits one step under its begin, and the declarations one step under their section keyword, while the begin itself stays where it belongs — attached to the call it is an argument of. This is not tied to an option: it happens with the standard settings, which is why it was reported from ordinary use. Measured against a large open source library, every one of the affected places now matches the column its authors had written by hand.
  • A unit named Inline keeps its name. inline is a directive in Delphi, not a reserved word — but the formatter had it listed among the reserved words, so every identifier of that name was treated as a keyword and re-cased: unit Inline; came out as unit inline;, and the same happened in a uses clause or a qualified reference. Nothing stopped compiling, since Delphi does not distinguish case in identifiers, but the formatter was changing a name that belongs to the author. It is now handled like every other directive — overload, stdcall, register, deprecated were all already treated correctly, so this removes an inconsistency rather than adding a rule.
  • One-line anonymous methods no longer make a whole unit unformattable. Passing an anonymous method as a call argument on a single line — Foo(procedure begin X := 1; end) — left a stray internal region behind whenever one of the two routine-body indentation options was on. A single occurrence still balanced out by chance; from the second one in a file the bookkeeping came apart, the safety net declared the file unsound, and the formatter refused it. The visible symptom was the worst kind: nothing happened at all, with no explanation. Measured against a large open source library, this was the last file in 366 that could not be formatted under any of six configuration profiles; all of them are now clean.
  • A wrapped assignment keeps its indentation level. When an assignment is broken across lines without brackets, everything below the first line used to fall back to the column of the statement itself, so Result := and the expression belonging to it ended up side by side and the statement read as two. The continuation now sits one step in, anchored on the line that opened the assignment — so a right-hand side spanning three or four lines stays at one step instead of drifting further right with every line. Where the right-hand side is an anonymous method, its header, its local declarations, its body and its end each land on the level they belong to. Brackets keep priority, so a wrapped argument list is unaffected. Measured against a large open source library, this moves the formatter closer to what the authors wrote by several hundred lines.
  • A for loop is no longer aligned like an assignment. With Align assignments switched on, a loop header standing between two assignments was padded into their column, so for I := 0 to 9 do came out as for I          := 0 to 9 do. The alignment looks for any := outside brackets, and a loop header's is spelled exactly like an assignment's — only the leading keyword tells them apart. It does now.
  • Comments no longer drift when a section ends. A uses, var or const section ends at its semicolon — but the formatter kept treating the space after it as part of the section, so a comment standing between the section and the next routine was pulled in one level. That hit { TMyClass }, the comment the IDE itself writes above the first method body: the formatter moved a line nobody had touched. Such a comment now takes the level of the code it introduces. A comment inside a section still moves with its declarations, and one above a nested routine follows that routine rather than dropping to the margin. Measured on a large code base, this restores the author's own column in the great majority of cases. Compiler directives on the same spot follow the same rule, and a closing {$ENDIF} moves together with the {$IF} it belongs to.
  • A note above a routine directive moves with it. The option that indents a stand-alone inline; or overload; line under its routine header moved the directive alone. In the very shape the option was built for — a note explaining why the directive is wrapped in a condition — the comment stayed behind on the old column, so a pair that had been written on one column came apart, and the result looked less like the original than before the option existed. The comment now takes the column of the directive it introduces, the same rule a comment above an else already followed. A comment that introduces an ordinary declaration keeps its place, and Indent comments: No still means every comment stays exactly where it is. Measured against a large open source library, this moves one single line in 366 units — the one from the report.
  • The align page's preview demonstrates its own option again. The sample there had no hand-set columns in it, so switching Keep hand-set columns on changed nothing visible — the one thing the preview exists for. The sample now carries a hand-aligned = column and hand-aligned trailing comments, which shows all three behaviours in one snippet: the default collapses them, the preserve option keeps them, and the align options re-compute them.

-----------------------------------------------------------------------
3. Under the hood
-----------------------------------------------------------------------

  • Every defect above is pinned by regression checks that fail without their respective fix — including the column drift, which no balance check could catch.
  • Verified against a large open source code base — 366 units — under twelve different configuration profiles, not just the default one: no unbalanced unit, no file the formatter had to refuse, and under every one of the twelve a second pass over the formatted output changes nothing.
  • The alignment options were measured against inline variables and leave them alone in every combination, at every nesting depth — that immunity is now pinned by a test as well.

=======================================================================
MSys Delphi Formatter 0.6.0.21 — What's New
Maenken Systems · https://maenken.systems
Release 0.6.0.21 (from release 0.5.0.17)
=======================================================================

-----------------------------------------------------------------------
1. New
-----------------------------------------------------------------------

  • Indent type/const sections inside a class body. Many libraries — and the RTL itself — put a type or const section inside a class or record body and indent its declarations one level under the keyword. The formatter used to pull them back to the level of the section keyword, and the existing "indent after sections" option did not help: that one only ever covered the unit sections interface and implementation. The new option Indent type/const sections inside a class or record body (Indentation page, or the .editorconfig key delphi_indent_nested_sections) covers the class-internal case. Default off, so nothing changes unless you ask for it; the indented region ends at the next visibility specifier, method declaration, further section keyword or the type's end, so it cannot spill into the rest of the file.
  • Indent case-else statements under their own else. With the case-else placed on the case column, its statements used to stay on the arm column — two levels away from the else they belong to. The new option Indent case-else statements under their own else (Indentation page, .editorconfig key delphi_indent_case_else_contents) closes that gap. It only differs in exactly that pairing; with the default case-else placement both readings coincide.
  • Indent directive lines under their routine header. A stand-alone inline;, overload; or stdcall; line — including the conditional form {$IF …}inline;{$IFEND} — can now be indented one continuation step under the header it belongs to, via Indent directive lines under their routine header (Indentation page, .editorconfig key delphi_indent_routine_directives). This is a matter of style rather than a defect: the ; after the parameter list ends the declaration, so the directive really is a line of its own and the flat reading is just as defensible — which is why the default is off. A comment between the header and the directive does not break the association.
  • Keep hand-set columns. Manually aligned trailing comments and = columns in const blocks used to be collapsed to a single space — the formatter threw away work someone had done on purpose. The align options were no answer: they compute the minimal column and so replace one normalisation with another. The new option Keep hand-set columns (Align page, .editorconfig key delphi_preserve_manual_columns) simply leaves such a run alone. It never widens a single space, so it cannot create alignment — it only keeps what is there. Default off.

=======================================================================
MSys Delphi Formatter 0.5.0.17 — What's New
Maenken Systems · https://maenken.systems
Release 0.5.0.17 (from release 0.4.0.10)
=======================================================================

All changes in this release were driven by community feedback from the Delphi-PRAXiS beta threads — thank you to everyone who tested and reported.

-----------------------------------------------------------------------
1. Fixed
-----------------------------------------------------------------------

  • The branch-swap conditional idiom no longer blocks formatting. The pattern where one preprocessor branch opens a case … of and the other contributes a begin instead — both sharing the closing ends, with {$ELSE} and {$ENDIF} sitting in the middle of one code line (else{$ELSE}begin{$ENDIF}) — used to make the whole file count as structurally unbalanced: with several occurrences the formatter refused the file (this is what made Spring4D's Spring.pas appear "unformattable"), and with exactly one occurrence everything after the pattern silently drifted two columns to the right. The formatter now recognizes this shape, follows the first branch — consistent with how conditional regions are handled everywhere else — and keeps the indentation stable. Other mid-line directive regions remain deliberately untouched, as documented under Known limits.
  • The options dialog is readable again under a light IDE theme. The pane holding the options took its background from the editor colour scheme instead of the IDE theme. Since that scheme is chosen independently of the theme, anyone running a light IDE with a dark editor scheme — a very common combination — got a black options pane while the captions stayed dark, which left whole pages unreadable. Editor colours now dress the two preview panes only, where they belong; everything else follows the IDE theme, in both the light and the dark variant.
  • The command-line formatter carries version information. Formatter.exe shipped without any version resource at all: neither Windows' file properties nor a deployment script could tell which build was in use. It now reports its version and vendor like the plugin does, and both are built from the same version number.

-----------------------------------------------------------------------
2. New
-----------------------------------------------------------------------

  • Blank-line separators without switching on reflow. The separators that put blank lines at structural boundaries — between methods, before the final end., around sections — used to require the reflow master to be off, which meant that anyone who only wanted a blank line between methods had to hand the formatter their whole line layout as well. Inserting a blank line moves no code, so it never needed that: the new option Apply the separators even when user line breaks are kept (Blank Lines page, or the .editorconfig key delphi_apply_blank_line_separators) releases them on their own. The default is off, so nothing changes unless you ask for it. Verified against a large real-world code base: with the option on, the only difference to a normal run is blank lines — not a single token moves.
  • Product page, version and contact are now in plain sight. The options dialog carries a slim header above every page: the product name with a link straight to the product page — opening the English or the German edition to match the IDE language — and the installed version on the right. Beta testers told us the previous placement was easy to miss, which made it unnecessarily hard to find out where to send feedback.
  • Format while typing (pilot, opt-in). On IDEs that offer the native formatter interface — prepared for future RAD Studio versions — the formatter can now re-format the line the caret leaves with Enter — same rules and safety gates as Ctrl+D, but completely silent: an incomplete or unbalanced buffer (the normal state while typing) or an already-formatted line is a quiet no-op, and no dialog ever appears. Caret, breakpoints and bookmarks follow exactly. Strictly opt-in (default: off) via the new General-page option Format line on Enter or per project via the new .editorconfig key delphi_format_on_type; semicolons, pasting and navigation never trigger it.
  • The command-line formatter no longer overwrites files it could not read properly. When the formatter cannot make sense of a file's structure — it ends up with more block openers than closers — its indentation is a guess. The IDE has always refused such a buffer and left it alone; the command-line tool used to mention the fact in passing and rewrite the file anyway, with a success exit code. A batch run over a repository therefore wrote guessed indentation into exactly the files the IDE protects, and --check reported them as an ordinary formatting difference. Both now give the same answer: the file is reported as KEEP and left untouched, the run ends with its own exit code 3 so a build pipeline can tell "needs formatting" from "cannot be formatted safely", and --out still writes the file into the mirror directory, where it overwrites nothing. The new switch --best-effort restores the previous behaviour for anyone who wants it, exit code included.

-----------------------------------------------------------------------
3. Under the hood
-----------------------------------------------------------------------

  • Conditional branches no longer add up in the line-break pass. The reflow stage kept one structural tally across all branches of a {$IFDEF} region instead of following the first one, the way the indentation stage already did. A branch that opened or closed a block without closing or opening it again shifted that tally for the rest of the unit, after which whole families of line-break rules quietly stopped applying — or started applying — far away from the directive that caused it. The effect was invisible from the outside: the output stayed structurally sound and stable under repeated formatting, only the line breaks were placed as if a different file had been read. Both stages now follow the same rule. This only ever affected profiles with reflow enabled.
  • A var or const parameter is no longer mistaken for a declaration section. With per-element wrapping of var/const lists enabled, a routine taking a var parameter had the comma in a generic return type (IDictionary) broken as if it were a name-list separator, leaving the continuation dangling. The two meanings of the keyword are now kept apart.

=======================================================================
MSys Delphi Formatter — History 0.4.0.10
=======================================================================

Release 0.4.0.10 (from beta build 3.0.1 / GetIt). All changes below were driven by community feedback from the Delphi-PRAXiS beta threads — thank you to everyone who tested and reported.

-----------------------------------------------------------------------
1. Fixed
-----------------------------------------------------------------------

Sources the formatter refused, or changed in ways it must not

Conditional compilation ({$IFDEF} / {$ELSE} / {$ENDIF}) — the big one

Sources whose conditional branches open or close blocks (begin, try, class, asm …) could not be formatted at all: the formatter saw the code of every branch at once, counted openers and closers across branches and refused the whole file as "unbalanced block structure". The mirror case — a closer duplicated across branches — silently produced drifted indentation.

The structural bookkeeping is now branch-aware: at {$IF*} the formatter snapshots its state, walks every {$ELSE} / {$ELSEIF} branch from that same entry state and continues after {$ENDIF} / {$IFEND} with the first branch's exit state. Both directive families are supported, nested regions work, and column alignment no longer bridges across branch boundaries. The safety guarantee is unchanged: nothing is ever written when the source truly is unbalanced.

Known limits: include files ({$I}) that contribute block edges and directives sharing a line with code are by-design limits — now documented in the manual's "Known limits" section; some reflow-mode edge cases remain tracked.

Variant records refused every unit

Any unit containing a variant record (case Integer of inside a record) was refused with the same "unbalanced" message — without a single compiler directive involved. Fixed.

A closing end at the end of a statement line refused the whole file

A line that both finishes a statement and closes its block — B; end;, or the end); a compact one-line anonymous method leaves behind — made the formatter report the source as unbalanced and refuse it entirely, although the code is perfectly valid. The closer was consuming the pending continuation of an enclosing if … then / while … do instead of the block itself, so the block stayed open until the end of the file. A closer now always ends a block, wherever it sits on the line. This affected the default profile too, not just reflow — and in the cases that were not refused outright it silently pushed everything after that line further and further right.

asm blocks that end mid-line refused the file

The same class of defect as the previous fix, one code path over: after the end of an asm block the formatter stopped looking at the rest of that line, so a routine written as asm … end; end; lost its outer block and the file was refused. The remaining closers on the line are now counted.

Reflow could silently change what a string literal means

With line-break rules active, if C = '''' then Q; was reflowed so that the apostrophe literal ended up as the last token on its line. Delphi 12 reads a run of three or more apostrophes followed only by whitespace as the opening delimiter of a multiline string — so on the next run the formatter (correctly) read its own output as a multiline string and swallowed the following code. The result was a program with different meaning, and in some shapes one that no longer even parses. Such a literal is now never left at the end of a line. This also removes the last known case where formatting twice gave a different result than formatting once.

An unrelated .editorconfig could be applied to your file

The settings cascade walks from the file's own directory upwards — but one step past the drive root it produced the drive-relative form (C:), and asking Windows for C:.editorconfig means ".editorconfig in the current directory of that drive". Files that had no .editorconfig of their own therefore silently picked up the one belonging to whatever directory the formatter happened to be started from — in the IDE that is not even a directory you chose. The cascade now stops at the drive root, so only the file's own path decides its settings.

Broken parentheses no longer produce file-wide indent drift

A source with a missing ) or ] used to pass the safety check silently — it only measured begin/end blocks — and the continuation indent then drifted through the rest of the file. Unbalanced parentheses or brackets now share the same protection as unbalanced blocks: the IDE refuses with a precise message ("unbalanced parentheses or brackets") and leaves the buffer untouched. Such files cannot compile anyway; once the syntax is fixed, a single format run restores canonical indentation everywhere.

Layout

Alignment stopped working after branch-asymmetric conditionals

The aligner's nesting counters read every {$IFDEF} branch as if all of them were compiled at once — a begin in each branch counted twice, so behind such a conditional the aligner believed it was still inside executable code and quietly stopped aligning const/var/field blocks. The counters now follow the first branch only (the same first-branch-wins rule the conditional-fork indenter uses); behind the region the alignment is identical to a file containing just that branch.

Generics with conditional type arguments were spaced as comparisons

TList came out as TList ; — the generic matcher silently swallowed the directives and read both branches as one invalid token stream. The scan now follows the first branch and skips {$ELSE}…{$ENDIF} whole (the same first-branch-wins rule the conditional-fork indenter uses), so the angle brackets stay generic-tight in every branch. Real comparisons next to directives keep their operator spacing.

Box-art comment headers were gutted

Under the default profile, decorative comment blocks such as the classic { Framework Name } unit headers lost their interior padding, and whitespace-only filler lines collapsed to {}. The comment-spacing option now does exactly what it says — it normalizes the single space inside the delimiters ({x}{ x }) — and treats everything beyond that (padding runs, frame lines like {******}, multi-line comments) as deliberate layout that survives byte-for-byte.

Nested if/else indented misleadingly

In if A then if B then … else … chains the else branch was visually re-bound to the outer if, although Delphi binds it to the nearest one. The indentation now follows the language's actual binding — including through while … do in between, and without disturbing case-else handling.

Multi-line signatures and calls lost their continuation indent

Continuation lines of a multi-line parameter list or call were flattened to the same column as their head line. They now indent one continuation step past the line that opened the bracket; a closing-bracket line aligns with that opener line.

Statements after a mid-line finally / except were mis-indented

try / if A then / B; finally left the pending then continuation standing, so the statements of the finally part sat one step too deep.

The else of an unparenthesized if-expression looked like a second else

In if C then / X := if A / then 1 / else 2 / else / Y := 3; the first else belongs to the expression, the second to the statement — but the formatter pulled both onto the same column, so the code read as if one if had two else branches. The expression's else now stays at the expression's level. (The branch lines themselves keep their layout: an unparenthesized continuation is never indented an extra step — the same as X := A + / B;.)

Generic constraints were spaced as comparisons

TList came out as TList . Constraint lists (class, record, constructor, interface types, multiple parameter groups) are now recognized as generics.

Generics in parameter defaults were torn apart

A default value glued to a generic parameter type — Symbols: TArray= [] (no space before the =) — made the scanner read >= as a single greater-or-equal operator. The generic then failed to be recognized and came out spaced as a comparison: TArray = []. Both the tight original and the previously damaged form now heal to TArray = []; a generic < also glues back to its type name. Real comparisons like a = c are untouched.

Delphi 13 if-expressions were staircased

A multi-line if-expression in parentheses — (if cond then '-' else '') spread over lines — had its branch lines indented like a statement-if, one extra level per then/else. Combined with the bracket-indent option this produced a staircase drifting right with every branch. Inside parentheses an if is always an expression (only an anonymous method's begin re-enters statement territory — that case is recognized and unchanged), so the branch lines now get plain continuation indent. Statement-if formatting, dangling- else binding and case-else handling are untouched.

"else if" line breaks left the else hanging

With line-break rules active, if A then B else if C then D reflowed to then B elseif C. A statement-level else now always starts its own line; the existing option keeps controlling the gap between else and if (both settings of it now produce clean shapes). Delphi 13 if-expressions (x := if a then b else c) are never broken apart.

Line-break rules tore if-expressions apart

With reflow enabled, a Delphi 13 if-expression was laid out like a statement: S := (if A then 'yes' else 'no'); came back split across four lines. The first round of protection covered only the unparenthesized form and only two of the four rules involved, so both the parenthesized form and — with the then and simple instruction rules armed — even the bare one were still broken up. Inside parentheses an if is always an expression (an anonymous method's begin re-enters statement territory), and those rules now leave both forms alone. Statement ifs keep breaking exactly as configured.

Command line

One bad file no longer aborts the whole run

A source that cannot be decoded (a stray byte in a file claiming UTF-8) made Formatter.exe stop right there — silently truncating a recursive sweep, even under --check where nothing is written at all. Such a file is now reported, counted as skipped and left untouched; the run continues and the exit code still reports the error.

-----------------------------------------------------------------------
2. New
-----------------------------------------------------------------------

Blank lines around initialization/finalization, and before the final end.

Two new structure separators and a new indent option close the gap the section separators left: delphi_blank_lines_around_initialization guarantees blank lines before and after the initialization/ finalization keywords, delphi_blank_lines_before_final_end puts them before the closing end., and Indent initialization/finalization contents indents the sections' statements one level like a begin..end block. All three are off by default — existing output stays byte-identical.

Unusable options are now hidden

When a master option turns a group of settings off, those settings used to stay visible — at best with a grayed group title, while the controls below still looked active ("It's disturbing"). Dependent options are now hidden outright: with "Keep user line breaks" on (the default), the line-break rules, the whole Reflow page and the blank-line separators disappear (an explanatory note stays behind); the alignment tuning numbers hide while no alignment case is active; coupled or inert switches (colons-before-types coupling, case options without block indent, bracket indent under reflow) vanish with their masters. Toggling the master brings everything back — live, across pages, without reopening the dialog.

Readable, complete option texts

Longer labels were cut off — most visibly the note under Blank Lines and the "colons before type names" switch under Alignment, and more often in German, where the translations are longer than the English originals. Every page was measured against both languages: notes have room for their full text, long switch captions wrap instead of being clipped, and the drop-downs sit far enough right that no label can run into them. The explanatory notes are now laid out in paragraphs instead of one dense block.

The option previews now show real cases

The live before/after preview on each options page demonstrates the constellations this release fixed: conditional branches carrying a try, case with else, box-art comment headers, generic constraints and defaults, multi-line call continuations, dangling else binding, {$REGION} blank lines and alignment groups broken by a directive — so every page shows its own options working on real code.

The line-break master is now a regular .editorconfig key

"Keep user line breaks" can be set from a project's .editorconfig (delphi_keep_user_linebreaks) like every other option, so a team can pin its line-break policy in the repository and an exported profile round-trips completely. This deliberately reverses the earlier safety stance that a repository file must never enable reflow.

Export writes what you see

Both export buttons (.config and .editorconfig) now write the values currently set in the options dialog, including pages you have edited but not yet applied — previously they silently wrote the last saved state, and the note explaining that is gone along with the behaviour.

The installer now serves both IDEs

The setup installs the 32-bit and the 64-bit design package side by side and registers each with its IDE (Known Packages / Known Packages x64) — Ctrl+D works in whichever RAD Studio 13 you launch. Both packages always carry the same version number; the installer build refuses to package mismatched builds.

Option: placement of the case-else line

A new switch "Indent else line" (delphi_indent_case_else) controls where the else of a case statement sits: at the level of the alternative labels (default, unchanged behaviour) or at the case keyword — the classic RTL style. The statements below it remain governed by the existing case options.

-----------------------------------------------------------------------
3. Clarified and pinned
-----------------------------------------------------------------------

  • Blank lines around {$REGION}: both halves of the request are covered by existing options — set Max. consecutive blank lines to 2 to preserve a two-blank region spacing, and Blank lines around compiler directives (reflow tier) to insert them. Documented in the manual and locked in by tests.
  • "Ensure final newline" and "Enable formatting": both reported against beta build 3.0.1; the current code base behaves correctly (the disable switch is honoured end to end, including the .editorconfig cascade, and the final-newline option is exact in both directions). Both behaviours are now locked in by tests. The 3.0.1 symptoms came from that build's Revive-based IDE integration, which the native RAD Studio 13.2 formatter interface has since replaced.
  • Options pages opening slowly: verified not to be the plugin — even empty pages build up slowly; the cost sits in RAD Studio's own Tools/Options page embedding and would affect any add-in equally.

The limits of conditional handling are documented

Two constellations the conditional-fork model cannot cover by principle now have their own "Known limits" manual section (German and English): include files that contribute block structure (the formatter refuses honestly or, for an included begin, may indent differently after the spot - never damaging anything), and directive regions starting or ending next to code on the same line (left untouched). Each comes with a minimal example, the observable behavior and an .editorconfig opt-out recipe.

-----------------------------------------------------------------------
4. By design
-----------------------------------------------------------------------

  • The options tree stays under the MSys node: requested twice from the community ("Third Party" placement); declined deliberately — the MSys node is the shared home for current and future MSys settings.
  • Ctrl+D stays Ctrl+D: the format shortcut is not configurable — Ctrl+D has been the Delphi formatter's key since the built-in one, and on RAD Studio 13.2 the IDE owns the command anyway. Plugins that also claim Ctrl+D (e.g. GExperts) offer configurable shortcuts on their side.

-----------------------------------------------------------------------
5. Under the hood
-----------------------------------------------------------------------

  • The regression suite grew from 744 to 970 checks; every repository fixture is now also verified to format balanced, and formatting twice is now pinned for reflow profiles too, not just the default one.
  • New shared conditional-directive classifier used by the re-indenter and the aligner; community-provided reproduction sources joined the fixture set.
  • Several of the defects above were found by the fix for another one: the mid-line closer and the multiline-string cases came out of reviewing the if-expression reflow, and the .editorconfig cascade bug out of measuring the multiline-string fix.