Skip to content

feat: add weak whitespace and indentation policy - #17

Merged
QuadnucYard merged 2 commits into
mainfrom
weak-space-2
Oct 3, 2026
Merged

QuadnucYard merged 2 commits into
mainfrom
weak-space-2

Conversation

@QuadnucYard

@QuadnucYard QuadnucYard commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Add WeakSpace and WeakLine primitives with consistent constructors
across allocator and document APIs.

weak_space() defers spaces after nonempty text. Consecutive weak
spaces accumulate and are committed by following nonempty text or a
line-suffix flush. Leading spaces and uncommitted trailing spaces are
omitted; empty text does not commit them. A line-suffix flush commits
them by presence alone, without inspecting the suffix document.

weak_line() emits a break only when the current line contains
nonempty text or a pending suffix. It has no flat alternative; callers
can supply one explicitly with flat_alt(space()) or flat_alt(nil()).

Extend ColumnState to track deferred indentation, pending padding,
and line freshness. Share these transitions between rendering and
fitting so suppressed breaks do not terminate fit checks and committed
padding participates in width decisions.

Add IndentationPolicy to RenderOptions to choose when a structural
break writes its indentation. Eager writes it right after the
terminator, so blank lines and a terminal break carry trailing spaces;
this stays the default for compatibility with upstream pretty.
Deferred postpones indentation until content commits it, so blank
lines and a terminal break emit none, a later break replaces pending
indentation, and the end of output discards it. The policy changes only
when indentation is written: the break itself, its indentation value,
blank-line counts, fitting, union rollback, and contextual columns are
unaffected, and explicit text and spaces stay literal.

OnColumn callbacks and alignment observe the prospective column
without forcing pending whitespace to be emitted.

Treat pending suffixes as content without evaluating their documents
during fitting. A suffix flush commits weak spaces even for an empty
suffix. Suffix text remains excluded from group and partial-union
fitting, while padding it commits counts toward the width. Suffixes
combined with weak whitespace must not emit line breaks.

Add regression tests for constructor consistency, explicit flat
alternatives, empty text, zero-width Unicode content, indentation,
contextual callbacks, suffix handling, and nested union rollback. Cover
both indentation policies and assert they agree except on blank and
terminal lines.

Add benchmarks for weak lines with suffixes, accumulated weak spaces
committed by text, and trailing weak spaces discarded at breaks or EOF.

@QuadnucYard
QuadnucYard force-pushed the weak-space-2 branch 2 times, most recently from a4fa401 to 6c2f74e Compare October 1, 2026 13:04
Options are plain configuration with no invariants to protect, so
reading and writing fields directly beats getter indirection. Mark the
struct `#[non_exhaustive]` so future options stay additive, and keep
`new` plus the fluent `with_*` methods as the construction path.

`Printer` now carries `options: RenderOptions` instead of separate
fields, so render state tracks one configuration value.
Add `WeakSpace` and `WeakLine` primitives with consistent constructors
across allocator and document APIs.

`weak_space()` defers spaces after nonempty text. Consecutive weak
spaces accumulate and are committed by following nonempty text or a
line-suffix flush. Leading spaces and uncommitted trailing spaces are
omitted; empty text does not commit them. A line-suffix flush commits
them by presence alone, without inspecting the suffix document.

`weak_line()` emits a break only when the current line contains
nonempty text or a pending suffix. It has no flat alternative; callers
can supply one explicitly with `flat_alt(space())` or `flat_alt(nil())`.

Extend `ColumnState` to track deferred indentation, pending padding,
and line freshness. Share these transitions between rendering and
fitting so suppressed breaks do not terminate fit checks and committed
padding participates in width decisions.

Add `IndentationPolicy` to `RenderOptions` to choose when a structural
break writes its indentation. `Eager` writes it right after the
terminator, so blank lines and a terminal break carry trailing spaces;
this stays the default for compatibility with upstream `pretty`.
`Deferred` postpones indentation until content commits it, so blank
lines and a terminal break emit none, a later break replaces pending
indentation, and the end of output discards it. The policy changes only
when indentation is written: the break itself, its indentation value,
blank-line counts, fitting, union rollback, and contextual columns are
unaffected, and explicit text and spaces stay literal.

`OnColumn` callbacks and alignment observe the prospective column
without forcing pending whitespace to be emitted.

Treat pending suffixes as content without evaluating their documents
during fitting. A suffix flush commits weak spaces even for an empty
suffix. Suffix text remains excluded from group and partial-union
fitting, while padding it commits counts toward the width. Suffixes
combined with weak whitespace must not emit line breaks.

Add regression tests for constructor consistency, explicit flat
alternatives, empty text, zero-width Unicode content, indentation,
contextual callbacks, suffix handling, and nested union rollback. Cover
both indentation policies and assert they agree except on blank and
terminal lines.

Add benchmarks for weak lines with suffixes, accumulated weak spaces
committed by text, and trailing weak spaces discarded at breaks or EOF.
@QuadnucYard QuadnucYard changed the title feat: add weak_space and weak_line feat: add weak whitespace and indentation policy Oct 3, 2026
@QuadnucYard
QuadnucYard merged commit 0bd826e into main Oct 3, 2026
2 checks passed
@QuadnucYard
QuadnucYard deleted the weak-space-2 branch October 3, 2026 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant