use std::io::{self, Write};
use anyhow::Result;
use crossterm::{
QueueableCommand, execute,
terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate},
};
struct SynchronizedOutput<'a, W: Write> {
writer: Option<&'a mut W>,
}
impl<W: Write> SynchronizedOutput<'_, W> {
fn finish(&mut self) -> io::Result<()> {
if let Some(writer) = self.writer.take() {
execute!(writer, EndSynchronizedUpdate)?;
}
Ok(())
}
}
impl<W: Write> Drop for SynchronizedOutput<'_, W> {
fn drop(&mut self) {
let _ = self.finish();
}
}
pub(in crate::tui) fn draw_synchronized<W: Write, T>(
writer: &mut W,
draw: impl FnOnce(&mut W) -> Result<T>,
) -> Result<T> {
let mut output = SynchronizedOutput {
writer: Some(writer),
};
let writer = output.writer.as_deref_mut().expect("active frame writer");
writer.queue(BeginSynchronizedUpdate)?;
let draw_result = draw(writer);
let finish_result = output.finish();
let value = draw_result?;
finish_result?;
Ok(value)
}