Skip to main content

Terminal

Struct Terminal 

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

An interface to interact and draw Frames on the user’s terminal.

This is the main entry point for Ratatui’s rendering subsystem. It owns the backend-facing render state: double buffers, viewport bookkeeping, and cursor synchronization for each render pass.

If you’re building a fullscreen application with the ratatui crate’s default backend (Crossterm), prefer ratatui::run (or ratatui::init + ratatui::restore) over constructing Terminal directly. These helpers enable common terminal modes (raw mode + alternate screen) and restore them on exit and on panic.

ratatui::run(|terminal| {
    let mut should_quit = false;
    while !should_quit {
        terminal.draw(|frame| {
            frame.render_widget("Hello, World!", frame.area());
        })?;

        // Handle events, update application state, and set `should_quit = true` to exit.
    }
    Ok(())
})?;

§Typical Usage

In a typical application, the flow is: set up a terminal, run an event loop, update state, and draw each frame.

  1. Choose a setup path for a Terminal. Most apps call ratatui::run, which passes a preconfigured Terminal into your callback. If you need more control, use ratatui::init and ratatui::restore, or construct a Terminal manually via Terminal::new (fullscreen) or Terminal::with_options (select a Viewport).
  2. Enter your application’s event loop and call Terminal::draw (or Terminal::try_draw) to render the current UI state into a Frame.
  3. Handle input and application state updates between draw calls.
  4. If the terminal is resized, call Terminal::draw again. Ratatui automatically resizes fullscreen and inline viewports during draw; fixed viewports require an explicit call to Terminal::resize if you want the region to change.

The normal mental model is: redraw the whole UI each pass, let Ratatui compute the diff, and treat Frame::area as the source of truth for where this pass can render. Most application code can stay entirely within that model.

§Rendering Pipeline

A single call to Terminal::draw (or Terminal::try_draw) represents one render pass. In broad strokes, Ratatui:

  1. Checks whether the underlying terminal size changed (see Terminal::autoresize).
  2. Creates a Frame backed by the current buffer (see Terminal::get_frame).
  3. Runs your render callback to populate that buffer.
  4. Diffs the current buffer against the previous buffer and writes the changes (see Terminal::flush).
  5. Applies cursor visibility and position requested by the frame (see Frame::set_cursor_position).
  6. Swaps the buffers to prepare for the next render pass (see Terminal::swap_buffers).
  7. Flushes the backend (see Backend::flush).

Each render pass starts with an empty buffer for the current viewport. Your render callback should render everything that should be visible in Frame::area, even if it is unchanged from the previous frame. Ratatui diffs the current and previous buffers and only writes the changes; anything you don’t render is treated as empty and may clear previously drawn content.

If the viewport size changes between render passes (for example via Terminal::autoresize or an explicit Terminal::resize), Ratatui clears the viewport and resets the previous buffer so the next draw is treated as a full redraw.

If Terminal::try_draw returns an error, the render pass ends early. Depending on where the failure happened, Ratatui may have already resized internal buffers, written part of the diff, or left cursor state unapplied. In most applications, treat that error as fatal for the current terminal session and let higher-level setup code restore terminal state before continuing.

Most applications should use Terminal::draw / Terminal::try_draw. Manual rendering is a separate, lower-level path intended primarily for tests and specialized integrations. In that mode you build a frame with Terminal::get_frame, apply the current buffer diff with Terminal::flush, then call Terminal::swap_buffers. If your backend buffers output, also call Backend::flush.

Terminal::flush only knows about Ratatui’s two screen buffers. It does not know whether you have changed terminal modes or switched display surfaces (for example by leaving the alternate screen). If you call it after such a change, Ratatui may replay a diff computed for the old surface onto the new one. When you need a complete draw pass that stays synchronized with cursor updates and backend flushing, prefer Terminal::draw / Terminal::try_draw.

The same caution applies to direct backend mutation and direct cursor manipulation. If you write to the backend or move the cursor outside Ratatui’s normal render pass, the next draw may overwrite those changes or may diff against stale assumptions. Use those escape hatches only when you intentionally manage resynchronization yourself, typically by calling Terminal::clear or performing a full render pass afterward.

use ratatui::Terminal;
use ratatui::backend::{Backend, TestBackend};

let backend = TestBackend::new(10, 10);
let mut terminal = Terminal::new(backend)?;

