From 7b4d35d224c1b15d415be9979b4c5cde637dfacb Mon Sep 17 00:00:00 2001 From: Florian Dehau Date: Mon, 24 Sep 2018 07:54:33 +0200 Subject: [PATCH] feat: restore the cursor state on terminal drop --- examples/barchart.rs | 1 - examples/block.rs | 1 - examples/canvas.rs | 1 - examples/chart.rs | 1 - examples/crossterm.rs | 1 - examples/demo.rs | 1 - examples/gauge.rs | 1 - examples/layout.rs | 1 - examples/list.rs | 1 - examples/paragraph.rs | 1 - examples/sparkline.rs | 1 - examples/table.rs | 1 - examples/user_input.rs | 1 + src/terminal.rs | 41 +++++++++++++++++++++++++++++++---------- 14 files changed, 32 insertions(+), 22 deletions(-) diff --git a/examples/barchart.rs b/examples/barchart.rs index 90a567d..4be84ed 100644 --- a/examples/barchart.rs +++ b/examples/barchart.rs @@ -132,6 +132,5 @@ fn main() -> Result<(), failure::Error> { } } - terminal.show_cursor()?; Ok(()) } diff --git a/examples/block.rs b/examples/block.rs index e622db7..a98e416 100644 --- a/examples/block.rs +++ b/examples/block.rs @@ -105,6 +105,5 @@ fn main() -> Result<(), failure::Error> { _ => {} } } - terminal.show_cursor()?; Ok(()) } diff --git a/examples/canvas.rs b/examples/canvas.rs index 6eed2a9..83bc8a0 100644 --- a/examples/canvas.rs +++ b/examples/canvas.rs @@ -176,6 +176,5 @@ fn main() -> Result<(), failure::Error> { } } - terminal.show_cursor()?; Ok(()) } diff --git a/examples/chart.rs b/examples/chart.rs index 3799de2..80f06a9 100644 --- a/examples/chart.rs +++ b/examples/chart.rs @@ -129,6 +129,5 @@ fn main() -> Result<(), failure::Error> { } } - terminal.show_cursor()?; Ok(()) } diff --git a/examples/crossterm.rs b/examples/crossterm.rs index 37262f6..53d305d 100644 --- a/examples/crossterm.rs +++ b/examples/crossterm.rs @@ -55,6 +55,5 @@ fn main() -> Result<(), failure::Error> { _ => {} }; } - terminal.show_cursor()?; Ok(()) } diff --git a/examples/demo.rs b/examples/demo.rs index 55a462b..414f960 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -249,7 +249,6 @@ fn main() -> Result<(), failure::Error> { } } } - terminal.show_cursor()?; Ok(()) } diff --git a/examples/gauge.rs b/examples/gauge.rs index 3d59a78..edbb5ce 100644 --- a/examples/gauge.rs +++ b/examples/gauge.rs @@ -125,6 +125,5 @@ fn main() -> Result<(), failure::Error> { } } - terminal.show_cursor()?; Ok(()) } diff --git a/examples/layout.rs b/examples/layout.rs index 5e98ac1..bf16b32 100644 --- a/examples/layout.rs +++ b/examples/layout.rs @@ -85,6 +85,5 @@ fn main() -> Result<(), failure::Error> { } } - terminal.show_cursor()?; Ok(()) } diff --git a/examples/list.rs b/examples/list.rs index 6feeae1..01eea90 100644 --- a/examples/list.rs +++ b/examples/list.rs @@ -174,6 +174,5 @@ fn main() -> Result<(), failure::Error> { } } - terminal.show_cursor()?; Ok(()) } diff --git a/examples/paragraph.rs b/examples/paragraph.rs index a99f232..429a8db 100644 --- a/examples/paragraph.rs +++ b/examples/paragraph.rs @@ -102,6 +102,5 @@ fn main() -> Result<(), failure::Error> { _ => {} } } - terminal.show_cursor()?; Ok(()) } diff --git a/examples/sparkline.rs b/examples/sparkline.rs index ee58016..61c6bd8 100644 --- a/examples/sparkline.rs +++ b/examples/sparkline.rs @@ -128,6 +128,5 @@ fn main() -> Result<(), failure::Error> { } } - terminal.show_cursor()?; Ok(()) } diff --git a/examples/table.rs b/examples/table.rs index b90cf2f..d626f93 100644 --- a/examples/table.rs +++ b/examples/table.rs @@ -108,6 +108,5 @@ fn main() -> Result<(), failure::Error> { }; } - terminal.show_cursor()?; Ok(()) } diff --git a/examples/user_input.rs b/examples/user_input.rs index 212d898..205b449 100644 --- a/examples/user_input.rs +++ b/examples/user_input.rs @@ -57,6 +57,7 @@ fn main() -> Result<(), failure::Error> { let stdout = AlternateScreen::from(stdout); let backend = TermionBackend::new(stdout); let mut terminal = Terminal::new(backend)?; + terminal.hide_cursor()?; // Setup event handlers let events = Events::new(); diff --git a/src/terminal.rs b/src/terminal.rs index 5984506..a01e0db 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -17,6 +17,8 @@ where buffers: [Buffer; 2], /// Index of the current buffer in the previous array current: usize, + /// Whether the cursor is currently hidden + hidden_cursor: bool, } pub struct Frame<'a, B: 'a> @@ -39,18 +41,33 @@ where } } +impl Drop for Terminal +where + B: Backend, +{ + fn drop(&mut self) { + // Attempt to restore the cursor state + if self.hidden_cursor { + if let Err(_) = self.show_cursor() { + error!("Failed to show the cursor"); + } + } + } +} + impl Terminal where B: Backend, { /// Wrapper around Termion initialization. Each buffer is initialized with a blank string and /// default colors for the foreground and the background - pub fn new(backend: B) -> Result, io::Error> { + pub fn new(backend: B) -> io::Result> { let size = backend.size()?; Ok(Terminal { backend, buffers: [Buffer::empty(size), Buffer::empty(size)], current: 0, + hidden_cursor: false, }) } @@ -72,7 +89,7 @@ where /// Builds a string representing the minimal escape sequences and characters set necessary to /// update the UI and writes it to stdout. - pub fn flush(&mut self) -> Result<(), io::Error> { + pub fn flush(&mut self) -> io::Result<()> { let width = self.buffers[self.current].area.width; let content = self.buffers[self.current] .content @@ -94,7 +111,7 @@ where /// Updates the interface so that internal buffers matches the current size of the terminal. /// This leads to a full redraw of the screen. - pub fn resize(&mut self, area: Rect) -> Result<(), io::Error> { + pub fn resize(&mut self, area: Rect) -> io::Result<()> { self.buffers[self.current].resize(area); self.buffers[1 - self.current].reset(); self.buffers[1 - self.current].resize(area); @@ -102,7 +119,7 @@ where } /// Flushes the current internal state and prepares the interface for the next draw call - pub fn draw(&mut self, f: F) -> Result<(), io::Error> + pub fn draw(&mut self, f: F) -> io::Result<()> where F: FnOnce(Frame), { @@ -120,16 +137,20 @@ where Ok(()) } - pub fn hide_cursor(&mut self) -> Result<(), io::Error> { - self.backend.hide_cursor() + pub fn hide_cursor(&mut self) -> io::Result<()> { + self.backend.hide_cursor()?; + self.hidden_cursor = true; + Ok(()) } - pub fn show_cursor(&mut self) -> Result<(), io::Error> { - self.backend.show_cursor() + pub fn show_cursor(&mut self) -> io::Result<()> { + self.backend.show_cursor()?; + self.hidden_cursor = false; + Ok(()) } - pub fn clear(&mut self) -> Result<(), io::Error> { + pub fn clear(&mut self) -> io::Result<()> { self.backend.clear() } - pub fn size(&self) -> Result { + pub fn size(&self) -> io::Result { self.backend.size() } }