ok/jj
1
0
Fork 0
forked from mirrors/jj

cli: hide cursor during progress display

This commit is contained in:
Benjamin Saunders 2022-10-29 19:34:17 -07:00
parent 472b6926e5
commit 210b54afd7
2 changed files with 33 additions and 0 deletions

View file

@ -4,12 +4,14 @@ use std::time::{Duration, Instant};
use crossterm::terminal::{Clear, ClearType}; use crossterm::terminal::{Clear, ClearType};
use jujutsu_lib::git; use jujutsu_lib::git;
use crate::cleanup_guard::CleanupGuard;
use crate::ui::Ui; use crate::ui::Ui;
pub struct Progress { pub struct Progress {
next_print: Instant, next_print: Instant,
rate: RateEstimate, rate: RateEstimate,
buffer: String, buffer: String,
guard: Option<CleanupGuard>,
} }
impl Progress { impl Progress {
@ -18,6 +20,7 @@ impl Progress {
next_print: now + INITIAL_DELAY, next_print: now + INITIAL_DELAY,
rate: RateEstimate::new(), rate: RateEstimate::new(),
buffer: String::new(), buffer: String::new(),
guard: None,
} }
} }
@ -40,6 +43,14 @@ impl Progress {
if now < self.next_print { if now < self.next_print {
return Ok(()); 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.next_print = now.min(self.next_print + Duration::from_secs(1) / UPDATE_HZ);
self.buffer.clear(); self.buffer.clear();

View file

@ -234,8 +234,30 @@ impl Ui {
pub fn size(&self) -> Option<(u16, u16)> { pub fn size(&self) -> Option<(u16, u16)> {
crossterm::terminal::size().ok() 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 { enum UiOutputPair {
Terminal { stdout: Stdout, stderr: Stderr }, 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());
}
}