// Manual render pass (roughly what `Terminal::draw` does internally).
{
    let mut frame = terminal.get_frame();
    frame.render_widget("Hello World!", frame.area());
}

terminal.flush()?;
terminal.swap_buffers();
terminal.backend_mut().flush()?;

§Viewports

The viewport controls where Ratatui draws and therefore what Frame::area represents. Most applications use Viewport::Fullscreen, but Ratatui also supports Viewport::Inline and Viewport::Fixed.

Choose a viewport based on how the app should fit into the terminal:

  • Viewport::Fullscreen: the standard TUI case where Ratatui owns the whole terminal window.
  • Viewport::Inline: embed the UI into a larger CLI flow with normal terminal output above it.
  • Viewport::Fixed: render into one region of a larger terminal layout managed elsewhere.

Choose a viewport at initialization time with Terminal::with_options and TerminalOptions.

Frame::area depends on the active viewport. In fullscreen mode it starts at (0, 0); in fixed and inline mode it may have a non-zero origin, so prefer using frame.area() as your root layout rectangle. The variant docs on Viewport describe each mode in more detail, and inline-specific behavior is covered in the “Inline Viewport” section below.

use ratatui::backend::CrosstermBackend;
use ratatui::layout::{Constraint, Layout, Rect};
use ratatui::{Terminal, TerminalOptions, Viewport};

// Fullscreen (most common):
let fullscreen = Terminal::new(CrosstermBackend::new(std::io::stdout()))?;

// Fixed region (your app manages the coordinates):
let viewport = Viewport::Fixed(Rect::new(0, 0, 30, 10));
let fixed = Terminal::with_options(
    CrosstermBackend::new(std::io::stdout()),
    TerminalOptions { viewport },
)?;

fixed.draw(|frame| {
    // Split the fixed viewport itself instead of assuming the viewport starts at `(0, 0)`.
    let [header, body] =
        Layout::vertical([Constraint::Length(1), Constraint::Min(0)]).areas(frame.area());

    frame.render_widget("Fixed panel header", header);
    frame.render_widget("Render the panel body relative to frame.area()", body);
})?;

Applications should redraw after terminal resizes with Terminal::draw / Terminal::try_draw. Fullscreen and inline viewports resize automatically during those render passes; fixed viewports do not.

If your event loop receives a resize event, treat that event as a signal to render again rather than as a complete source of truth for layout. During a render pass, use Frame::area as the rectangle that Ratatui has actually prepared for drawing. Ratatui checks the backend’s current size during draw / try_draw so layout reflects the terminal size that exists at render time, even if resize events were coalesced, missed, or arrived before your app handled them.

§Inline Viewport

Inline mode is designed for applications that want to embed a UI into a larger CLI flow. In Viewport::Inline, Ratatui anchors the viewport to the backend cursor row and always starts drawing at column 0.

To reserve vertical space for the requested height, Ratatui may append lines. When the cursor is near the bottom edge, terminals scroll; Ratatui accounts for that scrolling by shifting the computed viewport origin upward so the viewport stays fully visible.

While running in inline mode, Terminal::insert_before can be used to print output above the viewport without disturbing the UI’s logical position. When Ratatui is built with the scrolling-regions feature, insert_before can do this without clearing and redrawing the viewport.

use ratatui::{TerminalOptions, Viewport};

println!("Some output above the UI");

let options = TerminalOptions {
    viewport: Viewport::Inline(10),
};
let mut terminal = ratatui::try_init_with_options(options)?;

terminal.insert_before(1, |buf| {
    // Render a single line of output into `buf` before the UI.
    // (For example: logs, status updates, or command output.)
})?;

terminal.draw(|frame| {
    // Continue rendering the inline UI relative to the inline viewport.
    frame.render_widget("inline ui", frame.area());
})?;

§More Information

§Initialization

Most interactive TUIs need process-wide terminal setup (for example: raw mode and an alternate screen) and matching teardown on exit and on panic. In Ratatui, that setup lives in the ratatui crate; Terminal itself focuses on rendering and does not implicitly change those modes.

If you’re using the ratatui crate with its default backend (Crossterm), there are three common entry points:

ratatui::run was introduced in Ratatui 0.30, so older tutorials may use init/restore or manual construction.

Some applications install a custom panic hook to log a crash report, print a friendlier error, or integrate with error reporting. If you do, install it before calling ratatui::init / ratatui::run. Ratatui wraps the current hook so it can restore terminal state first (for example: leaving the alternate screen and disabling raw mode) and then delegate to your hook.

