Skip to main content

Terminal

Struct Terminal 

Source
pub struct Terminal<B: Backend> { /* private fields */ }
Expand description

A double-buffered terminal generic over a Backend.

Owns the current and previous frame grids and the backend’s lifecycle (resize, present, events). Drawing itself goes entirely through Surface: see draw for the common case (draw a frame, then present it) and surface for manual control over presenting.

§Out-of-bounds drawing

Surface clips any write that falls outside its own area rather than panicking; see Surface’s own “out-of-bounds drawing” documentation.

§Examples

use retroglyph_core::backend::Headless;
use retroglyph_core::{Color, Terminal};

let mut term = Terminal::new(Headless::new(20, 5));
term.draw(|surface| {
    surface.put((2, 1), '@', retroglyph_core::Style::new().fg(Color::GREEN));
})
.unwrap();

Implementations§

Source§

impl<B: Backend> Terminal<B>

Source

pub fn new(backend: B) -> Self

Create a terminal with the given backend. Grid dimensions are queried from the backend.

Source

pub fn draw( &mut self, f: impl FnOnce(&mut Surface<'_>), ) -> Result<(), <B as Output>::Error>

Draws one frame: f gets a Surface scoped to the whole terminal on layer 0, then the frame is presented (see present) once f returns.

This is the common entry point for drawing: a caller that draws every frame regardless of whether anything changed calls this once per frame. A caller that only wants to redraw when its own state changed should gate the call to draw itself (e.g. if state.changed() { term.draw(|s| render(s, &state))?; }) rather than rely on draw/ present to no-op. Unlike some earlier revisions of this API, presenting is unconditional here.

§Errors

Propagates errors from present.

Source

pub const fn surface(&mut self) -> Surface<'_>

A Surface scoped to the whole terminal on layer 0, for manual control over presenting (e.g. partial updates spread across several calls, or conditionally skipping a present). Most callers want draw instead.

Source

pub const fn size(&self) -> Size

Returns the current grid dimensions.

Source

pub const fn area(&self) -> Rect

Returns the full drawing surface as a Rect at the origin.

Equivalent to Rect::new(0, 0, width, height). Handy for passing the whole terminal to layout helpers or region-based drawing.

Source

pub fn resize(&mut self, width: u16, height: u16)

Resize both grids to width × height cells.

Content within the overlapping region is preserved in the current grid. The previous grid is cleared so the next present redraws the entire new surface rather than diffing stale data.

Source

pub const fn grid(&self) -> &Grid

Returns a reference to the current grid.

Source

pub const fn grid_mut(&mut self) -> &mut Grid

Returns a mutable reference to the current grid, with no clipping or layer scoping.

Escape hatch for whole-grid operations that don’t fit Surface’s clipped, single-layer model (e.g. Grid::blit). Most drawing should go through draw/surface instead.

Source

pub const fn backend(&self) -> &B

Returns a reference to the backend.

Source

pub const fn backend_mut(&mut self) -> &mut B

Returns a mutable reference to the backend.

Source

pub const fn present_count(&self) -> u64

Number of times present has been called so far.

Wraps on overflow; intended for detecting whether present was called at all between two points in time (compare a saved count against the current one), not as a precise total. Embedding drivers (e.g. retroglyph-window’s windowed drivers) use this to decide whether application code already presented during a frame, so they can skip a redundant driver-side present.

Source

pub fn present(&mut self) -> Result<(), <B as Output>::Error>

Present the current frame: computes the diff against the previous frame, sends changed cells to the backend, flushes, then swaps buffers. Always presents unconditionally, even if nothing was drawn since the last call; most callers want draw instead of calling this directly.

When the backend requires a full frame (see crate::Output::needs_full_frame), all cells from every allocated layer are sent rather than just the diff, so pixel-based backends can clear and redraw to avoid orphaned pixels from sub-cell offsets.

After a present, the new current buffer is cleared so the next frame starts empty. Callers should not draw into a frame and skip presenting it: the next draw call starts from an empty grid regardless.

§Immediate mode

This is an immediate-mode API (the same trade ratatui makes): the current buffer is wiped after every present, so each frame must redraw its entire scene from scratch. Cells are not retained between frames. The diff only bounds what is sent to the backend (terminal or pixel I/O); it does not bound the CPU cost of your redraw.

§Errors

Propagates errors from the backend’s draw_layers or flush operations. Either failure returns before the current/previous buffers are swapped, so the cells from the failed frame stay marked dirty and are resent the next time present succeeds; the caller doesn’t need to redraw anything to recover, just call draw/present again.

Source

pub fn poll(&mut self, timeout: Duration) -> Option<Event>

Polls for an input event, waiting up to timeout.

If an event was previously buffered by has_input, it is returned immediately. Otherwise, the backend is polled for a new event.

Event::Resize events are automatically applied: both grids are resized before the event is returned to the caller, so the game loop can immediately redraw at the new size.

Source

pub fn read_blocking(&mut self) -> Event

Reads an input event, blocking indefinitely until one is available.

Only call this on backends that genuinely block (e.g. crossterm, window). Backends that never block (e.g. Headless, which returns immediately regardless of timeout) will panic here once their event queue is empty; use poll or drain_events instead if that is a possibility.

§Panics

Panics if the backend’s poll_event returns None even with an unbounded timeout.

Source

pub fn drain_events(&mut self) -> impl Iterator<Item = Event> + use<'_, B>

Drains all available events without blocking.

Returns an iterator that yields every pending event — the internal queued event followed by all events buffered in the backend. The iterator polls the backend with zero timeout repeatedly until None is returned.

This is needed for frame-based game loops (e.g. software backend + WASM, where frames are gated by requestAnimationFrame). Multiple keypresses can arrive between frames; draining all of them ensures accumulated input doesn’t replay in slow motion.

Crossterm and headless backends can also use this, but the single-event poll pattern works for them because their loops aren’t frame-capped.

Source

pub fn has_input(&mut self) -> bool

Checks if a pending input event is available without blocking.

If an event is already buffered, returns true. Otherwise, polls the backend with zero timeout. If the backend returns an event, it is stored in the internal buffer and true is returned; otherwise, returns false.

Auto Trait Implementations§

§

impl<B> Freeze for Terminal<B>
where B: Freeze,

§

impl<B> RefUnwindSafe for Terminal<B>
where B: RefUnwindSafe,

§

impl<B> Send for Terminal<B>
where B: Send,

§

impl<B> Sync for Terminal<B>
where B: Sync,

§

impl<B> Unpin for Terminal<B>
where B: Unpin,

§

impl<B> UnsafeUnpin for Terminal<B>
where B: UnsafeUnpin,

§

impl<B> UnwindSafe for Terminal<B>
where B: UnwindSafe,

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> 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, 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.