From 7c3436ea96d3e897b184f8b57fc554950885459c Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sun, 27 Oct 2019 13:32:58 -0400 Subject: copy implementation over from teleterm --- src/lib.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 31e1bb2..218010e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,72 @@ -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); +use futures::future::Future as _; +use futures::stream::Stream as _; +use snafu::futures01::StreamExt as _; +use snafu::ResultExt as _; +use std::convert::TryInto as _; + +#[derive(Debug, snafu::Snafu)] +pub enum Error { + #[snafu(display("failed to get terminal size"))] + GetTerminalSize, + + #[snafu(display("invalid terminal size found: {}", source))] + InvalidTerminalSize { source: std::num::TryFromIntError }, + + #[snafu(display("SIGWINCH handler failed: {}", source))] + SigWinchHandler { source: std::io::Error }, +} + +pub type Result = std::result::Result; + +pub struct Resizer { + winches: + Box + Send>, + sent_initial_size: bool, +} + +impl Resizer { + pub fn new() -> Self { + Self::default() + } +} + +impl Default for Resizer { + fn default() -> Self { + let winches = tokio_signal::unix::Signal::new( + tokio_signal::unix::libc::SIGWINCH, + ) + .flatten_stream() + .map(|_| ()) + .context(SigWinchHandler); + Self { + winches: Box::new(winches), + sent_initial_size: false, + } + } +} + +#[must_use = "streams do nothing unless polled"] +impl futures::stream::Stream for Resizer { + type Item = (u16, u16); + type Error = Error; + + fn poll(&mut self) -> futures::Poll, Self::Error> { + if !self.sent_initial_size { + self.sent_initial_size = true; + return Ok(futures::Async::Ready(Some(term_size()?))); + } + let _ = futures::try_ready!(self.winches.poll()); + Ok(futures::Async::Ready(Some(term_size()?))) + } +} + +fn term_size() -> Result<(u16, u16)> { + if let Some((cols, rows)) = term_size::dimensions() { + Ok(( + rows.try_into().context(InvalidTerminalSize)?, + cols.try_into().context(InvalidTerminalSize)?, + )) + } else { + Err(Error::GetTerminalSize) } } -- cgit v1.2.3-54-g00ecf