Struct TerminalScreen

Source
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: usize

Visible row count; normally nonzero and equal to lines.len().

§cols: usize

Visible column count; normally nonzero and equal to every line length.

§lines: Vec<TerminalLine>

Visible rows in top-to-bottom order.

§scroll_top: usize

Inclusive first row of the active scroll region.

§scroll_bottom: usize

Inclusive last row of the active scroll region.

Implementations§

Source§

impl TerminalScreen

Source

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));
Source

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));
Source

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());
Source

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());
Source

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);
Source

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]);
Source

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));
Source

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));
Source

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");
Source

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);
Source

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}");
Source

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);
Source

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);
Source

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(), "   ");
Source

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]);
Source

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(), "  ");
Source

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");
Source

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]);
Source

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);
Source

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);
Source

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

Source§

fn clone(&self) -> TerminalScreen

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for TerminalScreen

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for TerminalScreen

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for TerminalScreen

Source§

fn eq(&self, other: &TerminalScreen) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for TerminalScreen

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Eq for TerminalScreen

Source§

impl StructuralPartialEq for TerminalScreen

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,