1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use crate::backend::Backend;
use crate::layout::Size;
use crate::terminal::Terminal;
impl<B: Backend> Terminal<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`].
///
/// [`TestBackend`]: crate::backend::TestBackend
pub const fn backend(&self) -> &B {
&self.backend
}
/// 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.
///
/// [`Terminal::clear`]: crate::terminal::Terminal::clear
/// [`Terminal::draw`]: crate::terminal::Terminal::draw
/// [`Terminal::try_draw`]: crate::terminal::Terminal::try_draw
pub const fn backend_mut(&mut self) -> &mut B {
&mut self.backend
}
/// 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`].
///
/// [`Frame::area`]: crate::terminal::Frame::area
/// [`Terminal::autoresize`]: crate::terminal::Terminal::autoresize
/// [`Terminal::draw`]: crate::terminal::Terminal::draw
/// [`Terminal::try_draw`]: crate::terminal::Terminal::try_draw
/// [`Viewport`]: crate::terminal::Viewport
pub fn size(&self) -> Result<Size, B::Error> {
self.backend.size()
}
}
#[cfg(test)]
mod tests {
use crate::backend::TestBackend;
use crate::layout::{Position, Size};
use crate::terminal::Terminal;
#[test]
fn backend_returns_shared_reference() {
let backend = TestBackend::new(3, 2);
let terminal = Terminal::new(backend).unwrap();
assert_eq!(terminal.backend().cursor_position(), Position::ORIGIN);
}
#[test]
fn backend_mut_allows_mutating_backend_state() {
let backend = TestBackend::new(3, 2);
let mut terminal = Terminal::new(backend).unwrap();
terminal.backend_mut().resize(4, 3);
assert_eq!(terminal.size().unwrap(), Size::new(4, 3));
terminal
.backend()
.assert_buffer_lines([" ", " ", " "]);
}
#[test]
fn size_queries_underlying_backend_size() {
let mut backend = TestBackend::new(3, 2);
backend.resize(4, 3);
let terminal = Terminal::new(backend).unwrap();
assert_eq!(terminal.size().unwrap(), Size::new(4, 3));
}
}