termwiz: add ClearLine change (#8124)

This commit is contained in:
ZhongYu Li 2026-09-12 19:38:23 +08:00 committed by GitHub
parent f6f0727893
commit 2afb836403
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 77 additions and 0 deletions

View File

@ -385,6 +385,19 @@ impl TerminfoRenderer {
out.write_all(buf.as_slice())?;
}
}
Change::ClearLine(color) => {
let defaults = CellAttributes::default().set_background(*color).clone();
if self.current_attr != defaults {
self.pending_attr = Some(defaults);
self.flush_pending_attr(out)?;
}
self.pending_attr = None;
write!(
out,
"{}",
CSI::Edit(Edit::EraseInLine(EraseInLine::EraseLine))
)?;
}
Change::ClearToEndOfLine(color) => {
// ClearScreen implicitly resets all to default
let defaults = CellAttributes::default().set_background(*color).clone();
@ -1012,6 +1025,27 @@ mod test {
assert_eq!(out.renderer.current_attr, CellAttributes::default());
}
#[test]
fn clear_line() {
let mut out = FakeTerm::new(xterm_terminfo());
out.render(&[Change::ClearLine(AnsiColor::Maroon.into())])
.unwrap();
assert_eq!(
out.parse(),
vec![
Action::CSI(CSI::Sgr(Sgr::Background(AnsiColor::Maroon.into()))),
Action::CSI(CSI::Edit(Edit::EraseInLine(EraseInLine::EraseLine))),
]
);
assert_eq!(
out.renderer.current_attr,
CellAttributes::default()
.set_background(AnsiColor::Maroon)
.clone()
);
}
#[test]
fn clear_screen_bce() {
let mut out = FakeTerm::new_with_size(xterm_terminfo(), 4, 3);

View File

@ -328,6 +328,19 @@ impl WindowsConsoleRenderer {
);
buffer.set_cursor(0, 0, out)?;
}
Change::ClearLine(color) => {
let attr = CellAttributes::default()
.set_background(color.clone())
.clone();
buffer.fill(
' ',
to_attr_word(&self.capabilities, &attr),
0,
buffer.cursor_y,
cols,
);
}
Change::ClearToEndOfLine(color) => {
let attr = CellAttributes::default()
.set_background(color.clone())

View File

@ -45,6 +45,9 @@ pub enum Change {
/// Implicitly clears all attributes prior to clearing the screen.
/// Moves the cursor to the home position (top left).
ClearScreen(ColorAttribute),
/// Clear the entire current line. The background color is set to the
/// provided color. The cursor position remains unchanged.
ClearLine(ColorAttribute),
/// Clear from the current cursor X position to the rightmost
/// edge of the screen. The background color is set to the
/// provided color. The cursor position remains unchanged.
@ -218,6 +221,7 @@ impl ChangeSequence {
| Change::CursorColor(_)
| Change::CursorShape(_)
| Change::CursorVisibility(_)
| Change::ClearLine(_)
| Change::ClearToEndOfLine(_)
| Change::Title(_)
| Change::LineAttribute(_)

View File

@ -305,6 +305,7 @@ impl Surface {
Change::Attribute(change) => self.attributes.apply_change(change),
Change::CursorPosition { x, y } => self.set_cursor_pos(x, y),
Change::ClearScreen(color) => self.clear_screen(*color),
Change::ClearLine(color) => self.clear_line(*color),
Change::ClearToEndOfLine(color) => self.clear_eol(*color),
Change::ClearToEndOfScreen(color) => self.clear_eos(*color),
Change::CursorColor(color) => self.cursor_color = *color,
@ -401,6 +402,12 @@ impl Surface {
self.lines[self.ypos].fill_range(self.xpos..self.width, &cleared, self.seqno);
}
fn clear_line(&mut self, color: ColorAttribute) {
self.attributes = CellAttributes::default().set_background(color).clone();
let cleared = Cell::new(' ', self.attributes.clone());
self.lines[self.ypos].fill_range(0..self.width, &cleared, self.seqno);
}
fn scroll_screen_up(&mut self) {
self.lines.remove(0);
self.lines.push(Line::with_width(self.width, self.seqno));
@ -1015,6 +1022,25 @@ mod test {
assert_eq!(s.screen_chars_to_string(), " \nw\nfoo\n");
}
#[test]
fn clear_line() {
let mut s = Surface::new(3, 3);
s.add_change("helwowfoo");
s.add_change(Change::CursorPosition {
x: Position::Absolute(1),
y: Position::Absolute(1),
});
s.add_change(Change::ClearLine(AnsiColor::Maroon.into()));
assert_eq!(s.xpos, 1);
assert_eq!(s.ypos, 1);
assert_eq!(s.screen_chars_to_string(), "hel\n \nfoo\n");
assert_eq!(
s.lines[1].get_cell(0).unwrap().attrs().background(),
ColorAttribute::PaletteIndex(1)
);
}
#[test]
fn clear_eos() {
let mut s = Surface::new(3, 3);