From 853f3d9200da1a76a2fba24af098ff037d11ad53 Mon Sep 17 00:00:00 2001 From: Florian Dehau Date: Fri, 1 Jan 2021 16:20:51 +0100 Subject: [PATCH] feat(terminal): add a read-only view of the terminal state after the draw call --- src/backend/test.rs | 6 ++++++ src/lib.rs | 6 ++++-- src/terminal.rs | 15 +++++++++++++-- tests/terminal.rs | 23 +++++++++++++++++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/backend/test.rs b/src/backend/test.rs index f9e2b86..3f317f8 100644 --- a/src/backend/test.rs +++ b/src/backend/test.rs @@ -60,6 +60,12 @@ impl TestBackend { &self.buffer } + pub fn resize(&mut self, width: u16, height: u16) { + self.buffer.resize(Rect::new(0, 0, width, height)); + self.width = width; + self.height = height; + } + pub fn assert_buffer(&self, expected: &Buffer) { assert_eq!(expected.area, self.buffer.area); let diff = expected.diff(&self.buffer); diff --git a/src/lib.rs b/src/lib.rs index 422598a..65810f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,7 +94,8 @@ //! .title("Block") //! .borders(Borders::ALL); //! f.render_widget(block, size); -//! }) +//! })?; +//! Ok(()) //! } //! ``` //! @@ -136,7 +137,8 @@ //! .title("Block 2") //! .borders(Borders::ALL); //! f.render_widget(block, chunks[1]); -//! }) +//! })?; +//! Ok(()) //! } //! ``` //! diff --git a/src/terminal.rs b/src/terminal.rs index 12521a6..48d43be 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -148,6 +148,14 @@ where } } +/// CompletedFrame represents the state of the terminal after all changes performed in the last +/// [`Terminal::draw`] call have been applied. Therefore, it is only valid until the next call to +/// [`Terminal::draw`]. +pub struct CompletedFrame<'a> { + pub buffer: &'a Buffer, + pub area: Rect, +} + impl Drop for Terminal where B: Backend, @@ -247,7 +255,7 @@ where /// Synchronizes terminal size, calls the rendering closure, flushes the current internal state /// and prepares for the next draw call. - pub fn draw(&mut self, f: F) -> io::Result<()> + pub fn draw(&mut self, f: F) -> io::Result where F: FnOnce(&mut Frame), { @@ -279,7 +287,10 @@ where // Flush self.backend.flush()?; - Ok(()) + Ok(CompletedFrame { + buffer: &self.buffers[1 - self.current], + area: self.viewport.area, + }) } pub fn hide_cursor(&mut self) -> io::Result<()> { diff --git a/tests/terminal.rs b/tests/terminal.rs index 67305e0..705c97e 100644 --- a/tests/terminal.rs +++ b/tests/terminal.rs @@ -1,5 +1,8 @@ +use std::error::Error; use tui::{ backend::{Backend, TestBackend}, + layout::Rect, + widgets::Paragraph, Terminal, }; @@ -11,3 +14,23 @@ fn terminal_buffer_size_should_be_limited() { assert_eq!(size.width, 255); assert_eq!(size.height, 255); } + +#[test] +fn terminal_draw_returns_the_completed_frame() -> Result<(), Box> { + let backend = TestBackend::new(10, 10); + let mut terminal = Terminal::new(backend)?; + let frame = terminal.draw(|f| { + let paragrah = Paragraph::new("Test"); + f.render_widget(paragrah, f.size()); + })?; + assert_eq!(frame.buffer.get(0, 0).symbol, "T"); + assert_eq!(frame.area, Rect::new(0, 0, 10, 10)); + terminal.backend_mut().resize(8, 8); + let frame = terminal.draw(|f| { + let paragrah = Paragraph::new("test"); + f.render_widget(paragrah, f.size()); + })?; + assert_eq!(frame.buffer.get(0, 0).symbol, "t"); + assert_eq!(frame.area, Rect::new(0, 0, 8, 8)); + Ok(()) +}