Crossterm is cross-platform and is what most Ratatui applications use by default. Ratatui also supports other backends such as Termion and Termwiz, and third-party backends can integrate by implementing Backend.

§How it works

Terminal ties together a Backend, a Viewport, and a double-buffered diffing renderer. The high-level flow is described in the “Rendering Pipeline” section above; this section focuses on how that pipeline is implemented.

Terminal is generic over a Backend implementation and does not depend on a particular terminal library. It relies on the backend to:

§Buffers and diffing

The Terminal maintains two Buffers sized to the current viewport. During a render pass, widgets draw into the “current” buffer via the Frame passed to your callback. At the end of the pass, Terminal::flush diffs the current buffer against the previous buffer and sends only the changed cells to the backend.

After flushing, Terminal::swap_buffers flips which buffer is considered “current” and resets the next buffer. This is why each render pass starts from an empty buffer: your callback is expected to fully redraw the viewport every time.

The CompletedFrame returned from Terminal::draw / Terminal::try_draw provides a reference to the buffer that was just rendered, which can be useful for assertions in tests.

§Viewport state and resizing

The active Viewport controls how the viewport area is computed:

  • Fullscreen: Frame::area covers the full backend size.
  • Fixed: Frame::area is the exact rectangle you provided in terminal coordinates.
  • Inline: Frame::area is a rectangle anchored to the backend cursor row.

For fullscreen and inline viewports, Terminal::autoresize checks the backend size during every render pass and calls Terminal::resize when it changes. Resizing updates the internal buffer sizes and clears the affected region; it also resets the previous buffer so the next draw is treated as a full redraw.

§Cursor tracking

The cursor position requested by Frame::set_cursor_position is applied after Terminal::flush so the cursor ends up on top of the rendered UI. Terminal also tracks a “last known cursor position” as a best-effort record of where it last wrote, and uses that information when recomputing inline viewports on resize.

§Inline-specific behavior

Inline viewports reserve vertical space by calling Backend::append_lines. If the cursor is close enough to the bottom edge, terminals scroll as lines are appended. Ratatui accounts for that scrolling by shifting the computed viewport origin upward so the viewport remains fully visible. On resize, Ratatui recomputes the inline origin while trying to keep the cursor at the same relative row inside the viewport.

When Ratatui is built with the scrolling-regions feature, Terminal::insert_before uses terminal scrolling regions to insert content above an inline viewport without clearing and redrawing it.

Implementations§

Source§

impl<B> Terminal<B>
where B: Backend,

Source

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

Returns a shared reference to the backend.

This is primarily useful for backend-specific inspection in tests (e.g. reading TestBackend’s buffer) or for backend-specific APIs that Ratatui does not model.

Reading from the backend does not desynchronize Ratatui, but values observed here may lag behind the current render callback because Ratatui does not apply a frame to the backend until the end of Terminal::draw / Terminal::try_draw.

Source

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

Returns a mutable reference to the backend.

This is an advanced escape hatch. Normal applications should render through Terminal::draw / Terminal::try_draw instead of mutating the backend directly.

Use this when integrating with backend-specific APIs that Ratatui does not model, or when tests need direct control over backend state.

Mutating the backend directly can desynchronize Ratatui’s internal buffers, cursor tracking, or viewport assumptions from what’s on-screen. If you do this, call Terminal::clear or perform a full draw pass before relying on Ratatui’s view of the terminal again.

Source

pub fn size(&self) -> Result<Size, <B as Backend>::Error>

Queries the real size of the backend.

This returns the backend’s current terminal size and does not update Ratatui’s internal viewport bookkeeping by itself. The current renderable area depends on the configured Viewport; use Frame::area inside Terminal::draw / Terminal::try_draw if you want the area you should render into for the current pass.

To make Ratatui observe backend size changes for fullscreen or inline viewports, see Terminal::autoresize.

Source§

impl<B> Terminal<B>
where B: Backend,

Source

pub const fn get_frame(&mut self) -> Frame<'_>

Returns a Frame for manual rendering.

Most applications should render via Terminal::draw / Terminal::try_draw. This is an escape hatch that exposes the frame construction step used by Terminal::try_draw so tests and advanced callers can render without running the full draw pipeline.

This is primarily useful for tests, backend adapters, and specialized integrations that intentionally manage presentation themselves.

