Skip to content

fix: seven reported defects in the 0.10.0 surface - #301

Merged
vyncint merged 1 commit into
mainfrom
fix-0-10-1
Sep 8, 2026
Merged

fix: seven reported defects in the 0.10.0 surface#301
vyncint merged 1 commit into
mainfrom
fix-0-10-1

Conversation

@vyncint

@vyncint vyncint commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Every issue was reproduced first, from the report's own test unchanged, before anything was edited — all six filed reports were accurate:

verified fix
#295 ["MIDDLE","BOTTOM",""] vs ["TOP","MIDDLE","BOTTOM"] to_asciicast drops the trailing newline that scrolled every frame
#296 grid came back blank grid/metadata split by the header's row count, not a marker hunt
#297 Parse("line 2: '\u{301}' has no character to combine with") the mark attaches to the cell owning the glyph, not its continuation half
#298 (1,2,false) vs (0,0,false) a hidden cursor's position is not part of "the same picture"
#299 end byte index 2 is not a char boundary six ASCII hex digits validated before slicing
#300 find_all reported it, the mask left it find_all and the masks share one multi-row engine
#292 macOS, 1 thread, stress fixtures register the SIGWINCH listener before the frame a test waits on

#292 turned out to be diagnosable after all. resize-echo already carried this exact guard, with a comment naming the mechanism: crossterm registers its SIGWINCH listener on the first event::read(), so a resize landing between the first draw and that call is lost for good — SIGWINCH's default disposition is ignore. form-echo and my ratatui-app never got it. A fixture must not announce readiness before it can receive what a test is about to send. hello-tui needs nothing (it handles no resize).

#300 was fixed by extraction, not duplication. The rustdoc promises find_all semantics, so the two now literally share for_each_multirow_match — that is what stops them drifting apart again.

#296 has a stated policy for the one ambiguous input (a hand-trimmed grid that also carries a styles block): content wins, and the rustdoc says why — a wrong row of text is visible in a diff, a silently dropped one is not. One existing unit test relied on the old lenient split and was rewritten around realistic with_styles() output.

Also corrects the skill, which showed mask_matching("0123456789", '#') as "every digit anywhere" — reading a literal-substring API as a character set. The snippet compiled; its comment was wrong, which check-skill-snippets.sh cannot catch.

Gates: fmt, clippy ×6 incl. Windows cross-target, docs ×2, msrv, deny, zizmor, gates-listed, skill snippets. 513 tests pass. cargo-semver-checks against 0.10.0: no semver update required, so this is a clean patch.

Closes #295, closes #296, closes #297, closes #298, closes #299, closes #300, closes #292

Every one reproduced first from the report's own test, unchanged, before
anything was edited; each fix carries the reproduction as a regression
test plus the extra coverage its issue asked for.

- to_asciicast dropped the newline that scrolled every frame. to_ansi ends
  each row with one, the bottom row included — right for a file, wrong for
  a repaint. The test now replays each exported event into a terminal of
  the recorded size and compares it to the frame it came from, which is
  what the old shape-only assertion could not see. (#295)

- Screen::parse splits grid from metadata by the header's row count
  instead of hunting a `styles:` marker, because a grid can contain that
  word and a snapshot of one came back blank. The single input that cannot
  be read both ways — a hand-trimmed grid carrying a styles block —
  resolves as content, stated in the rustdoc: a wrong row shows up in a
  diff, a dropped one does not. (#296)

- A combining mark after a wide character attaches to the cell that owns
  the glyph rather than to its continuation half, which holds no text.
  (#297)

- A hidden cursor's position is no longer part of "the same picture", for
  ScreenDiff::is_empty and wait_stable alike: it draws nothing and the text
  format does not record it, so a screen differed from its own snapshot
  with nothing visible behind it. Visibility, and a visible cursor's
  position, still count. (#298)

- parse_color validates six ASCII hex digits before slicing. `#a€bc` is six
  bytes, so the length check passed and the pair slice landed inside a
  character — an unwind out of the function whose whole job is returning
  Error::Parse, in a parser the CLI shares. (#299)

- find_all and the masks now share one multi-row match engine. mask_matching
  is documented as matching "the way find_all matches", but ran its matcher
  per row, where a newline can never appear: it reported a row-spanning
  needle and then left it on screen, which is the one failure a mask exists
  to prevent. Extracting the engine is what stops the two drifting again.
  (#300)

- form-echo and ratatui-app register crossterm's SIGWINCH listener before
  drawing the frame a test synchronizes on. A resize landing before the
  first event::read() was lost for good — SIGWINCH's default disposition is
  ignore — and wait_frame then spent a full deadline on an application that
  had never heard. resize-echo already guarded this; the comment there
  named the mechanism exactly. Found by the stress workflow on macOS at one
  thread. (#292)

Also corrects the skill: it showed mask_matching("0123456789", '#') as
"every digit anywhere", which reads a literal-substring API as a character
set. Compiling a snippet does not check what its comment claims.

Closes #295
Closes #296
Closes #297
Closes #298
Closes #299
Closes #300
Closes #292

Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
@vyncint
vyncint merged commit 3663d1c into main Sep 8, 2026
15 checks passed
@vyncint
vyncint deleted the fix-0-10-1 branch September 8, 2026 09:23
@vyncint vyncint mentioned this pull request Sep 8, 2026
vyncint added a commit that referenced this pull request Sep 8, 2026
Patch release: the seven defects fixed in #301, plus the Windows stress leg from #291. Gated on a 15/15 green stress run across all three OSes.

Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment