pub struct TerminalState {Show 19 fields
pub screen: TerminalScreen,
pub alternate_screen: TerminalScreen,
pub active_screen: ActiveScreen,
pub cursor: TerminalCursor,
pub saved_cursor: Option<TerminalCursor>,
pub current_style: TerminalStyle,
pub scrollback: TerminalScrollback,
pub modes: TerminalModes,
pub title: Option<String>,
pub cwd_uri: Option<String>,
pub shell: ShellExecutionState,
pub diagnostics: Vec<TerminalDiagnostic>,
pub hyperlinks: Vec<TerminalHyperlink>,
pub active_hyperlink: Option<TerminalHyperlinkId>,
pub damage: TerminalDamage,
pub warnings: Vec<TerminalWarning>,
pub security: TerminalSecurityPolicy,
pub pending_cursor_addressed_write: bool,
pub pending_prompt_carriage_return: bool,
}Expand description
Complete mutable terminal state.
Both screen buffers share one cursor, style, mode set, hyperlink selection, shell state, warning list, and damage tracker. Switching buffers therefore does not preserve an independent alternate cursor. Normal-screen top-region scrolling contributes to scrollback; alternate-screen scrolling does not.
Public fields and deserialization do not validate rectangular screens, nonzero dimensions, cursor bounds, hyperlink references, scroll regions, or shell lifecycle consistency. Restore constructor invariants before invoking mutation methods on untrusted serialized state.
§Examples
use ailloli_ui_terminal_core::{ActiveScreen, TerminalState};
let mut state = TerminalState::new();
state.write_str("hello");
assert_eq!(state.active_screen, ActiveScreen::Normal);
assert!(state.screen.lines[0].plain_text().starts_with("hello"));Fields§
§screen: TerminalScreenPrimary screen buffer.
alternate_screen: TerminalScreenEphemeral alternate screen buffer.
active_screen: ActiveScreenBuffer targeted by active-screen operations.
cursor: TerminalCursorShared cursor for whichever screen is active.
saved_cursor: Option<TerminalCursor>Cursor saved by save-cursor operations, or None before the first save.
current_style: TerminalStyleStyle assigned to newly written or erased cells.
scrollback: TerminalScrollbackRetained lines removed from the top of the normal screen.
modes: TerminalModesInput/output mode flags, including the mirrored alternate-screen flag.
title: Option<String>Terminal title, or None; not intrinsically redacted.
cwd_uri: Option<String>Current working-directory URI, or None; not intrinsically redacted.
shell: ShellExecutionStateShell process, prompt, command history, and queued integration events.
diagnostics: Vec<TerminalDiagnostic>Most recently stored output classification diagnostics.
hyperlinks: Vec<TerminalHyperlink>Append-only hyperlink registry; no automatic deduplication or limit.
active_hyperlink: Option<TerminalHyperlinkId>Hyperlink assigned to newly written cells, or None.
damage: TerminalDamageRendering changes accumulated since the last external reset.
warnings: Vec<TerminalWarning>Append-only blocked/unsupported warning list.
security: TerminalSecurityPolicyPermissions consulted by title, hyperlink, and parser operations.
pending_cursor_addressed_write: boolWhether the next cell mutation should break surrounding soft-wrap links.
pending_prompt_carriage_return: boolWhether a carriage return may be the start of a live-prompt redraw.
Implementations§
Source§impl TerminalState
impl TerminalState
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates a state from TerminalConfig::default.
§Examples
use ailloli_ui_terminal_core::{TerminalSize, TerminalState};
let state = TerminalState::new();
assert_eq!(state.screen.size(), TerminalSize::new(24, 80));Sourcepub fn with_config(config: TerminalConfig) -> Self
pub fn with_config(config: TerminalConfig) -> Self
Creates empty normal and alternate screens from config.
Zero dimensions are independently clamped to one. The cursor begins at
(0, 0), the normal screen is active, style/modes are defaults, damage is
initially full, and all optional text and append-only collections are empty.
§Panics
Allocating the two rectangular screen buffers can panic or abort if the requested positive dimensions exceed available memory or their product overflows an allocation layout.
§Examples
use ailloli_ui_terminal_core::{TerminalConfig, TerminalSize, TerminalState};
let state = TerminalState::with_config(TerminalConfig {
size: TerminalSize { rows: 0, cols: 5 },
..Default::default()
});
assert_eq!(state.screen.size(), TerminalSize::new(1, 5));Sourcepub fn active_screen(&self) -> &TerminalScreen
pub fn active_screen(&self) -> &TerminalScreen
Borrows the buffer selected by Self::active_screen.
§Examples
use ailloli_ui_terminal_core::{ActiveScreen, TerminalState};
let mut state = TerminalState::new();
assert!(std::ptr::eq(state.active_screen(), &state.screen));
state.active_screen = ActiveScreen::Alternate;
assert!(std::ptr::eq(state.active_screen(), &state.alternate_screen));Sourcepub fn move_cursor_up(&mut self, count: usize)
pub fn move_cursor_up(&mut self, count: usize)
Moves the cursor up by at most count rows, saturating at row zero.
During a recognized live-prompt carriage-return redraw, movement is also clamped to the visible prompt start. Even a zero movement marks cursor damage and makes the next cell write break surrounding soft-wrap links.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.set_cursor_position(3, 0);
state.move_cursor_up(usize::MAX);
assert_eq!(state.cursor.row, 0);Sourcepub fn move_cursor_down(&mut self, count: usize)
pub fn move_cursor_down(&mut self, count: usize)
Moves down by count, clamped to the active screen’s final row.
Even a zero movement marks cursor damage and a cursor-addressed pending write.
§Panics
cursor.row + count uses ordinary usize arithmetic and can overflow for
an invalid/out-of-bounds public cursor or extreme count when checks are enabled.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.move_cursor_down(usize::MAX / 2);
assert_eq!(state.cursor.row, state.screen.rows - 1);Sourcepub fn move_cursor_next_line(&mut self, count: usize)
pub fn move_cursor_next_line(&mut self, count: usize)
Moves down by count, clamps to the last row, and sets column zero.
§Panics
The row addition can overflow under the same invalid/extreme inputs as
Self::move_cursor_down.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.set_cursor_position(0, 9);
state.move_cursor_next_line(2);
assert_eq!((state.cursor.row, state.cursor.col), (2, 0));Sourcepub fn move_cursor_previous_line(&mut self, count: usize)
pub fn move_cursor_previous_line(&mut self, count: usize)
Moves up by count with saturation and sets column zero.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.set_cursor_position(2, 9);
state.move_cursor_previous_line(1);
assert_eq!((state.cursor.row, state.cursor.col), (1, 0));Sourcepub fn move_cursor_forward(&mut self, count: usize)
pub fn move_cursor_forward(&mut self, count: usize)
Moves right by count, clamped to the active screen’s final column.
§Panics
cursor.col + count can overflow for invalid/extreme public values when
overflow checks are enabled.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.move_cursor_forward(3);
assert_eq!(state.cursor.col, 3);Sourcepub fn move_cursor_back(&mut self, count: usize)
pub fn move_cursor_back(&mut self, count: usize)
Moves left by count, saturating at column zero.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.set_cursor_position(0, 2);
state.move_cursor_back(9);
assert_eq!(state.cursor.col, 0);Sourcepub fn set_cursor_position(&mut self, row: usize, col: usize)
pub fn set_cursor_position(&mut self, row: usize, col: usize)
Sets a zero-based position, clamped to the active screen bounds.
It also marks cursor damage and makes the next cell mutation break the surrounding soft-wrap relationship.
§Panics
A publicly constructed/deserialized active screen with zero rows or
columns underflows the size - 1 bound when checks are enabled.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.set_cursor_position(usize::MAX, usize::MAX);
assert_eq!(state.cursor.row, state.screen.rows - 1);
assert_eq!(state.cursor.col, state.screen.cols - 1);Sourcepub fn set_cursor_position_ansi(&mut self, row: usize, col: usize)
pub fn set_cursor_position_ansi(&mut self, row: usize, col: usize)
Sets a one-based ANSI row/column, treating zero as the first cell.
Values are converted with saturating subtraction and then clamped.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.set_cursor_position_ansi(2, 3);
assert_eq!((state.cursor.row, state.cursor.col), (1, 2));Sourcepub fn set_cursor_column_ansi(&mut self, col: usize)
pub fn set_cursor_column_ansi(&mut self, col: usize)
Sets the one-based ANSI column while preserving the row.
Zero is normalized to one before conversion.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.set_cursor_column_ansi(4);
assert_eq!(state.cursor.col, 3);Sourcepub fn set_cursor_row_ansi(&mut self, row: usize)
pub fn set_cursor_row_ansi(&mut self, row: usize)
Sets the one-based ANSI row while preserving the column.
Zero is normalized to one before conversion.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.set_cursor_row_ansi(4);
assert_eq!(state.cursor.row, 3);Sourcepub fn save_cursor(&mut self)
pub fn save_cursor(&mut self)
Copies the shared current cursor into the single saved slot.
Repeated calls replace the previous value and do not mark damage.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.set_cursor_position(2, 3);
state.save_cursor();
assert_eq!(state.saved_cursor, Some(state.cursor));Sourcepub fn restore_cursor(&mut self)
pub fn restore_cursor(&mut self)
Restores and clamps the saved cursor, or does nothing when absent.
A successful restore retains the saved value, marks cursor damage, and makes the next write cursor-addressed.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.set_cursor_position(2, 3); state.save_cursor();
state.set_cursor_position(0, 0); state.restore_cursor();
assert_eq!((state.cursor.row, state.cursor.col), (2, 3));Sourcepub fn set_cursor_visible(&mut self, visible: bool)
pub fn set_cursor_visible(&mut self, visible: bool)
Sets cursor visibility and marks cursor damage, even if unchanged.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.set_cursor_visible(false);
assert!(!state.cursor.visible);Sourcepub fn set_wraparound_mode(&mut self, enabled: bool)
pub fn set_wraparound_mode(&mut self, enabled: bool)
Enables or disables automatic wrapping after the final column.
This setter does not mark rendering damage.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.set_wraparound_mode(false);
assert!(!state.modes.wraparound);Sourcepub fn set_application_cursor_mode(&mut self, enabled: bool)
pub fn set_application_cursor_mode(&mut self, enabled: bool)
Sets application-cursor-key mode without marking damage.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.set_application_cursor_mode(true);
assert!(state.modes.application_cursor);Sourcepub fn set_application_keypad_mode(&mut self, enabled: bool)
pub fn set_application_keypad_mode(&mut self, enabled: bool)
Sets application-keypad mode without marking damage.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.set_application_keypad_mode(true);
assert!(state.modes.application_keypad);Sourcepub fn set_bracketed_paste_mode(&mut self, enabled: bool)
pub fn set_bracketed_paste_mode(&mut self, enabled: bool)
Sets bracketed-paste mode without marking damage.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.set_bracketed_paste_mode(true);
assert!(state.modes.bracketed_paste);Sourcepub fn set_mouse_tracking_mode(&mut self, mode: TerminalMouseTrackingMode)
pub fn set_mouse_tracking_mode(&mut self, mode: TerminalMouseTrackingMode)
Replaces the mouse-tracking mode without marking damage.
§Examples
use ailloli_ui_terminal_core::{TerminalMouseTrackingMode, TerminalState};
let mut state = TerminalState::new();
state.set_mouse_tracking_mode(TerminalMouseTrackingMode::AnyMotion);
assert_eq!(state.modes.mouse_tracking, TerminalMouseTrackingMode::AnyMotion);Sourcepub fn set_sgr_mouse_mode(&mut self, enabled: bool)
pub fn set_sgr_mouse_mode(&mut self, enabled: bool)
Enables or disables SGR mouse-coordinate encoding without marking damage.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.set_sgr_mouse_mode(true);
assert!(state.modes.sgr_mouse);Sourcepub fn write_str(&mut self, text: &str)
pub fn write_str(&mut self, text: &str)
Applies Unicode text and four embedded control characters.
\n, \r, \t, and backspace (U+0008) dispatch to their respective
state operations; every other scalar goes through Self::write_char.
A newline does not imply a carriage return. This helper parses no ANSI or
OSC escape sequences; use a TerminalParser for bytes.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new();
state.write_str("ab\rZ");
assert!(state.screen.lines[0].plain_text().starts_with("Zb"));Sourcepub fn write_char(&mut self, ch: char)
pub fn write_char(&mut self, ch: char)
Writes one Unicode scalar at the shared cursor using the current style/link.
Width-zero scalars are appended to the preceding physical cell (or the current top-left cell when no predecessor exists) without advancing. Scalars wider than one cell occupy a leading/trailing pair when the screen has at least two columns; on a one-column screen they are stored narrow. A wide scalar that does not fit forces a soft wrap even when wraparound mode is disabled. Filling the final column also wraps immediately when wraparound is enabled.
§Panics
This method assumes a rectangular, nonzero active screen and an in-bounds cursor. Publicly corrupted fields can cause indexing/subtraction panics. Cursor-column additions can overflow for invalid extreme values when overflow checks are enabled.
§Examples
use ailloli_ui_terminal_core::{CellWidth, TerminalState};
let mut state = TerminalState::new();
state.write_char('界');
assert_eq!(state.screen.lines[0].cells[0].width, CellWidth::WideLeading);
assert_eq!(state.cursor.col, 2);Sourcepub fn carriage_return(&mut self)
pub fn carriage_return(&mut self)
Moves to column zero and arms live-prompt redraw detection.
The row is unchanged. Cursor damage is marked and the next cell write is considered cursor-addressed, which breaks surrounding soft-wrap links.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.move_cursor_forward(5);
state.carriage_return();
assert_eq!(state.cursor.col, 0);
assert!(state.pending_prompt_carriage_return);Sourcepub fn line_feed(&mut self)
pub fn line_feed(&mut self)
Performs a hard line feed without changing the cursor column.
At or below the active scroll-region bottom it scrolls that region up and
keeps the cursor at the bottom; otherwise it increments the row. The new
line is marked as not soft-wrapped. On the normal screen, lines removed
from a top-anchored region can enter scrollback through Self::scroll_up.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.move_cursor_forward(3);
state.line_feed();
assert_eq!((state.cursor.row, state.cursor.col), (1, 3));Sourcepub fn backspace(&mut self)
pub fn backspace(&mut self)
Moves left by one column without erasing; column zero is a no-op.
A successful move marks cursor damage and a cursor-addressed pending write.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("ab");
state.backspace();
assert_eq!(state.cursor.col, 1);
assert!(state.screen.lines[0].plain_text().starts_with("ab"));Sourcepub fn tab(&mut self)
pub fn tab(&mut self)
Writes spaces up to the next fixed eight-column tab stop.
Stops early after a wrap resets the column to zero. Tabs therefore mutate cells, styles, hyperlinks, cursor position, soft-wrap metadata, and damage; there is no configurable tab-stop table.
§Panics
Computing the next multiple of eight can overflow for a publicly corrupted
cursor near usize::MAX when overflow checks are enabled.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_char('x'); state.tab();
assert_eq!(state.cursor.col, 8);
assert!(state.screen.lines[0].plain_text().starts_with("x "));Sourcepub fn clear_screen(&mut self)
pub fn clear_screen(&mut self)
Fills the active screen with current-style blanks and breaks all soft wraps.
Cursor position, scrollback, title, and shell state are unchanged. Screen clearing marks full damage through the screen helper.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("text"); state.clear_screen();
assert!(state.screen.lines[0].plain_text().trim().is_empty());Sourcepub fn clear_line(&mut self, row: usize)
pub fn clear_line(&mut self, row: usize)
Clears one zero-based active-screen row with current-style blanks.
It breaks soft-wrap links immediately before and after row. An
out-of-range row performs no cell mutation but still clears the pending
cursor-addressed/prompt-redraw flags through wrap-breaking helpers.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("text"); state.clear_line(0);
assert!(state.screen.lines[0].plain_text().trim().is_empty());Sourcepub fn erase_display(&mut self, mode: u16)
pub fn erase_display(&mut self, mode: u16)
Applies ANSI erase-in-display mode on the active screen.
Mode 0 clears cursor-through-end, 1 clears start-through-cursor, and
2 clears the entire screen. Other values do nothing. Valid modes break
affected soft-wrap links and fill with the current style; cursor and
scrollback remain unchanged.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("abc");
state.set_cursor_position(0, 1); state.erase_display(0);
assert!(state.screen.lines[0].plain_text().starts_with("a "));Sourcepub fn erase_line(&mut self, mode: u16)
pub fn erase_line(&mut self, mode: u16)
Applies ANSI erase-in-line mode at the cursor row.
Mode 0 clears cursor-through-end, 1 clears start-through-cursor, and
2 clears the full row. Other values do not erase. A pending live-prompt
carriage-return redraw may first clear its wrapped prompt range and move
the cursor to that range’s start. The prompt-redraw flag is cleared for
every mode.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("abc");
state.set_cursor_position(0, 1); state.erase_line(1);
assert!(state.screen.lines[0].plain_text().starts_with(" c"));Sourcepub fn set_scroll_region(&mut self, top: usize, bottom: usize)
pub fn set_scroll_region(&mut self, top: usize, bottom: usize)
Sets the active screen’s inclusive zero-based scroll region.
Bounds clamp to the final row. If clamped top > bottom, the full-height
region is restored. Cursor and damage are unchanged.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.set_scroll_region(2, 5);
assert_eq!((state.screen.scroll_top, state.screen.scroll_bottom), (2, 5));Sourcepub fn reset_scroll_region(&mut self)
pub fn reset_scroll_region(&mut self)
Restores the active screen’s scroll region to its full declared height.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.set_scroll_region(2, 5);
state.reset_scroll_region();
assert_eq!((state.screen.scroll_top, state.screen.scroll_bottom), (0, 23));Sourcepub fn insert_lines(&mut self, row: usize, count: usize)
pub fn insert_lines(&mut self, row: usize, count: usize)
Inserts current-style blank rows at row within the active scroll region.
The count is clamped to the region suffix, bottom rows are discarded, and surrounding soft-wrap links are broken. A row outside the region is a cell no-op; count zero still marks the valid suffix dirty in the screen.
§Panics
Can panic if public screen lines or scroll-region fields violate their documented invariants.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("x");
state.insert_lines(0, 1);
assert!(state.screen.lines[0].plain_text().trim().is_empty());Sourcepub fn delete_lines(&mut self, row: usize, count: usize)
pub fn delete_lines(&mut self, row: usize, count: usize)
Deletes rows at row within the active scroll region and appends blanks.
Removed rows are discarded rather than added to scrollback. The count is clamped to the suffix; zero still marks a valid suffix dirty. Soft-wrap links throughout the affected suffix are broken first.
§Panics
Can panic if public screen lines or scroll-region fields violate their documented invariants.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("x");
state.delete_lines(0, 1);
assert!(state.screen.lines[0].plain_text().trim().is_empty());
assert!(state.scrollback.is_empty());Sourcepub fn erase_chars(&mut self, count: usize)
pub fn erase_chars(&mut self, count: usize)
Blanks count cells from the cursor without shifting later cells.
Intersecting wide pairs are cleared together, the current style fills blanks, and soft-wrap links around the row are broken. Count zero still marks an existing row dirty through the screen helper.
§Panics
cursor.col + count can overflow inside line erasure when checks are
enabled, and malformed public screen state can cause indexing failures.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("abcd");
state.set_cursor_position(0, 1); state.erase_chars(2);
assert!(state.screen.lines[0].plain_text().starts_with("a d"));Sourcepub fn delete_chars(&mut self, count: usize)
pub fn delete_chars(&mut self, count: usize)
Deletes count cells from the cursor and shifts the row left.
Current-style blanks pad the right edge, line width is preserved, wide pairs are repaired, and surrounding soft-wrap links are broken. Count zero still marks an existing row dirty.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("abcd");
state.set_cursor_position(0, 1); state.delete_chars(2);
assert!(state.screen.lines[0].plain_text().starts_with("ad"));Sourcepub fn insert_blank_chars(&mut self, count: usize)
pub fn insert_blank_chars(&mut self, count: usize)
Inserts count current-style blanks at the cursor and shifts right.
Cells falling off the right edge are discarded, line width is preserved, wide pairs are repaired, and surrounding soft-wrap links are broken. Count zero still marks an existing row dirty.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("ab");
state.set_cursor_position(0, 1); state.insert_blank_chars(2);
assert!(state.screen.lines[0].plain_text().starts_with("a b"));Sourcepub fn scroll_up(&mut self, count: usize)
pub fn scroll_up(&mut self, count: usize)
Scrolls the active inclusive region upward by at most its height.
New bottom rows are current-style blanks. On the normal screen only, rows removed from a full-height region enter scrollback; partial-region and all alternate-screen removals are discarded. Count zero still marks the region dirty.
§Panics
Can panic or overflow if public screen/region fields violate invariants.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("top"); state.scroll_up(1);
assert_eq!(state.scrollback.len(), 1);
assert!(state.scrollback.iter().next().unwrap().plain_text().starts_with("top"));Sourcepub fn scroll_down(&mut self, count: usize)
pub fn scroll_down(&mut self, count: usize)
Scrolls the active inclusive region downward by at most its height.
Current-style blanks appear at the top and removed bottom rows are always discarded. Count zero still marks the region dirty.
§Panics
Can panic or overflow if public screen/region fields violate invariants.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("top"); state.scroll_down(1);
assert!(state.screen.lines[0].plain_text().trim().is_empty());
assert!(state.scrollback.is_empty());Sourcepub fn resize(&mut self, size: TerminalSize)
pub fn resize(&mut self, size: TerminalSize)
Resizes with TerminalResizePolicy::NormalReflow.
§Examples
use ailloli_ui_terminal_core::{TerminalSize, TerminalState};
let mut state = TerminalState::new(); state.resize(TerminalSize::new(10, 40));
assert_eq!(state.active_screen().size(), TerminalSize::new(10, 40));Sourcepub fn resize_with_policy(
&mut self,
size: TerminalSize,
policy: TerminalResizePolicy,
)
pub fn resize_with_policy( &mut self, size: TerminalSize, policy: TerminalResizePolicy, )
Resizes both buffers, reflowing the normal screen and its scrollback.
Zero dimensions clamp to one. Normal-screen soft-wrapped physical rows are reconstructed into logical lines and wrapped to the new width; trailing blank cells/rows not needed by content or cursor may be discarded. The visible window tries to preserve the cursor’s distance from the bottom. Reflow recomputes scrollback and its global counter with saturating arithmetic. The alternate buffer is resized top-left without reflow.
When normal is active, its cursor is mapped through reflow; an alternate resize uses a discarded cursor copy. When alternate is active, normal is reflowed without a live cursor and the shared cursor is clamped by the alternate resize. The saved cursor, if present, is clamped. Both scroll regions reset, and full damage is marked.
TerminalResizePolicy::LivePromptAwareReflow additionally tries to keep
the current visible live prompt group out of scrollback and updates its
global prompt line; see that variant for its activation conditions.
§Panics
Allocation can fail for extreme sizes. Publicly malformed screens or scrollback can also violate the indexing assumptions of reflow.
§Examples
use ailloli_ui_terminal_core::{TerminalResizePolicy, TerminalSize, TerminalState};
let mut state = TerminalState::new(); state.write_str("abcdefgh");
state.resize_with_policy(TerminalSize::new(4, 4), TerminalResizePolicy::NormalReflow);
assert_eq!(state.screen.size(), TerminalSize::new(4, 4));
assert_eq!(state.alternate_screen.size(), TerminalSize::new(4, 4));Sourcepub fn switch_to_alternate_screen(&mut self)
pub fn switch_to_alternate_screen(&mut self)
Selects and clears the alternate screen, resetting the shared cursor.
Every call clears alternate cells with the current style, even when it is already active. Normal cells and scrollback remain intact, but the former normal cursor is not saved automatically. The alternate mode flag is set and full damage is marked.
§Examples
use ailloli_ui_terminal_core::{ActiveScreen, TerminalState};
let mut state = TerminalState::new(); state.write_str("normal");
state.switch_to_alternate_screen(); state.write_str("alternate");
assert_eq!(state.active_screen, ActiveScreen::Alternate);
assert!(state.alternate_screen.lines[0].plain_text().starts_with("alternate"));
assert!(state.screen.lines[0].plain_text().starts_with("normal"));Sourcepub fn switch_to_normal_screen(&mut self)
pub fn switch_to_normal_screen(&mut self)
Selects the normal screen and clamps the shared cursor into its bounds.
The alternate buffer is retained until the next alternate switch clears it. No earlier normal-screen cursor is restored automatically. The mode flag is cleared and full damage is marked.
§Examples
use ailloli_ui_terminal_core::{ActiveScreen, TerminalState};
let mut state = TerminalState::new();
state.switch_to_alternate_screen(); state.switch_to_normal_screen();
assert_eq!(state.active_screen, ActiveScreen::Normal);
assert!(!state.modes.alternate_screen);Sourcepub fn set_title(&mut self, title: impl Into<String>)
pub fn set_title(&mut self, title: impl Into<String>)
Sets the title when allowed, otherwise appends a blocked warning.
Allowed values are stored verbatim, including an empty string, and title damage is marked. A blocked call leaves the existing title and damage unchanged; warnings are not deduplicated or bounded.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.security.allow_title_change = false;
state.set_title("blocked");
assert_eq!(state.title, None);
assert_eq!(state.warnings.len(), 1);Sourcepub fn set_cwd_uri(&mut self, cwd_uri: impl Into<String>)
pub fn set_cwd_uri(&mut self, cwd_uri: impl Into<String>)
Stores a CWD URI and forwards it to shell execution state.
The string is accepted verbatim, including empty or non-URI text. This method performs no security-policy check, marks no rendering damage, and the shell setter queues a CWD-changed event even if the value is unchanged.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.set_cwd_uri("file:///workspace");
assert_eq!(state.cwd_uri.as_deref(), Some("file:///workspace"));
assert_eq!(state.shell.cwd_uri, state.cwd_uri);Sourcepub fn current_global_line_index(&self) -> u64
pub fn current_global_line_index(&self) -> u64
Returns the saturating scrollback-push count plus shared cursor row.
The value identifies the current normal-screen line when state invariants
hold. It is computed the same way while the alternate screen is active,
so it is not an alternate-screen identity. On hypothetical targets where
usize exceeds 64 bits, converting the cursor row truncates high bits.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.move_cursor_down(2);
assert_eq!(state.current_global_line_index(), 2);Sourcepub fn mark_shell_prompt_start(&mut self)
pub fn mark_shell_prompt_start(&mut self)
Marks a shell prompt at Self::current_global_line_index.
This delegates to shell state, which makes the prompt visible and queues
a prompt-start event. It does not consult security.allow_shell_integration.
Callers receiving untrusted private shell controls must enforce that policy.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.mark_shell_prompt_start();
assert!(state.shell.prompt_visible);
assert_eq!(state.shell.last_prompt_line, Some(0));Sourcepub fn start_shell_command(
&mut self,
command_line: impl Into<String>,
cwd_uri: Option<String>,
started_at_ms: Option<u64>,
)
pub fn start_shell_command( &mut self, command_line: impl Into<String>, cwd_uri: Option<String>, started_at_ms: Option<u64>, )
Starts a tracked shell command at the current global line.
A supplied CWD first becomes both the terminal and shell CWD, queuing its
own change event, and is then stored on the command. None inherits the
current terminal CWD. Starting while another command runs implicitly
finishes the old command as unknown through ShellExecutionState.
Times are optional caller-domain milliseconds; strings may be empty.
This method does not enforce security.allow_shell_integration.
§Examples
use ailloli_ui_terminal_core::{CommandStatus, TerminalState};
let mut state = TerminalState::new();
state.start_shell_command("cargo check", Some("file:///repo".into()), Some(10));
let command = state.shell.current_command.as_ref().unwrap();
assert_eq!(command.status, CommandStatus::Running);
assert_eq!(command.cwd_uri.as_deref(), Some("file:///repo"));Sourcepub fn finish_shell_command(
&mut self,
exit_code: Option<i32>,
signal: Option<i32>,
ended_at_ms: Option<u64>,
duration_ms: Option<u64>,
)
pub fn finish_shell_command( &mut self, exit_code: Option<i32>, signal: Option<i32>, ended_at_ms: Option<u64>, duration_ms: Option<u64>, )
Finishes the current shell command at the current global line.
A signal yields interrupted status; otherwise exit zero succeeds,
nonzero fails, and absent signal/code is unknown. The output end clamps
no earlier than its start. A supplied duration wins; otherwise shell state
derives one only when checked ended - started succeeds. With no current
command this is a no-op. The shell-integration security flag is not checked.
§Examples
use ailloli_ui_terminal_core::{CommandStatus, TerminalState};
let mut state = TerminalState::new();
state.start_shell_command("true", None, Some(5));
state.finish_shell_command(Some(0), None, Some(8), None);
assert_eq!(state.shell.last_command.as_ref().unwrap().status, CommandStatus::Succeeded);
assert_eq!(state.shell.last_command.as_ref().unwrap().duration_ms, Some(3));Sourcepub fn set_shell_kind(&mut self, shell_kind: ShellKind)
pub fn set_shell_kind(&mut self, shell_kind: ShellKind)
Sets the shell family and queues a shell-kind event.
This stores duplicate values/events and does not consult the shell- integration security flag.
§Examples
use ailloli_ui_terminal_core::{ShellKind, TerminalState};
let mut state = TerminalState::new(); state.set_shell_kind(ShellKind::Fish);
assert_eq!(state.shell.shell_kind, ShellKind::Fish);Sourcepub fn set_shell_process_status(&mut self, status: TerminalProcessStatus)
pub fn set_shell_process_status(&mut self, status: TerminalProcessStatus)
Sets process status and queues an event without policy validation.
Duplicate or lifecycle-inconsistent values are retained as supplied.
§Examples
use ailloli_ui_terminal_core::{TerminalProcessStatus, TerminalState};
let mut state = TerminalState::new();
state.set_shell_process_status(TerminalProcessStatus::Running);
assert_eq!(state.shell.process_status, TerminalProcessStatus::Running);Sourcepub fn shell_snapshot(&self) -> TerminalShellSnapshot
pub fn shell_snapshot(&self) -> TerminalShellSnapshot
Returns an owned, unredacted shell-state snapshot.
Queued events are excluded, while current/last/history commands and their
command lines/CWDs are cloned verbatim. Use crate::TerminalSnapshot for
configured redaction.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.set_cwd_uri("file:///repo");
assert_eq!(state.shell_snapshot().cwd_uri.as_deref(), Some("file:///repo"));Sourcepub fn classify_terminal_output(&mut self) -> TerminalOutputClassification
pub fn classify_terminal_output(&mut self) -> TerminalOutputClassification
Classifies normal-screen visual text and replaces stored diagnostics.
Classification is deterministic and performs no I/O. The returned value
includes diagnostic events; Self::diagnostics receives a clone of only
its diagnostics. Existing stored diagnostics are replaced, including by
an empty result. See TerminalOutputClassifier::classify for matching,
indexing, complexity, and active-command correlation details.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("error: build failed");
let result = state.classify_terminal_output();
assert_eq!(state.diagnostics, result.diagnostics);
assert!(!result.diagnostics.is_empty());Sourcepub fn clear_terminal_diagnostics(&mut self)
pub fn clear_terminal_diagnostics(&mut self)
Removes all stored diagnostics without touching terminal text or damage.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("error: failed");
state.classify_terminal_output(); state.clear_terminal_diagnostics();
assert!(state.diagnostics.is_empty());Sourcepub fn terminal_diagnostics_snapshot(&self) -> Vec<TerminalDiagnostic>
pub fn terminal_diagnostics_snapshot(&self) -> Vec<TerminalDiagnostic>
Clones all stored diagnostics in their current order.
The returned vector is independent; modifying it does not affect state. No redaction or bounding is applied.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let state = TerminalState::new();
assert!(state.terminal_diagnostics_snapshot().is_empty());Sourcepub fn update_prompt_heuristic(&mut self)
pub fn update_prompt_heuristic(&mut self)
Applies the shell prompt heuristic to the current active-screen row.
The full padded plain text and normal-based global line index are passed to shell state. If the cursor row has no corresponding line, this is a no-op. A detected prompt can finish an active command as unknown, mark a prompt visible, and queue events. No security flag is consulted.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.write_str("user@host:~$ ");
state.update_prompt_heuristic();
assert!(state.shell.prompt_visible);Sourcepub fn open_hyperlink(
&mut self,
params: impl Into<String>,
uri: impl Into<String>,
)
pub fn open_hyperlink( &mut self, params: impl Into<String>, uri: impl Into<String>, )
Registers and activates a hyperlink when permitted.
Allowed strings are stored verbatim, including empty/invalid URIs. The ID
is the pre-push registry length converted to u64; links are never
deduplicated or removed. On a target with usize wider than 64 bits that
conversion can truncate. When blocked, the active link is cleared and a
warning is appended, leaving the registry unchanged.
§Examples
use ailloli_ui_terminal_core::{TerminalHyperlinkId, TerminalState};
let mut state = TerminalState::new(); state.open_hyperlink("id=docs", "https://example.test");
assert_eq!(state.active_hyperlink, Some(TerminalHyperlinkId(0)));
state.write_char('x');
assert_eq!(state.screen.lines[0].cells[0].hyperlink, Some(TerminalHyperlinkId(0)));Sourcepub fn close_hyperlink(&mut self)
pub fn close_hyperlink(&mut self)
Clears the hyperlink assigned to future cells.
Existing cell links and registry entries remain unchanged; repeated calls are no-ops and no damage is marked.
§Examples
use ailloli_ui_terminal_core::TerminalState;
let mut state = TerminalState::new(); state.open_hyperlink("", "https://example.test");
state.close_hyperlink();
assert_eq!(state.active_hyperlink, None);
assert_eq!(state.hyperlinks.len(), 1);Sourcepub fn push_warning(&mut self, warning: TerminalWarning)
pub fn push_warning(&mut self, warning: TerminalWarning)
Appends a warning without deduplication, redaction, or retention limit.
§Examples
use ailloli_ui_terminal_core::{TerminalState, TerminalWarning};
let mut state = TerminalState::new();
state.push_warning(TerminalWarning::unsupported_sequence("ESC Z"));
assert_eq!(state.warnings.len(), 1);Trait Implementations§
Source§impl Clone for TerminalState
impl Clone for TerminalState
Source§fn clone(&self) -> TerminalState
fn clone(&self) -> TerminalState
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more