fix(tui): clear resize repaint artifacts

This commit is contained in:
Felipe Coury
2026-05-09 12:28:49 -03:00
parent 328c5303f3
commit 5ff98050f5
2 changed files with 42 additions and 2 deletions
+32 -1
View File
@@ -135,7 +135,9 @@ where
let line_wrapped = match wrap_policy {
HistoryLineWrapPolicy::Terminal => vec![line.clone()],
HistoryLineWrapPolicy::PreWrap
if line_contains_url_like(line) && !line_has_mixed_url_and_non_url_tokens(line) =>
if is_preformatted_box_table_line(line)
|| (line_contains_url_like(line)
&& !line_has_mixed_url_and_non_url_tokens(line)) =>
{
vec![line.clone()]
}
@@ -246,6 +248,19 @@ where
Ok(())
}
fn is_preformatted_box_table_line(line: &Line<'_>) -> bool {
let text: String = line
.spans
.iter()
.map(|span| span.content.as_ref())
.collect();
let trimmed = text.trim_start();
(trimmed.starts_with('│') && trimmed.matches('│').count() >= 2)
|| trimmed.starts_with('┌')
|| trimmed.starts_with('├')
|| trimmed.starts_with('└')
}
/// Render a single wrapped history line: clear continuation rows for wide lines,
/// set foreground/background colors, and write styled spans. Caller is responsible
/// for cursor positioning and any leading `\r\n`.
@@ -442,6 +457,22 @@ mod tests {
use ratatui::layout::Rect;
use ratatui::style::Color;
#[test]
fn detects_preformatted_box_table_lines() {
assert!(is_preformatted_box_table_line(&Line::from(
"│ Link │ a (https://example.com/a) │"
)));
assert!(is_preformatted_box_table_line(&Line::from(
"┌──────┬────────┐"
)));
assert!(!is_preformatted_box_table_line(&Line::from(
"plain text with https://example.com"
)));
assert!(!is_preformatted_box_table_line(&Line::from(
" │ quoted text with https://example.com"
)));
}
#[test]
fn writes_bold_then_regular_spans() {
use ratatui::style::Stylize;
+10 -1
View File
@@ -770,7 +770,16 @@ impl Tui {
}
if area != terminal.viewport_area {
let clear_position = Position::new(/*x*/ 0, previous_area.y.min(area.y));
let terminal_resized = size != terminal.last_known_screen_size;
// Terminal emulators can natively reflow visible scrollback before Codex gets the
// resize event. When that happens, ratatui's diff buffer has no record of the glyphs
// now sitting under blank cells, so repaint from a fully-cleared visible screen.
let clear_y = if terminal_resized {
0
} else {
previous_area.y.min(area.y)
};
let clear_position = Position::new(/*x*/ 0, clear_y);
terminal.set_viewport_area(area);
terminal.clear_after_position(clear_position)?;
needs_full_repaint = true;