ratatui_core/terminal/backend.rs
1use crate::backend::Backend;
2use crate::layout::Size;
3use crate::terminal::Terminal;
4
5impl<B: Backend> Terminal<B> {
6 /// Returns a shared reference to the backend.
7 ///
8 /// This is primarily useful for backend-specific inspection in tests (e.g. reading
9 /// [`TestBackend`]'s buffer) or for backend-specific APIs that Ratatui does not model.
10 ///
11 /// Reading from the backend does not desynchronize Ratatui, but values observed here may lag
12 /// behind the current render callback because Ratatui does not apply a frame to the backend
13 /// until the end of [`Terminal::draw`] / [`Terminal::try_draw`].
14 ///
15 /// [`TestBackend`]: crate::backend::TestBackend
16 pub const fn backend(&self) -> &B {
17 &self.backend
18 }
19
20 /// Returns a mutable reference to the backend.
21 ///
22 /// This is an advanced escape hatch. Normal applications should render through
23 /// [`Terminal::draw`] / [`Terminal::try_draw`] instead of mutating the backend directly.
24 ///
25 /// Use this when integrating with backend-specific APIs that Ratatui does not model, or when
26 /// tests need direct control over backend state.
27 ///
28 /// Mutating the backend directly can desynchronize Ratatui's internal buffers, cursor
29 /// tracking, or viewport assumptions from what's on-screen. If you do this, call
30 /// [`Terminal::clear`] or perform a full draw pass before relying on Ratatui's view of the
31 /// terminal again.
32 ///
33 /// [`Terminal::clear`]: crate::terminal::Terminal::clear
34 /// [`Terminal::draw`]: crate::terminal::Terminal::draw
35 /// [`Terminal::try_draw`]: crate::terminal::Terminal::try_draw
36 pub const fn backend_mut(&mut self) -> &mut B {
37 &mut self.backend
38 }
39
40 /// Queries the real size of the backend.
41 ///
42 /// This returns the backend's current terminal size and does not update Ratatui's internal
43 /// viewport bookkeeping by itself. The current renderable area depends on the configured
44 /// [`Viewport`]; use [`Frame::area`] inside [`Terminal::draw`] / [`Terminal::try_draw`] if you
45 /// want the area you should render into for the current pass.
46 ///
47 /// To make Ratatui observe backend size changes for fullscreen or inline viewports, see
48 /// [`Terminal::autoresize`].
49 ///
50 /// [`Frame::area`]: crate::terminal::Frame::area
51 /// [`Terminal::autoresize`]: crate::terminal::Terminal::autoresize
52 /// [`Terminal::draw`]: crate::terminal::Terminal::draw
53 /// [`Terminal::try_draw`]: crate::terminal::Terminal::try_draw
54 /// [`Viewport`]: crate::terminal::Viewport
55 pub fn size(&self) -> Result<Size, B::Error> {
56 self.backend.size()
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use crate::backend::TestBackend;
63 use crate::layout::{Position, Size};
64 use crate::terminal::Terminal;
65
66 #[test]
67 fn backend_returns_shared_reference() {
68 let backend = TestBackend::new(3, 2);
69 let terminal = Terminal::new(backend).unwrap();
70
71 assert_eq!(terminal.backend().cursor_position(), Position::ORIGIN);
72 }
73
74 #[test]
75 fn backend_mut_allows_mutating_backend_state() {
76 let backend = TestBackend::new(3, 2);
77 let mut terminal = Terminal::new(backend).unwrap();
78
79 terminal.backend_mut().resize(4, 3);
80
81 assert_eq!(terminal.size().unwrap(), Size::new(4, 3));
82 terminal
83 .backend()
84 .assert_buffer_lines([" ", " ", " "]);
85 }
86
87 #[test]
88 fn size_queries_underlying_backend_size() {
89 let mut backend = TestBackend::new(3, 2);
90 backend.resize(4, 3);
91 let terminal = Terminal::new(backend).unwrap();
92
93 assert_eq!(terminal.size().unwrap(), Size::new(4, 3));
94 }
95}