Skip to main content

uncurses_ratatui/
lib.rs

1//! Backend integration between the widget library and
2//! [`uncurses::screen::Screen`].
3//!
4//! ## What this backend is
5//!
6//! [`UncursesBackend`] implements [`ratatui::backend::Backend`] by wrapping a
7//! single [`Screen`](uncurses::screen::Screen). The screen owns the
8//! terminal handle, its diffing renderer, and the input source. The backend's job is to adapt
9//! frame drawing, cursor operations, clearing, size queries, and event access
10//! to that one screen.
11//!
12//! ## Rendering path
13//!
14//! A frame is rendered into the widget library's buffer first. During
15//! [`Backend::draw`](ratatui::backend::Backend::draw), every visible buffer
16//! cell is converted into an uncurses cell and staged into the screen's
17//! buffer; no I/O happens yet.
18//! [`Backend::flush`](ratatui::backend::Backend::flush) then calls
19//! [`Screen::render`](uncurses::screen::Screen::render), which diffs the
20//! staged frame and writes the minimal escape bytes.
21//!
22//! ```text
23//! ┌──────────────────────┐
24//! │ widgets render Frame │
25//! └──────────┬───────────┘
26//!            │ ratatui::buffer::Cell values
27//!            ▼
28//! ┌──────────────────────┐
29//! │   UncursesBackend    │
30//! │ draw: Cell → Cell    │
31//! └──────────┬───────────┘
32//!            │ set_cell (stage only)
33//!            ▼
34//! ┌──────────────────────┐
35//! │        Screen        │
36//! │   renderer diff bytes │
37//! └──────────┬───────────┘
38//!            │ flush → Screen::render
39//!            ▼
40//!        terminal
41//! ```
42//!
43//! ## Setup and restore helpers
44//!
45//! Use [`try_init`] / [`init`] for the standard fullscreen session over
46//! process stdio. Use [`try_init_with_options`] / [`init_with_options`] when
47//! you need explicit [`ratatui::TerminalOptions`] or [`ScreenOptions`]. Pair
48//! those helpers with [`try_restore`] or [`restore`] on exit.
49//!
50//! The helpers enter raw mode, apply screen options, hide the cursor, and set
51//! up the requested viewport. They enter the alternate screen for fullscreen
52//! and fixed viewports; inline viewports stay on the main screen so scrollback
53//! around the application is preserved.
54//!
55//! ```rust,ignore
56//! use ratatui::widgets::Paragraph;
57//!
58//! fn main() -> std::io::Result<()> {
59//!     let mut terminal = uncurses_ratatui::try_init()?;
60//!     terminal.draw(|frame| {
61//!         frame.render_widget(Paragraph::new("drawn through uncurses"), frame.area());
62//!     })?;
63//!     uncurses_ratatui::try_restore(&mut terminal)
64//! }
65//! ```
66//!
67//! ## Viewports
68//!
69//! [`ratatui::Viewport::Fullscreen`] and [`ratatui::Viewport::Fixed`] are
70//! rendered on the alternate screen by the setup helpers. For
71//! [`ratatui::Viewport::Inline`], the backend keeps an inline origin in the
72//! main screen, resizes the screen buffer to the inline height, and translates
73//! absolute frame rows into that buffer before staging cells.
74//!
75//! ## Reading input through the backend
76//!
77//! The backend owns the same input source as the wrapped screen. Synchronous
78//! event loops can call [`UncursesBackend::poll_event`],
79//! [`UncursesBackend::try_read_event`], or [`UncursesBackend::read_event`] on
80//! `terminal.backend_mut()`. These reads are pure, like
81//! [`Screen`](uncurses::screen::Screen)'s: pass each event to
82//! [`UncursesBackend::observe_event`] to keep capability tracking alive.
83//!
84//! With the `async` feature, use [`UncursesBackend::event_stream`] with
85//! [`UncursesBackend::observe_event`] when an asynchronous loop is more
86//! convenient.
87//!
88//! ## Manual setup
89//!
90//! The constructors are inert: they do not enter raw mode, choose a viewport,
91//! enter the alternate screen, or hide the cursor. Use them when you need a
92//! prebuilt [`Screen`](uncurses::screen::Screen), a controlling terminal
93//! instead of stdio, or custom setup ordering.
94//!
95//! ```rust,ignore
96//! use uncurses_ratatui::{ScreenOptions, UncursesBackend};
97//!
98//! fn main() -> std::io::Result<()> {
99//!     let mut backend = UncursesBackend::stdio()?;
100//!     backend.init_with(ScreenOptions::default())?;
101//!     // Build ratatui::Terminal with `backend`, then restore the backend
102//!     // when the session ends.
103//!     Ok(())
104//! }
105//! ```
106
107mod backend;
108mod convert;
109mod init;
110
111pub use backend::{Output, UncursesBackend};
112pub use convert::{to_uncurses_color, to_uncurses_style};
113pub use init::{
114    DefaultTerminal, init, init_with_options, restore, try_init, try_init_with_options, try_restore,
115};
116#[doc(no_inline)]
117pub use uncurses::screen::{MouseTracking, ScreenOptions};