feat(tui): render fenced code on a surface, sized to the frame - #183
Merged
Merged
Conversation
`cargo fmt --all -- --check` (rust-ci.yml:52) fails on a pristine checkout of main: `render_response_reader` has a chained `saturating_add` that rustfmt wants broken across lines. It landed unformatted in #181, so the gate is currently red on main and every new PR inherits the failure. Pure formatting, no behavior change. Kept as its own commit so the code-block work in this branch stays readable. Signed-off-by: Val Alexander <68980965+BunsDev@users.noreply.github.com>
Fenced code in the transcript was drawn as a fixed 50-dash rule plus a yellow gutter, with the raw source line pushed verbatim. Three problems followed from that. The block had no edges. Code inherited the app background, so a fence bled into the prose above and below it and read as indented text rather than as a block. The rules ignored the frame. They were a hardcoded 50 dashes regardless of terminal width, so they under- or overshot on every terminal that was not exactly that wide. Worst, long lines were clipped silently. `render_markdown` already receives the frame width and the code path ignored it, so ratatui cut the line at the buffer edge with no marker. A truncated line was indistinguishable from a complete one, which matters most for exactly the content a reader is most likely to copy. Code rows now sit on COVEN_CODE_PANEL_BG and are fitted to the frame: clipped when they overrun, padded when they fall short, so a block reads as one continuous slab with a square right edge. Rules span the actual width. Body lines truncate with an ellipsis so a cut is visible. A tagged fence gets an accent-colored chip naming the language. The fence colors move off Color::Yellow and Color::White onto the COVEN_CODE_* tokens, per follow-up 4 of docs/tui-ux-accessibility-review.md: the named ANSI colors are terminal-theme dependent, so contrast there cannot be reasoned about. Two details worth review attention: - The edge glyph and the chip are independent. An untagged fence still opens with the opening edge; it just has no chip. An earlier version keyed the glyph off the label and opened untagged fences with the closing edge. - The fence tag is model output, so it is validated against a conservative identifier set and a length cap and rejected outright rather than mangled into a chip. Tests cover the surface fill, frame-width fitting, the chip, matching open and close edges, tag rejection, truncation, and narrow frames down to zero width. The live `render_markdown` fence path had no tests before; only the unreachable `messages::render_code_block` was snapshotted. Signed-off-by: Val Alexander <68980965+BunsDev@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fenced code in the transcript was drawn as a fixed 50-dash rule plus a yellow
│gutter, with the raw source line pushed verbatim (crates/tui/src/messages/markdown.rs:23). Three problems followed.The block had no edges. Code inherited the app background, so a fence bled into the prose around it and read as indented text rather than as a block.
The rules ignored the frame. Hardcoded 50 dashes regardless of terminal width, so they under- or overshot on every terminal that wasn't exactly that wide.
Long lines were clipped silently.
render_markdownalready receives the frame width and the code path ignored it, so ratatui cut the line at the buffer edge with no marker. A truncated line was indistinguishable from a complete one — which matters most for exactly the content a reader is most likely to copy.After
Every row sits on
COVEN_CODE_PANEL_BGand is fitted to the frame — clipped when it overruns, padded when it falls short — so the block reads as one continuous slab with a square right edge. Rules span the real width. Body lines truncate with…. A tagged fence gets an accent-colored chip.Review attention
┌; it just has no chip. My first version keyed the glyph off the label and opened untagged fences with└— the visual check caught it, and the test that should have caught it had an||that accepted either edge. Both are fixed.Color::Yellow/Color::Whiteonto theCOVEN_CODE_*tokens, per follow-up 4 ofdocs/tui-ux-accessibility-review.md— the named ANSI colors are terminal-theme dependent, so contrast through them cannot be reasoned about.The first commit is not mine to own
cargo fmt --all -- --check(rust-ci.yml:52) fails on a pristine checkout ofmain—render_response_readerlanded unformatted in #181:The gate is red on
mainand every new PR inherits it, so the fix is here as its own commit. Pure formatting, no behavior change.Tests
The live
render_markdownfence path had no tests before this — only the unreachablemessages::render_code_blockis snapshotted (tests/render_snapshots.rs:214). Added 8 cases: surface fill, frame-width fitting, the chip, matching open/close edges, untagged fences, tag rejection, truncation, and narrow frames down to zero width (which is how I found a rule-overflow bug at widths below the chip).Verification
Manual TUI validation per AGENTS.md, tmux 80x24:
App starts clean, welcome box intact. The strings
scripts/tui-tests/cases/02_startup.shpins —Coven v,Tips for getting started,What's new, and the❯prompt — all still render, so the startup case is unaffected.Known gaps
syntectis already a dependency and already wired for diffs (diff_viewer.rs:977); that is the obvious next step and is deliberately out of scope here to keep this diff reviewable.messages::render_code_blockremains dead code, kept alive only by its snapshot test. Not touched.