Unlike draw / try_draw, this does not call Terminal::autoresize, does not write updates to the backend, and does not apply any cursor changes. After rendering, you typically call Terminal::flush, Terminal::swap_buffers, and Backend::flush.

For the full render-pass behavior that also handles resizing, cursor updates, buffer swapping, and backend flushing, see Terminal::draw and Terminal::try_draw.

The returned Frame mutably borrows the current buffer, so it must be dropped before you can call methods like Terminal::flush. The example below uses a scope to make that explicit.

§Example
use ratatui::Terminal;
use ratatui::backend::{Backend, TestBackend};

let backend = TestBackend::new(30, 5);
let mut terminal = Terminal::new(backend)?;
{
    let mut frame = terminal.get_frame();
    frame.render_widget("Hello", frame.area());
}
// When not using `draw`, present the buffer manually:
terminal.flush()?;
terminal.swap_buffers();
terminal.backend_mut().flush()?;
Source

pub const fn current_buffer_mut(&mut self) -> &mut Buffer

Gets the current buffer as a mutable reference.

This is the buffer that the next Frame will render into (see Terminal::get_frame). This is a low-level escape hatch; normal applications should render inside Terminal::draw and access the buffer through widgets, or through Frame::buffer_mut when they intentionally need direct cell access during a render pass.

Mutating this buffer does not update the backend immediately. The changes become visible only after a later Terminal::flush or full draw pass applies the diff. Because this bypasses the usual render callback structure, it is mainly useful for tests and specialized integrations that intentionally manage presentation themselves.

Source

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

Applies the current buffer diff to the backend’s active display surface.

This compares the current buffer with the previous buffer and passes only the changed cells to Backend::draw. It is one of the building blocks used by Terminal::draw / Terminal::try_draw.

This method does not swap buffers, does not update cursor visibility or position, and does not call Backend::flush. See Terminal::swap_buffers and Backend::flush.

Terminal::flush only reasons about Ratatui’s internal buffers. It does not know whether the backend’s display surface changed since the last render pass. For example, if you leave the alternate screen and then call Terminal::flush, Ratatui may replay a diff that was computed for the alternate screen onto the main screen. In normal applications, prefer Terminal::draw / Terminal::try_draw unless you are intentionally managing the whole render pipeline yourself.

Implementation note: when there are updates, Ratatui records the position of the last updated cell as the “last known cursor position”. Inline viewports use this to preserve the cursor’s relative position within the viewport across resizes.

Source

pub fn swap_buffers(&mut self)

Clears the inactive buffer and swaps it with the current buffer.

This is part of the standard rendering flow (see Terminal::try_draw). If you render manually using Terminal::get_frame and Terminal::flush, call this immediately afterward so the next flush can compute diffs against the correct “previous” buffer.

Source

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

Clear the terminal and force a full redraw on the next draw call.

What gets cleared depends on the active Viewport:

Current behavior: for Viewport::Inline, clearing runs from the viewport origin through the end of the visible display area, not just the viewport’s rectangle. This is an implementation detail rather than a contract; do not rely on it.

This preserves the backend’s current cursor position.

This also resets the “previous” buffer so the next Terminal::flush redraws the full viewport.

Implementation note: this uses ClearType::AfterCursor starting at the viewport origin.

Source§

impl<B> Terminal<B>
where B: Backend,

Source

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

Hides the cursor.

When using Terminal::draw / Terminal::try_draw, prefer controlling the cursor with Frame::set_cursor_position. A later successful Terminal::draw / Terminal::try_draw call may overwrite this change.

Source

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

Shows the cursor.

When using Terminal::draw / Terminal::try_draw, prefer controlling the cursor with Frame::set_cursor_position. A later successful Terminal::draw / Terminal::try_draw call may overwrite this change.

Source

pub fn get_cursor(&mut self) -> Result<(u16, u16), <B as Backend>::Error>

👎Deprecated:

use get_cursor_position() instead which returns Result<Position>

Gets the current cursor position.

This queries the backend for the current cursor position and returns it as an (x, y) tuple.

Source

pub fn set_cursor( &mut self, x: u16, y: u16, ) -> Result<(), <B as Backend>::Error>

👎Deprecated:

use set_cursor_position((x, y)) instead which takes impl Into<Position>

Sets the cursor position.

Source

pub fn get_cursor_position(&mut self) -> Result<Position, <B as Backend>::Error>

Gets the current cursor position.

