From 894ec4f24c1269166f14c05b2ae3f737f76dd571 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 24 Oct 2019 15:16:10 -0400 Subject: add a couple examples --- examples/interhack.rs | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 examples/interhack.rs (limited to 'examples/interhack.rs') diff --git a/examples/interhack.rs b/examples/interhack.rs new file mode 100644 index 0000000..c0c575e --- /dev/null +++ b/examples/interhack.rs @@ -0,0 +1,127 @@ +#![allow(clippy::trivial_regex)] + +use futures::stream::Stream as _; +use std::io::Write as _; +use tokio::io::AsyncRead as _; + +mod input; + +struct Interhack { + process: tokio_pty_process_stream::Process, + stdin: input::evented_stdin::Stdin, + read_buf: [u8; 4096], + raw_screen: Option, +} + +impl Interhack { + fn new() -> Self { + Self { + process: tokio_pty_process_stream::Process::new( + "nethack", + &[], + input::buf::Stdin::new(), + ), + stdin: input::evented_stdin::Stdin::new(), + read_buf: [0; 4096], + raw_screen: None, + } + } + + fn filter_input(&self, buf: Vec) -> Vec { + lazy_static::lazy_static! { + static ref RE: regex::bytes::Regex = regex::bytes::Regex::new( + "\x05" + ).unwrap(); + } + if let Some(m) = RE.find(&buf) { + let mut new: Vec = vec![]; + new.extend(buf[..m.start()].iter()); + new.extend(b"E- Elbereth\n"); + new.extend(buf[m.end()..].iter()); + new + } else { + buf + } + } + + fn filter_output(&self, buf: Vec) -> Vec { + lazy_static::lazy_static! { + static ref RE: regex::bytes::Regex = regex::bytes::Regex::new( + r"Elbereth" + ).unwrap(); + } + if let Some(m) = RE.find(&buf) { + let mut new: Vec = vec![]; + new.extend(buf[..m.start()].iter()); + new.extend(b"\x1b[35m"); + new.extend(buf[m.start()..m.end()].iter()); + new.extend(b"\x1b[m"); + new.extend(buf[m.end()..].iter()); + new + } else { + buf + } + } +} + +#[allow(clippy::type_complexity)] +impl Interhack { + const POLL_FNS: + &'static [&'static dyn for<'a> Fn( + &'a mut Self, + ) + -> component_future::Poll<(), ()>] = + &[&Self::poll_input, &Self::poll_process, &Self::poll_screen]; + + fn poll_input(&mut self) -> component_future::Poll<(), ()> { + let n = component_future::try_ready!(self + .stdin + .poll_read(&mut self.read_buf) + .map_err(|e| panic!(e))); + let input = self.filter_input(self.read_buf[..n].to_vec()); + self.process.input().send(&input); + Ok(component_future::Async::DidWork) + } + + fn poll_process(&mut self) -> component_future::Poll<(), ()> { + let event = component_future::try_ready!(self + .process + .poll() + .map_err(|e| panic!(e))); + match event { + Some(tokio_pty_process_stream::Event::Output { data }) => { + let output = self.filter_output(data); + let stdout = std::io::stdout(); + let mut stdout = stdout.lock(); + stdout.write_all(&output).unwrap(); + stdout.flush().unwrap(); + } + None => return Ok(component_future::Async::Ready(())), + _ => {} + } + Ok(component_future::Async::DidWork) + } + + fn poll_screen(&mut self) -> component_future::Poll<(), ()> { + if self.raw_screen.is_none() { + self.raw_screen = + Some(crossterm::RawScreen::into_raw_mode().unwrap()); + Ok(component_future::Async::DidWork) + } else { + Ok(component_future::Async::NothingToDo) + } + } +} + +impl futures::future::Future for Interhack { + type Item = (); + type Error = (); + + fn poll(&mut self) -> futures::Poll { + component_future::poll_future(self, Self::POLL_FNS) + } +} + +fn main() { + tokio::run(futures::future::lazy(Interhack::new)); +} -- cgit v1.2.3-54-g00ecf