Skip to content

fix(tui): clear footer row before rendering statusline#2248

Open
Sskift wants to merge 2 commits into
Hmbown:mainfrom
Sskift:fix/issue-2244-transcript-footer-overlap
Open

fix(tui): clear footer row before rendering statusline#2248
Sskift wants to merge 2 commits into
Hmbown:mainfrom
Sskift:fix/issue-2244-transcript-footer-overlap

Conversation

@Sskift
Copy link
Copy Markdown

@Sskift Sskift commented May 27, 2026

Summary

  • repaint the entire footer row before drawing status spans so stale transcript glyphs cannot survive on the footer line
  • add a regression test that seeds stale cells across the full row and verifies the render clears them while applying the footer background

Closes #2244.

Testing

  • cargo test -p codewhale-tui render_clears_stale_cells_across_entire_footer_row
  • cargo test -p codewhale-tui render_swaps_toast_for_status_line
  • HOME="$(mktemp -d)" USERPROFILE="$HOME" RUSTUP_HOME="/Users/bytedance/.rustup" CARGO_HOME="/Users/bytedance/.cargo" cargo test -p codewhale-tui

Notes

  • the host environment has local skills in HOME that cause the unrelated prompts::tests::system_prompt_skips_locale_preamble_for_english test to fail outside an isolated HOME

Greptile Summary

This PR fixes a stale-cell rendering bug (#2244) in the TUI footer widget where leftover glyphs from the transcript pane could persist in footer row cells not touched by the current frame's status spans.

  • Adds a pre-clear loop in FooterWidget::render that fills every cell in the footer area with a space and the configured footer background before painting the status-line spans.
  • Adds a regression test (render_clears_stale_cells_across_entire_footer_row) that seeds the buffer with visually distinct stale content and asserts both that no stale symbol survives and that the full row carries the correct background colour.

Confidence Score: 5/5

Safe to merge — the change is a narrow, well-bounded defensive clear of a single-row buffer before an existing Paragraph render, with a direct regression test covering the exact failure mode.

The pre-clear loop iterates only over the footer area (typically 1 row wide), the bounds use ratatui's own top()/bottom()/left()/right() helpers so there is no off-by-one risk, and the subsequent Paragraph::render call is unchanged. The new regression test seeds the buffer with unmistakable stale content and asserts both symbol-level and background-level correctness, covering the exact scenario from issue #2244.

No files require special attention.

Important Files Changed

Filename Overview
crates/tui/src/tui/widgets/footer.rs Adds a defensive pre-clear loop before Paragraph::render and a focused regression test; bounds arithmetic and buffer indexing are correct.

Sequence Diagram

sequenceDiagram
    participant F as FooterWidget::render
    participant B as ratatui Buffer
    participant P as Paragraph::render

    F->>F: "guard: height/width == 0?"
    F->>B: pre-clear loop set every cell to space with footer_bg
    F->>F: build left_spans, spacer_span, right_spans
    F->>P: Paragraph::new(spans).style(footer_bg)
    P->>B: paint spans over cleared cells
Loading

Reviews (2): Last reviewed commit: "fix(tui): clear footer cells before rend..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request aims to prevent stale glyphs in the footer row by repainting the entire footer area before rendering the spans, and adds a corresponding regression test. However, the reviewer pointed out that rendering a Block with a background style only updates the background color and does not clear the cell symbols (characters). To properly clear stale characters, the reviewer suggests explicitly overwriting each cell in the footer area with a space character.

Comment thread crates/tui/src/tui/widgets/footer.rs Outdated
Comment on lines +579 to +581
Block::default()
.style(Style::default().bg(self.props.footer_bg))
.render(area, buf);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

In ratatui, rendering a Block with a background style (via Block::default().style(...)) only updates the style (specifically the background color) of the cells in the buffer. It does not clear or reset the symbol (the character) of those cells.

If there are cells in the footer row that are not explicitly overwritten by the subsequent Paragraph render (for example, due to unicode width calculation mismatches or layout constraints), those cells will still retain their stale symbols from the previous frame, even though their background color is updated.

Additionally, the regression test render_clears_stale_cells_across_entire_footer_row passes only because the Paragraph's all_spans (which includes the spacer_span of spaces) happens to cover the entire available_width of 48 cells, thereby overwriting all the seeded 'X' characters. The Block render itself is not what clears the 'X' symbols.

To actually clear the symbols of the entire row and set the background style, we should explicitly overwrite each cell in the area with a space character styled with the footer background color.

        for y in area.top()..area.bottom() {
            for x in area.left()..area.right() {
                buf[(x, y)]
                    .set_symbol(" ")
                    .set_style(Style::default().bg(self.props.footer_bg));
            }
        }

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in 129c9fc. I switched the footer pre-pass from Block::render to explicitly writing a space plus the footer background into every footer cell before rendering the spans, so stale symbols are cleared even if the later paragraph render leaves any cells untouched. Re-ran the two footer regression tests after the change and both pass.

Copy link
Copy Markdown
Owner

@Hmbown Hmbown left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean defensive fix. Adds a pre-clear loop that blanks every cell in the footer row before painting status-line spans, preventing stale transcript glyphs from surviving in untouched cells. The regression test is well-targeted. APPROVE.

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.

TUI: 输出超页时底部内容被 statusline 覆盖

2 participants