This queries the backend for the current cursor position. It is not limited to Ratatui’s last render pass, so direct backend mutations may also affect the returned value.

When using Terminal::draw / Terminal::try_draw, prefer controlling the cursor with Frame::set_cursor_position. For direct control, see Terminal::set_cursor_position.

Source

pub fn set_cursor_position<P>( &mut self, position: P, ) -> Result<(), <B as Backend>::Error>
where P: Into<Position>,

Sets the cursor position.

This updates the backend cursor and Ratatui’s internal cursor tracking. Inline viewports use that tracking when recomputing the viewport on resize.

When using Terminal::draw / Terminal::try_draw, consider using Frame::set_cursor_position instead so the cursor is updated as part of the normal rendering flow. A later successful Terminal::draw / Terminal::try_draw call may overwrite a direct cursor move.

Source§

impl<B> Terminal<B>
where B: Backend,

Source

pub fn new(backend: B) -> Result<Terminal<B>, <B as Backend>::Error>

Creates a new Terminal with the given Backend with a full screen viewport.

This is a convenience for Terminal::with_options with Viewport::Fullscreen. Ratatui initializes two empty buffers sized to the backend’s current screen area and treats future backend size changes as redraw-triggering resizes during render passes.

After creating a terminal, call Terminal::draw (or Terminal::try_draw) in a loop to render your UI.

Note that unlike ratatui::init, this does not install a panic hook, so it is recommended to do that manually when using this function, otherwise any panic messages will be printed to the alternate screen and the terminal may be left in an unusable state.

See how to set up panic hooks and better-panic example for more information.

§Example
use std::io::stdout;

use ratatui::Terminal;
use ratatui::backend::CrosstermBackend;

let backend = CrosstermBackend::new(stdout());
let _terminal = Terminal::new(backend)?;

// Optionally set up a panic hook to restore the terminal on panic.
let old_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
    ratatui::restore();
    old_hook(info);
}));
Source

pub fn with_options( backend: B, options: TerminalOptions, ) -> Result<Terminal<B>, <B as Backend>::Error>

Creates a new Terminal with the given Backend and TerminalOptions.

The viewport determines what area is exposed to widgets via Frame::area and how Ratatui keeps its internal buffers synchronized with the backend. See Viewport for an overview of the available modes.

For viewport behavior after initialization, see Terminal::resize and Terminal::autoresize.

After creating a terminal, call Terminal::draw (or Terminal::try_draw) in a loop to render your UI.

Resize behavior depends on the selected viewport:

§Example
use std::io::stdout;

use ratatui::backend::CrosstermBackend;
use ratatui::layout::Rect;
use ratatui::{Terminal, TerminalOptions, Viewport};

let backend = CrosstermBackend::new(stdout());
let viewport = Viewport::Fixed(Rect::new(0, 0, 10, 10));
let _terminal = Terminal::with_options(backend, TerminalOptions { viewport })?;

When the viewport is Viewport::Inline, Ratatui anchors the viewport to the current cursor row at initialization time (always starting at column 0). Ratatui may append lines and thereby scroll the terminal to make enough room for the requested height so the viewport stays fully visible.

Source§

impl<B> Terminal<B>
where B: Backend,

Source

pub fn insert_before<F>( &mut self, height: u16, draw_fn: F, ) -> Result<(), <B as Backend>::Error>
where F: FnOnce(&mut Buffer),

Insert some content before the current inline viewport. This has no effect when the viewport is not inline.

This is intended for inline UIs that want to print output (e.g. logs or status messages) above the UI without breaking it. See Viewport::Inline for how inline viewports are anchored.

The draw_fn closure will be called to draw into a writable Buffer that is height lines tall. The content of that Buffer will then be inserted before the viewport.

When Ratatui is built with the scrolling-regions feature, this can be done without clearing and redrawing the viewport. Without scrolling-regions, Ratatui falls back to a more portable approach and clears the viewport so the next Terminal::draw / Terminal::try_draw repaints it.

If the viewport isn’t yet at the bottom of the screen, inserted lines will push it towards the bottom. Once the viewport is at the bottom of the screen, inserted lines will scroll the area of the screen above the viewport upwards.

Before:

+---------------------+
| pre-existing line 1 |
| pre-existing line 2 |
+---------------------+
|       viewport      |
+---------------------+
|                     |
|                     |
+---------------------+

After inserting 2 lines:

