diff --git a/Cargo.toml b/Cargo.toml index 211ed5bd..058352f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" exclude = ["screenshots/*"] [dependencies] -console = { version = "0.15", default-features = false, features = ["ansi-parsing"] } +console = { git = "https://github.com/chris-laplante/console.git", branch = "cpl/sync-output-drop-guard", default-features = false, features = ["ansi-parsing"] } futures-core = { version = "0.3", default-features = false, optional = true } number_prefix = "0.4" portable-atomic = "1.0.0" diff --git a/src/draw_target.rs b/src/draw_target.rs index b99b2396..5fd88584 100644 --- a/src/draw_target.rs +++ b/src/draw_target.rs @@ -472,6 +472,8 @@ impl DrawState { return Ok(()); } + let sync_guard = term.begin_sync(); + if !self.lines.is_empty() && self.move_cursor { term.move_cursor_up(last_line_count.as_usize())?; } else { @@ -547,6 +549,9 @@ impl DrawState { } term.write_str(&" ".repeat(last_line_filler))?; + // End synchronized update + drop(sync_guard); + term.flush()?; *last_line_count = real_len - orphan_visual_line_count + shift; Ok(()) diff --git a/src/lib.rs b/src/lib.rs index 85fb3147..a37ad5cc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -269,4 +269,4 @@ pub use crate::progress_bar::{ProgressBar, WeakProgressBar}; pub use crate::rayon::ParallelProgressIterator; pub use crate::state::{ProgressFinish, ProgressState}; pub use crate::style::ProgressStyle; -pub use crate::term_like::TermLike; +pub use crate::term_like::{NoOpSyncGuard, SyncGuardLike, TermLike}; diff --git a/src/term_like.rs b/src/term_like.rs index b489b655..595eddd7 100644 --- a/src/term_like.rs +++ b/src/term_like.rs @@ -3,6 +3,24 @@ use std::io; use console::Term; +pub trait SyncGuardLike<'a> { + fn finish_sync(self) -> io::Result<()>; +} + +impl<'a> SyncGuardLike<'a> for console::SyncGuard<'a> { + fn finish_sync(self) -> io::Result<()> { + self.finish_sync() + } +} + +pub struct NoOpSyncGuard; + +impl<'a> SyncGuardLike<'a> for NoOpSyncGuard { + fn finish_sync(self) -> io::Result<()> { + Ok(()) + } +} + /// A trait for minimal terminal-like behavior. /// /// Anything that implements this trait can be used a draw target via [`ProgressDrawTarget::term_like`]. @@ -34,6 +52,10 @@ pub trait TermLike: Debug + Send + Sync { fn clear_line(&self) -> io::Result<()>; fn flush(&self) -> io::Result<()>; + + fn begin_sync<'a>(&'a self) -> io::Result + 'a>> { + Ok(Box::new(NoOpSyncGuard)) + } } impl TermLike for Term { @@ -76,4 +98,9 @@ impl TermLike for Term { fn flush(&self) -> io::Result<()> { self.flush() } + + fn begin_sync<'a>(&'a self) -> io::Result + 'a>> { + console::SyncGuard::begin_sync(self) + .map(|guard| Box::new(guard) as Box>) + } }