Skip to content

Read the indent unit off the file - #760

Merged
SimonCropp merged 6 commits into
mainfrom
inferred-indent-unit
Aug 14, 2026
Merged

Read the indent unit off the file#760
SimonCropp merged 6 commits into
mainfrom
inferred-indent-unit

Conversation

@SimonCropp

Copy link
Copy Markdown
Member

One level of indentation was hard coded to four spaces, in two copies of the same expression: one in TryAppend, one in IndentForSpan. That is wrong in every two space repo, and a single call site cannot fix it, because a line shows which characters it is indented with but not how wide a level is.

DetectIndentUnit takes the mode of the runs each line adds to the one above it, measuring the string added rather than a column count, so tabs and spaces come out of the same measurement with no tab width assumption. Lines that do not start in code are skipped: a snapshot literal's content is arbitrary text, and counting it would measure the snapshot rather than the file.

UnitFor then takes the character from the call site and the width from the file. That split is what keeps a tab indented method inside a space indented file on tabs. It also settles tabs for depth followed by spaces for alignment, by reading the character the site's indentation ends in rather than whether it holds a tab anywhere: a tab there would advance to the next tab stop from wherever the alignment left off, a different width in every editor.

Both former hard codes now call UnitFor, so the rule exists once.

Indentation had one test before this. Alongside the unit itself, the cases that were unpinned: append and remove against tab indented files, a file that mixes both, a call line indented with tabs then spaces, and a raw literal whose content and closing delimiter disagree on which character to indent with, which the parser refuses for the same reason the compiler does (CS9003).

One level of indentation was hard coded to four spaces, in two copies of the
same expression: one in TryAppend, one in IndentForSpan. That is wrong in every
two space repo, and a single call site cannot fix it, because a line shows which
characters it is indented with but not how wide a level is.

DetectIndentUnit takes the mode of the runs each line adds to the one above it,
measuring the string added rather than a column count, so tabs and spaces come
out of the same measurement with no tab width assumption. Lines that do not
start in code are skipped: a snapshot literal's content is arbitrary text, and
counting it would measure the snapshot rather than the file.

UnitFor then takes the character from the call site and the width from the file.
That split is what keeps a tab indented method inside a space indented file on
tabs. It also settles tabs for depth followed by spaces for alignment, by
reading the character the site's indentation ends in rather than whether it
holds a tab anywhere: a tab there would advance to the next tab stop from
wherever the alignment left off, a different width in every editor.

Both former hard codes now call UnitFor, so the rule exists once.

Indentation had one test before this. Alongside the unit itself, the cases that
were unpinned: append and remove against tab indented files, a file that mixes
both, a call line indented with tabs then spaces, and a raw literal whose
content and closing delimiter disagree on which character to indent with, which
the parser refuses for the same reason the compiler does (CS9003).
The inline docs covered the transports, the patch format and the applier
contract, but not what the applier actually writes. That is four decisions —
literal form, delimiter length, placement and indentation — plus line endings,
and a surface integrating against InlineApplier has no way to predict any of
them from the patch alone.

Each is read off the file being patched rather than configured, which is the
part worth stating: there is no setting to reach for, and a two space file gets
two spaces because that is what its lines do, not because anything was told.
Prose was wrapped at a line length, which makes diffs noisy: changing one word
reflows the paragraph and touches every line after it, so the real edit is buried
in the reflow.

One paragraph, or one list item, is now one line. Fenced blocks, tables,
headings and directives keep their own line structure. No wording changed —
every generated file is identical once whitespace is collapsed.
PixelTests.Images has failed on ubuntu-latest at 0.9979 against the suite's
0.999, on main as well as on branches, depending on which runner image the job
landed on.

The other baselines are stable because ImGui rasterises glyphs with its own
stb_truetype, so text is identical whatever the rasteriser is. A picture is not
drawn that way — the renderer samples it — so llvmpipe builds can disagree
slightly, and this is the one screen that paints one.

0.995 absorbs that and still catches what the test is for: the fixtures are
small against the window, but a picture that fails to draw, draws the wrong
file, or lands in the wrong place takes its whole region to near zero local
similarity, well below the new threshold.

Capture takes the override rather than the suite moving, so the text screens
keep 0.999 — where a dropped row of body text still scores about 0.998 and the
margin is already thin.
@SimonCropp
SimonCropp merged commit 86da5cb into main Aug 14, 2026
8 checks passed
@SimonCropp
SimonCropp deleted the inferred-indent-unit branch August 14, 2026 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant