use {
crossterm::{ExecutableCommand, cursor::*},
std::io::*,
};
pub struct PositionalWriter<InnerT>
where
InnerT: Write,
{
pub inner: InnerT,
restore: bool,
}
impl<InnerT> PositionalWriter<InnerT>
where
InnerT: Write,
{
pub fn new(inner: InnerT) -> Self {
Self { inner, restore: false }
}
#[allow(unused)]
pub fn new_save(mut inner: InnerT) -> Result<Self> {
inner.execute(SavePosition)?;
Ok(Self { inner, restore: true })
}
pub fn new_save_at(mut inner: InnerT, x: u16, y: u16) -> Result<Self> {
inner.execute(SavePosition)?.execute(MoveTo(x, y))?;
Ok(Self { inner, restore: true })
}
pub fn new_save_at_maybe(inner: InnerT, position: Option<(usize, usize)>) -> Result<Self> {
match position {
Some((x, y)) => Self::new_save_at(inner, x as u16, y as u16),
None => Ok(Self::new(inner)),
}
}
pub fn at(&mut self, x: u16, y: u16) -> Result<()> {
self.restore = true;
self.inner.execute(MoveTo(x, y)).map(|_| ())
}
}
impl<InnerT> Write for PositionalWriter<InnerT>
where
InnerT: Write,
{
fn write(&mut self, buffer: &[u8]) -> Result<usize> {
self.inner.write(buffer)
}
fn flush(&mut self) -> Result<()> {
self.inner.flush()
}
}
impl<InnerT> Drop for PositionalWriter<InnerT>
where
InnerT: Write,
{
fn drop(&mut self) {
if self.restore {
_ = self.inner.execute(RestorePosition);
}
}
}