+---------------------+
| pre-existing line 1 |
| pre-existing line 2 |
|   inserted line 1   |
|   inserted line 2   |
+---------------------+
|       viewport      |
+---------------------+
+---------------------+

After inserting 2 more lines:

+---------------------+
| pre-existing line 2 |
|   inserted line 1   |
|   inserted line 2   |
|   inserted line 3   |
|   inserted line 4   |
+---------------------+
|       viewport      |
+---------------------+

If more lines are inserted than there is space on the screen, then the top lines will go directly into the terminal’s scrollback buffer. At the limit, if the viewport takes up the whole screen, all lines will be inserted directly into the scrollback buffer.

§Examples
§Insert a single line before the current viewport
use ratatui::backend::{Backend, TestBackend};
use ratatui::layout::Position;
use ratatui::style::{Color, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::Widget;
use ratatui::{Terminal, TerminalOptions, Viewport};

let mut backend = TestBackend::new(10, 10);
// Simulate existing output above the inline UI.
backend.set_cursor_position(Position::new(0, 3))?;
let mut terminal = Terminal::with_options(
    backend,
    TerminalOptions {
        viewport: Viewport::Inline(4),
    },
)?;

terminal.insert_before(1, |buf| {
    Line::from(vec![
        Span::raw("This line will be added "),
        Span::styled("before", Style::default().fg(Color::Blue)),
        Span::raw(" the current viewport"),
    ])
    .render(buf.area, buf);
})?;
Source§

impl<B> Terminal<B>
where B: Backend,

Source

pub fn draw<F>( &mut self, render_callback: F, ) -> Result<CompletedFrame<'_>, <B as Backend>::Error>
where F: FnOnce(&mut Frame<'_>),

Draws a single frame to the terminal.

Returns a CompletedFrame if successful, otherwise a backend error (B::Error).

If the render callback passed to this method can fail, use try_draw instead.

Applications should call draw or try_draw in a loop to continuously render the terminal. These methods are the main entry points for drawing to the terminal.

The Frame passed to the render callback represents the currently configured Viewport (see Frame::area and Terminal::with_options).

Build layout relative to the Rect returned by Frame::area rather than assuming the origin is (0, 0), so the same rendering code works for fixed and inline viewports.

This method will:

If any backend step fails, the error is returned immediately and later steps in the render pass are skipped.

The CompletedFrame returned by this method can be useful for debugging or testing purposes, but it is often not used in regular applications.

The render callback should fully render the entire frame when called, including areas that are unchanged from the previous frame. This is because each frame is compared to the previous frame to determine what has changed, and only the changes are written to the terminal. If the render callback does not fully render the frame, the terminal will not be in a consistent state.

§Examples
use ratatui::backend::TestBackend;
use ratatui::layout::Position;
use ratatui::{Frame, Terminal};

let backend = TestBackend::new(10, 10);
let mut terminal = Terminal::new(backend)?;

// With a closure.
terminal.draw(|frame| {
    let area = frame.area();
    frame.render_widget("Hello World!", area);
    frame.set_cursor_position(Position { x: 0, y: 0 });
})?;

// Or with a function.
terminal.draw(render)?;

fn render(frame: &mut Frame<'_>) {
    frame.render_widget("Hello World!", frame.area());
}
Source

pub fn try_draw<F, E>( &mut self, render_callback: F, ) -> Result<CompletedFrame<'_>, <B as Backend>::Error>
where F: FnOnce(&mut Frame<'_>) -> Result<(), E>, E: Into<<B as Backend>::Error>,

Tries to draw a single frame to the terminal.

Returns Result::Ok containing a CompletedFrame if successful, otherwise Result::Err containing the backend error (B::Error) that caused the failure.

This is the equivalent of Terminal::draw but the render callback is a function or closure that returns a Result instead of nothing.

Applications should call try_draw or draw in a loop to continuously render the terminal. These methods are the main entry points for drawing to the terminal.

The Frame passed to the render callback represents the currently configured Viewport (see Frame::area and Terminal::with_options).

Build layout relative to the Rect returned by Frame::area rather than assuming the origin is (0, 0), so the same rendering code works for fixed and inline viewports.

This method will:

If the render callback returns an error, Ratatui leaves the backend, buffers, cursor state, and frame count unchanged.

The render callback passed to try_draw can return any Result with an error type that can be converted into B::Error using the Into trait. This makes it possible to use the ? operator to propagate errors that occur during rendering. If the render callback returns an error, the error will be returned from try_draw and the terminal will not be updated.

The CompletedFrame returned by this method can be useful for debugging or testing purposes, but it is often not used in regular applications.

The render callback should fully render the entire frame when called, including areas that are unchanged from the previous frame. This is because each frame is compared to the previous frame to determine what has changed, and only the changes are written to the terminal. If the render function does not fully render the frame, the terminal will not be in a consistent state.

§Examples
use std::io;

use ratatui::backend::CrosstermBackend;
use ratatui::layout::Position;
use ratatui::{Frame, Terminal};

let backend = CrosstermBackend::new(std::io::stdout());
let mut terminal = Terminal::new(backend)?;

// With a closure that returns `Result`.
terminal.try_draw(|frame| -> io::Result<()> {
    let _value: u8 = "42".parse().map_err(io::Error::other)?;
    let area = frame.area();
    frame.render_widget("Hello World!", area);
    frame.set_cursor_position(Position { x: 0, y: 0 });
    Ok(())
})?;

// Or with a function.
terminal.try_draw(render)?;

fn render(frame: &mut Frame<'_>) -> io::Result<()> {
    frame.render_widget("Hello World!", frame.area());
    Ok(())
}
Source

pub fn apply_buffer( &mut self, ) -> Result<CompletedFrame<'_>, <B as Backend>::Error>

A low-level function that applies and flushes the current buffer to the backend.

This calls Terminal::apply_buffer_with_cursor with None, which hides the cursor.

§Examples
use std::io;

use ratatui::Terminal;
use ratatui::backend::CrosstermBackend;
use ratatui::buffer::Buffer;
use ratatui::widgets::Widget;

let backend = CrosstermBackend::new(io::stdout());
let mut terminal = Terminal::new(backend)?;

terminal.autoresize()?;

let mut custom_buffer = Buffer::default();
custom_buffer.resize(terminal.get_frame().area());
custom_buffer.reset();

"Hello World!".render(custom_buffer.area, &mut custom_buffer);

terminal.current_buffer_mut().merge(&custom_buffer);
terminal.apply_buffer()?;
Source

pub fn apply_buffer_with_cursor( &mut self, cursor_position: Option<Position>, ) -> Result<CompletedFrame<'_>, <B as Backend>::Error>

A low-level function that applies and flushes the current buffer to the backend and re-positions the cursor. This function is useful if you need to manage your own custom draw lifecycle and buffer.

Returns Result::Ok containing a CompletedFrame if successful, otherwise Result::Err containing the backend error (B::Error) that caused the failure.

This method will:

  • show/hide the cursor based on cursor_position (None will hide the cursor)
  • call Terminal::swap_buffers to prepare for the next render pass
  • call Backend::flush to flush any buffered backend output
  • return a CompletedFrame with the current buffer and the area used for rendering

The CompletedFrame returned by this method can be useful for debugging or testing purposes, but it is often not used in regular applications.

§Examples
use std::io;

use ratatui::Terminal;
use ratatui::backend::CrosstermBackend;
use ratatui::buffer::Buffer;
use ratatui::widgets::Widget;

let backend = CrosstermBackend::new(io::stdout());
let mut terminal = Terminal::new(backend)?;

terminal.autoresize()?;

let mut custom_buffer = Buffer::default();
custom_buffer.resize(terminal.get_frame().area());
custom_buffer.reset();

"Hello World!".render(custom_buffer.area, &mut custom_buffer);

terminal.current_buffer_mut().merge(&custom_buffer);
terminal.apply_buffer_with_cursor(None)?;
Source§

impl<B> Terminal<B>
where B: Backend,

Source

pub fn resize(&mut self, area: Rect) -> Result<(), <B as Backend>::Error>

Updates the Terminal so that internal buffers match the requested area.

This updates the buffer size used for rendering and triggers a full clear so the next Terminal::draw / Terminal::try_draw paints into a consistent area.

When the viewport is Viewport::Inline, the area argument is treated as the new terminal size and the viewport origin is recomputed relative to the current cursor position. Ratatui attempts to keep the cursor at the same relative row within the viewport across resizes.

See also: Terminal::autoresize (automatic resizing during Terminal::draw / Terminal::try_draw).

For Viewport::Fixed and Viewport::Fullscreen, area becomes the new viewport area. For Viewport::Inline, area is interpreted as the backend’s new terminal size and the viewport origin may move to preserve the cursor’s relative row within the inline UI.

Source

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

Queries the backend for size and resizes if it doesn’t match the previous size.

This is called automatically during Terminal::draw / Terminal::try_draw for fullscreen and inline viewports. Fixed viewports are not automatically resized.

If the size changed, this calls Terminal::resize and therefore clears the affected region before the next frame is rendered.

Trait Implementations§

Source§

impl<B> Clone for Terminal<B>
where B: Clone + Backend,

Source§

fn clone(&self) -> Terminal<B>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl<B> Debug for Terminal<B>
where B: Debug + Backend,

Source§

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

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

impl<B> Default for Terminal<B>
where B: Default + Backend,

Source§

fn default() -> Terminal<B>

Returns the “default value” for a type. Read more
Source§

impl<B> Drop for Terminal<B>
where B: Backend,

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl<B> Eq for Terminal<B>
where B: Eq + Backend,

Source§

impl<B> Hash for Terminal<B>
where B: Hash + Backend,

Source§

fn hash<__H>(&self, state: &mut __H)
where __H: Hasher,

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<B> PartialEq for Terminal<B>
where B: PartialEq + Backend,

Source§

fn eq(&self, other: &Terminal<B>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · 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<B> StructuralPartialEq for Terminal<B>
where B: PartialEq + Backend,

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<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for S
where T: Real + Zero + Arithmetics + Clone, Swp: WhitePoint<T>, Dwp: WhitePoint<T>, D: AdaptFrom<S, Swp, Dwp, T>,

Source§

fn adapt_into_using<M>(self, method: M) -> D
where M: TransformMatrix<T>,

Convert the source color to the destination color using the specified method.
Source§

fn adapt_into(self) -> D

Convert the source color to the destination color using the bradford method by default.
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, C> ArraysFrom<C> for T
where C: IntoArrays<T>,

Source§

fn arrays_from(colors: C) -> T

Cast a collection of colors into a collection of arrays.
Source§

impl<T, C> ArraysInto<C> for T
where C: FromArrays<T>,

Source§

fn arrays_into(self) -> C

Cast this collection of arrays into a collection of colors.
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<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for U
where T: FromCam16Unclamped<WpParam, U>,

Source§

type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
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, C> ComponentsFrom<C> for T
where C: IntoComponents<T>,

Source§

fn components_from(colors: C) -> T

Cast a collection of colors into a collection of color components.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromAngle<T> for T

Source§

fn from_angle(angle: T) -> T

Performs a conversion from angle.
Source§

impl<T, U> FromStimulus<U> for T
where U: IntoStimulus<T>,

Source§

fn from_stimulus(other: U) -> T

Converts other into Self, while performing the appropriate scaling, rounding and clamping.
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> IntoAngle<U> for T
where U: FromAngle<T>,

Source§

fn into_angle(self) -> U

Performs a conversion into T.
Source§

impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for U
where T: Cam16FromUnclamped<WpParam, U>,

Source§

type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T, U> IntoColor<U> for T
where U: FromColor<T>,

Source§

fn into_color(self) -> U

Convert into T with values clamped to the color defined bounds Read more
Source§

impl<T, U> IntoColorUnclamped<U> for T
where U: FromColorUnclamped<T>,

Source§

fn into_color_unclamped(self) -> U

Convert into T. The resulting color might be invalid in its color space Read more
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoStimulus<T> for T

Source§

fn into_stimulus(self) -> T

Converts self into T, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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, C> TryComponentsInto<C> for T
where C: TryFromComponents<T>,

Source§

type Error = <C as TryFromComponents<T>>::Error

The error for when try_into_colors fails to cast.
Source§

fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>

Try to cast this collection of color components into a collection of colors. 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, U> TryIntoColor<U> for T
where U: TryFromColor<T>,

Source§

fn try_into_color(self) -> Result<U, OutOfBounds<U>>

Convert into T, returning ok if the color is inside of its defined range, otherwise an OutOfBounds error is returned which contains the unclamped color. Read more
Source§

impl<C, U> UintsFrom<C> for U
where C: IntoUints<U>,

Source§

fn uints_from(colors: C) -> U

Cast a collection of colors into a collection of unsigned integers.
Source§

impl<C, U> UintsInto<C> for U
where C: FromUints<U>,

Source§

fn uints_into(self) -> C

Cast this collection of unsigned integers into a collection of colors.