diff --git a/src/lib.rs b/src/lib.rs index a1ac2275..ebc5ec39 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,7 +78,7 @@ pub use crate::kb::Key; pub use crate::term::{ - user_attended, user_attended_stderr, Term, TermFamily, TermFeatures, TermTarget, + user_attended, user_attended_stderr, SyncGuard, Term, TermFamily, TermFeatures, TermTarget, }; pub use crate::utils::{ colors_enabled, colors_enabled_stderr, measure_text_width, pad_str, pad_str_with, diff --git a/src/term.rs b/src/term.rs index 44e94055..4ea1459e 100644 --- a/src/term.rs +++ b/src/term.rs @@ -1,3 +1,4 @@ +use std::cell::Cell; use std::fmt::{Debug, Display}; use std::io::{self, Read, Write}; use std::sync::{Arc, Mutex, RwLock}; @@ -78,6 +79,19 @@ impl<'a> TermFeatures<'a> { is_a_color_terminal(self.0) } + #[inline] + pub fn is_synchronized_output_supported(&self) -> bool { + #[cfg(unix)] + { + supports_synchronized_output() + } + #[cfg(not(unix))] + { + // TODO + false + } + } + /// Check if this terminal is an msys terminal. /// /// This is sometimes useful to disable features that are known to not @@ -656,6 +670,42 @@ impl<'a> Read for &'a Term { } } +pub struct SyncGuard<'a> { + term: Cell>, +} + +impl<'a> SyncGuard<'a> { + pub fn begin_sync(term: &'a Term) -> io::Result { + let ret = if term.features().is_synchronized_output_supported() { + term.write_str("\x1b[?2026h")?; + Some(term) + } else { + None + }; + + Ok(Self { + term: Cell::new(ret), + }) + } + + pub fn finish_sync(self) -> io::Result<()> { + self.finish_sync_inner() + } + + fn finish_sync_inner(&self) -> io::Result<()> { + if let Some(term) = self.term.take() { + term.write_str("\x1b[?2026l")?; + } + Ok(()) + } +} + +impl Drop for SyncGuard<'_> { + fn drop(&mut self) { + let _ = self.finish_sync_inner(); + } +} + #[cfg(all(unix, not(target_arch = "wasm32")))] pub use crate::unix_term::*; #[cfg(target_arch = "wasm32")]