pub struct TerminalScreen {
pub rows: usize,
pub cols: usize,
pub lines: Vec<TerminalLine>,
pub scroll_top: usize,
pub scroll_bottom: usize,
}Expand description
Rectangular visible terminal buffer with an inclusive scroll region.
Self::new maintains lines.len() == rows, every line width equal to
cols, nonzero dimensions, and scroll_top <= scroll_bottom < rows.
Public fields and derived deserialization can bypass these invariants; most
mutation methods index under them and may panic on inconsistent values.
§Examples
use ailloli_ui_terminal_core::{TerminalScreen, TerminalSize, TerminalStyle};
let screen = TerminalScreen::new(TerminalSize::new(24, 80), TerminalStyle::default());
assert_eq!((screen.rows, screen.cols, screen.lines.len()), (24, 80, 24));Fields§
§rows: usizeVisible row count; normally nonzero and equal to lines.len().
cols: usizeVisible column count; normally nonzero and equal to every line length.
lines: Vec<TerminalLine>Visible rows in top-to-bottom order.
scroll_top: usizeInclusive first row of the active scroll region.
scroll_bottom: usizeInclusive last row of the active scroll region.
Implementations§
Source§impl TerminalScreen
impl TerminalScreen
Sourcepub fn new(size: TerminalSize, style: TerminalStyle) -> Self
pub fn new(size: TerminalSize, style: TerminalStyle) -> Self
Creates a blank rectangular screen and full-height scroll region.
Zero dimensions are clamped to one. Every cell is a narrow styled space.
§Examples
use ailloli_ui_terminal_core::{TerminalScreen, TerminalSize, TerminalStyle};
let screen = TerminalScreen::new(TerminalSize { rows: 0, cols: 0 }, TerminalStyle::default());
assert_eq!((screen.rows, screen.cols, screen.scroll_bottom), (1, 1, 0));Sourcepub fn size(&self) -> TerminalSize
pub fn size(&self) -> TerminalSize
Returns dimensions with zero public-field values clamped to one.
It does not inspect lines or repair an inconsistent screen.
§Examples
use ailloli_ui_terminal_core::{TerminalScreen, TerminalSize, TerminalStyle};
let screen = TerminalScreen::new(TerminalSize::new(2, 3), TerminalStyle::default());
assert_eq!(screen.size(), TerminalSize::new(2, 3));Sourcepub fn line(&self, row: usize) -> Option<&TerminalLine>
pub fn line(&self, row: usize) -> Option<&TerminalLine>
Borrows a zero-based physical row, or None outside lines.
§Examples
use ailloli_ui_terminal_core::{TerminalScreen, TerminalSize, TerminalStyle};
let screen = TerminalScreen::new(TerminalSize::new(2, 3), TerminalStyle::default());
assert!(screen.line(1).is_some() && screen.line(2).is_none());Sourcepub fn cell(&self, row: usize, col: usize) -> Option<&TerminalCell>
pub fn cell(&self, row: usize, col: usize) -> Option<&TerminalCell>
Borrows a zero-based cell, or None when either index is absent.
§Examples
use ailloli_ui_terminal_core::{TerminalScreen, TerminalSize, TerminalStyle};
let screen = TerminalScreen::new(TerminalSize::new(2, 3), TerminalStyle::default());
assert!(screen.cell(1, 2).is_some() && screen.cell(2, 0).is_none());Sourcepub fn clear_screen(
&mut self,
style: TerminalStyle,
damage: &mut TerminalDamage,
)
pub fn clear_screen( &mut self, style: TerminalStyle, damage: &mut TerminalDamage, )
Blanks every retained line and requests full-grid/cursor repaint.
Line lengths are preserved, soft-wrap markers are cleared, and the damage title flag is not changed.
§Examples
use ailloli_ui_terminal_core::{TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let mut screen = TerminalScreen::new(TerminalSize::new(1, 2), TerminalStyle::default());
let mut damage = TerminalDamage::clean(); screen.clear_screen(TerminalStyle::default(), &mut damage);
assert!(damage.full && damage.cursor_dirty);Sourcepub fn clear_line(
&mut self,
row: usize,
style: TerminalStyle,
damage: &mut TerminalDamage,
)
pub fn clear_line( &mut self, row: usize, style: TerminalStyle, damage: &mut TerminalDamage, )
Blanks one retained row and marks it dirty.
An index outside lines is a no-op, even if below the public rows
field. The row’s soft-wrap marker is cleared.
§Examples
use ailloli_ui_terminal_core::{TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let mut screen = TerminalScreen::new(TerminalSize::new(1, 2), TerminalStyle::default());
let mut damage = TerminalDamage::clean(); screen.clear_line(0, TerminalStyle::default(), &mut damage);
assert_eq!(damage.dirty_lines, vec![0]);Sourcepub fn set_scroll_region(&mut self, top: usize, bottom: usize)
pub fn set_scroll_region(&mut self, top: usize, bottom: usize)
Sets an inclusive scroll region after clamping both bounds to the last row.
If the clamped top exceeds the clamped bottom, the full-height region is restored. No cursor movement or damage is produced. On an invalid zero-row public state, both bounds become zero.
§Examples
use ailloli_ui_terminal_core::{TerminalScreen, TerminalSize, TerminalStyle};
let mut screen = TerminalScreen::new(TerminalSize::new(5, 2), TerminalStyle::default());
screen.set_scroll_region(1, 3);
assert_eq!((screen.scroll_top, screen.scroll_bottom), (1, 3));Sourcepub fn reset_scroll_region(&mut self)
pub fn reset_scroll_region(&mut self)
Restores the inclusive scroll region to all declared rows.
For rows == 0 (possible only through public mutation/deserialization),
both bounds become zero.
§Examples
use ailloli_ui_terminal_core::{TerminalScreen, TerminalSize, TerminalStyle};
let mut screen = TerminalScreen::new(TerminalSize::new(4, 2), TerminalStyle::default());
screen.set_scroll_region(1, 2); screen.reset_scroll_region();
assert_eq!((screen.scroll_top, screen.scroll_bottom), (0, 3));Sourcepub fn put_narrow(
&mut self,
row: usize,
col: usize,
text: impl Into<String>,
style: TerminalStyle,
hyperlink: Option<TerminalHyperlinkId>,
damage: &mut TerminalDamage,
)
pub fn put_narrow( &mut self, row: usize, col: usize, text: impl Into<String>, style: TerminalStyle, hyperlink: Option<TerminalHyperlinkId>, damage: &mut TerminalDamage, )
Writes one narrow cell after clearing any intersecting wide pair.
Text is stored verbatim without Unicode-width validation. Out-of-range row/column values are no-ops and produce no damage.
§Panics
May panic if public fields/lines violate the screen invariants.
§Examples
use ailloli_ui_terminal_core::{TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let style = TerminalStyle::default();
let mut screen = TerminalScreen::new(TerminalSize::new(1, 2), style);
screen.put_narrow(0, 1, "A", style, None, &mut TerminalDamage::clean());
assert_eq!(screen.cell(0, 1).unwrap().text, "A");Sourcepub fn put_wide(
&mut self,
row: usize,
col: usize,
text: impl Into<String>,
style: TerminalStyle,
hyperlink: Option<TerminalHyperlinkId>,
damage: &mut TerminalDamage,
)
pub fn put_wide( &mut self, row: usize, col: usize, text: impl Into<String>, style: TerminalStyle, hyperlink: Option<TerminalHyperlinkId>, damage: &mut TerminalDamage, )
Writes a leading/trailing two-cell pair after clearing intersecting pairs.
Text is stored verbatim without Unicode-width validation. A pair that does not fit, including one starting at the last column, is a no-op. Both cells receive the same optional hyperlink.
§Panics
In debug builds col + 1 can panic on theoretical usize overflow.
The method can also panic if public screen fields violate invariants.
§Examples
use ailloli_ui_terminal_core::{CellWidth, TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let style = TerminalStyle::default();
let mut screen = TerminalScreen::new(TerminalSize::new(1, 2), style);
screen.put_wide(0, 0, "界", style, None, &mut TerminalDamage::clean());
assert_eq!(screen.cell(0, 1).unwrap().width, CellWidth::WideTrailing);Sourcepub fn append_combining(
&mut self,
row: usize,
col: usize,
mark: char,
damage: &mut TerminalDamage,
)
pub fn append_combining( &mut self, row: usize, col: usize, mark: char, damage: &mut TerminalDamage, )
Appends one Unicode scalar to a cell’s text.
If col names a wide trailing cell, the mark is appended to its leading
neighbor. An exact blank’s space is removed first. The scalar is not
validated as a combining mark. Out-of-range coordinates are no-ops.
§Panics
May panic if public screen fields/lines violate invariants.
§Examples
use ailloli_ui_terminal_core::{TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let mut screen = TerminalScreen::new(TerminalSize::new(1, 1), TerminalStyle::default());
screen.append_combining(0, 0, '\u{301}', &mut TerminalDamage::clean());
assert_eq!(screen.cell(0, 0).unwrap().text, "\u{301}");Sourcepub fn set_line_wrapped_from_previous(&mut self, row: usize, wrapped: bool)
pub fn set_line_wrapped_from_previous(&mut self, row: usize, wrapped: bool)
Sets one row’s soft-wrap provenance without recording damage.
An index outside lines is a no-op.
§Examples
use ailloli_ui_terminal_core::{TerminalScreen, TerminalSize, TerminalStyle};
let mut screen = TerminalScreen::new(TerminalSize::new(2, 2), TerminalStyle::default());
screen.set_line_wrapped_from_previous(1, true);
assert!(screen.line(1).unwrap().wrapped_from_previous);Sourcepub fn scroll_up(
&mut self,
count: usize,
style: TerminalStyle,
damage: &mut TerminalDamage,
) -> Vec<TerminalLine>
pub fn scroll_up( &mut self, count: usize, style: TerminalStyle, damage: &mut TerminalDamage, ) -> Vec<TerminalLine>
Scrolls the inclusive region upward by at most its height.
New bottom rows are styled blanks. Removed rows are returned only when the scroll region spans the complete screen; partial-region rows are discarded. Count zero still marks the whole region dirty.
§Panics
May panic or overflow if public screen/region fields violate invariants.
§Examples
use ailloli_ui_terminal_core::{TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let style = TerminalStyle::default();
let mut screen = TerminalScreen::new(TerminalSize::new(2, 2), style);
let removed = screen.scroll_up(1, style, &mut TerminalDamage::clean());
assert_eq!(removed.len(), 1);Sourcepub fn clear_line_range(
&mut self,
row: usize,
start: usize,
end_inclusive: usize,
style: TerminalStyle,
damage: &mut TerminalDamage,
)
pub fn clear_line_range( &mut self, row: usize, start: usize, end_inclusive: usize, style: TerminalStyle, damage: &mut TerminalDamage, )
Blanks an inclusive column range and both halves of intersecting wide cells.
Bounds are clamped to the last declared column. An absent row, zero columns, or a range whose clamped start exceeds end is a no-op.
§Panics
May panic if public fields/line widths violate screen invariants.
§Examples
use ailloli_ui_terminal_core::{TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let style = TerminalStyle::default();
let mut screen = TerminalScreen::new(TerminalSize::new(1, 3), style);
screen.put_narrow(0, 1, "x", style, None, &mut TerminalDamage::clean());
screen.clear_line_range(0, 1, 99, style, &mut TerminalDamage::clean());
assert_eq!(screen.line(0).unwrap().plain_text(), " ");Sourcepub fn erase_chars(
&mut self,
row: usize,
col: usize,
count: usize,
style: TerminalStyle,
damage: &mut TerminalDamage,
)
pub fn erase_chars( &mut self, row: usize, col: usize, count: usize, style: TerminalStyle, damage: &mut TerminalDamage, )
Delegates in-row character erasure and marks an existing row dirty.
A missing row is a no-op. A valid row is marked dirty even when count
is zero or col is out of range. See TerminalLine::erase_chars for
wide-cell and overflow behavior.
§Examples
use ailloli_ui_terminal_core::{TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let style = TerminalStyle::default(); let mut damage = TerminalDamage::clean();
let mut screen = TerminalScreen::new(TerminalSize::new(1, 2), style);
screen.erase_chars(0, 0, 1, style, &mut damage);
assert_eq!(damage.dirty_lines, vec![0]);Sourcepub fn delete_chars(
&mut self,
row: usize,
col: usize,
count: usize,
style: TerminalStyle,
damage: &mut TerminalDamage,
)
pub fn delete_chars( &mut self, row: usize, col: usize, count: usize, style: TerminalStyle, damage: &mut TerminalDamage, )
Deletes cells within one row, pads its right edge, and marks it dirty.
A missing row is a no-op. A valid row is marked even for an otherwise no-op count/column. Line length is preserved.
§Examples
use ailloli_ui_terminal_core::{TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let style = TerminalStyle::default(); let mut screen = TerminalScreen::new(TerminalSize::new(1, 2), style);
screen.put_narrow(0, 0, "x", style, None, &mut TerminalDamage::clean());
screen.delete_chars(0, 0, 1, style, &mut TerminalDamage::clean());
assert_eq!(screen.line(0).unwrap().plain_text(), " ");Sourcepub fn insert_blank_chars(
&mut self,
row: usize,
col: usize,
count: usize,
style: TerminalStyle,
damage: &mut TerminalDamage,
)
pub fn insert_blank_chars( &mut self, row: usize, col: usize, count: usize, style: TerminalStyle, damage: &mut TerminalDamage, )
Inserts blanks within one row, discards its right edge, and marks it dirty.
A missing row is a no-op. A valid row is marked even for an otherwise no-op count/column. Line length is preserved.
§Examples
use ailloli_ui_terminal_core::{TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let style = TerminalStyle::default(); let mut screen = TerminalScreen::new(TerminalSize::new(1, 2), style);
screen.put_narrow(0, 0, "x", style, None, &mut TerminalDamage::clean());
screen.insert_blank_chars(0, 0, 1, style, &mut TerminalDamage::clean());
assert_eq!(screen.line(0).unwrap().plain_text(), " x");Sourcepub fn scroll_down(
&mut self,
count: usize,
style: TerminalStyle,
damage: &mut TerminalDamage,
)
pub fn scroll_down( &mut self, count: usize, style: TerminalStyle, damage: &mut TerminalDamage, )
Scrolls the inclusive region downward by at most its height.
Bottom rows are discarded and styled blank rows appear at the top. Count zero still marks the complete region dirty; removed rows are not returned for scrollback.
§Panics
May panic or overflow if public screen/region fields violate invariants.
§Examples
use ailloli_ui_terminal_core::{TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let style = TerminalStyle::default(); let mut damage = TerminalDamage::clean();
let mut screen = TerminalScreen::new(TerminalSize::new(2, 2), style);
screen.scroll_down(1, style, &mut damage);
assert_eq!(damage.dirty_lines, vec![0, 1]);Sourcepub fn insert_lines(
&mut self,
row: usize,
count: usize,
style: TerminalStyle,
damage: &mut TerminalDamage,
)
pub fn insert_lines( &mut self, row: usize, count: usize, style: TerminalStyle, damage: &mut TerminalDamage, )
Inserts blank rows at row within the scroll region.
Rows at the region bottom are discarded. Count is clamped to the suffix
height; zero still marks row..=scroll_bottom dirty. A row outside the
region is a no-op.
§Panics
May panic or overflow if public screen/region fields violate invariants.
§Examples
use ailloli_ui_terminal_core::{TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let style = TerminalStyle::default(); let mut screen = TerminalScreen::new(TerminalSize::new(3, 2), style);
screen.insert_lines(1, 1, style, &mut TerminalDamage::clean());
assert_eq!(screen.lines.len(), 3);Sourcepub fn delete_lines(
&mut self,
row: usize,
count: usize,
style: TerminalStyle,
damage: &mut TerminalDamage,
)
pub fn delete_lines( &mut self, row: usize, count: usize, style: TerminalStyle, damage: &mut TerminalDamage, )
Deletes rows at row within the scroll region and appends blank rows.
Count is clamped to the region suffix; zero still marks the suffix dirty. A row outside the active region is a no-op. Removed rows are discarded.
§Panics
May panic or overflow if public screen/region fields violate invariants.
§Examples
use ailloli_ui_terminal_core::{TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let style = TerminalStyle::default(); let mut screen = TerminalScreen::new(TerminalSize::new(3, 2), style);
screen.delete_lines(1, usize::MAX, style, &mut TerminalDamage::clean());
assert_eq!(screen.lines.len(), 3);Sourcepub fn resize(
&mut self,
size: TerminalSize,
style: TerminalStyle,
cursor: &mut TerminalCursor,
damage: &mut TerminalDamage,
)
pub fn resize( &mut self, size: TerminalSize, style: TerminalStyle, cursor: &mut TerminalCursor, damage: &mut TerminalDamage, )
Resizes without reflow, preserving the old top-left rectangle.
Zero dimensions clamp to one. Right/bottom cells are discarded, new cells/rows are styled blanks, the scroll region resets to full height, the cursor clamps into bounds, and full/cursor damage is requested. Scrollback is not modified.
§Examples
use ailloli_ui_terminal_core::{TerminalCursor, TerminalDamage, TerminalScreen, TerminalSize, TerminalStyle};
let style = TerminalStyle::default(); let mut screen = TerminalScreen::new(TerminalSize::new(2, 2), style);
let mut cursor = TerminalCursor { row: 9, col: 9, ..TerminalCursor::new() };
screen.resize(TerminalSize::new(1, 3), style, &mut cursor, &mut TerminalDamage::clean());
assert_eq!((screen.rows, screen.cols, cursor.row, cursor.col), (1, 3, 0, 2));Trait Implementations§
Source§impl Clone for TerminalScreen
impl Clone for TerminalScreen
Source§fn clone(&self) -> TerminalScreen
fn clone(&self) -> TerminalScreen
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more