forked from mirrors/jj
cli: hide cursor during progress display
This commit is contained in:
parent
472b6926e5
commit
210b54afd7
2 changed files with 33 additions and 0 deletions
|
@ -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();
|
||||||
|
|
22
src/ui.rs
22
src/ui.rs
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue