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