From 210b54afd721b6d4f3b670a25f96e5cdd45cd588 Mon Sep 17 00:00:00 2001 From: Benjamin Saunders Date: Sat, 29 Oct 2022 19:34:17 -0700 Subject: [PATCH] cli: hide cursor during progress display --- src/progress.rs | 11 +++++++++++ src/ui.rs | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/progress.rs b/src/progress.rs index 6bccd0ca2..0e45d6634 100644 --- a/src/progress.rs +++ b/src/progress.rs @@ -4,12 +4,14 @@ use std::time::{Duration, Instant}; use crossterm::terminal::{Clear, ClearType}; use jujutsu_lib::git; +use crate::cleanup_guard::CleanupGuard; use crate::ui::Ui; pub struct Progress { next_print: Instant, rate: RateEstimate, buffer: String, + guard: Option, } impl Progress { @@ -18,6 +20,7 @@ impl Progress { next_print: now + INITIAL_DELAY, rate: RateEstimate::new(), buffer: String::new(), + guard: None, } } @@ -40,6 +43,14 @@ impl Progress { if now < self.next_print { return Ok(()); } + if self.guard.is_none() { + let guard = self.ui.output_guard(crossterm::cursor::Show.to_string()); + let guard = CleanupGuard::new(move || { + drop(guard); + }); + _ = write!(self.ui, "{}", crossterm::cursor::Hide); + self.guard = Some(guard); + } self.next_print = now.min(self.next_print + Duration::from_secs(1) / UPDATE_HZ); self.buffer.clear(); diff --git a/src/ui.rs b/src/ui.rs index 0562a3562..3eeb53d9e 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -234,8 +234,30 @@ impl Ui { pub fn size(&self) -> Option<(u16, u16)> { crossterm::terminal::size().ok() } + + /// Construct a guard object which writes `data` when dropped. Useful for + /// restoring terminal state. + pub fn output_guard(&self, text: String) -> OutputGuard { + OutputGuard { + text, + output: match self.output_pair { + UiOutputPair::Terminal { .. } => io::stdout(), + }, + } + } } enum UiOutputPair { Terminal { stdout: Stdout, stderr: Stderr }, } + +pub struct OutputGuard { + text: String, + output: Stdout, +} + +impl Drop for OutputGuard { + fn drop(&mut self) { + _ = self.output.write_all(self.text.as_bytes()); + } +}