Skip to content

Commit

Permalink
Implement crossterm buffer creation (alternate + raw)
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Jul 3, 2020
1 parent 659065d commit eaf904b
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ tui-renderer = ["tui",
log-renderer = ["log"]
localtime = ["time"]
with-termion = ["termion", "tui/termion"]
with-crossterm = ["termion", "tui/termion"]
with-crossterm = ["crossterm", "tui/crossterm"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
Expand Down
66 changes: 66 additions & 0 deletions src/tui/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,72 @@ mod _impl {
}
}

#[cfg(all(feature = "crossterm", not(feature = "termion")))]
mod _impl {
use crate::tui::input::Key;
use crossterm::terminal::disable_raw_mode;
use crossterm::{
execute,
terminal::{enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use futures_util::SinkExt;
use std::io;
use tui::backend::CrosstermBackend;
use tui_react::Terminal;

pub struct AlternateScreen<T: io::Write> {
inner: T,
}

fn into_io_error(err: crossterm::ErrorKind) -> io::Error {
if let crossterm::ErrorKind::IoError(err) = err {
return err;
}
unimplemented!("we cannot currently handle non-io errors reported by crossterm")
}

impl<T: io::Write> AlternateScreen<T> {
fn new(mut write: T) -> Result<AlternateScreen<T>, io::Error> {
enable_raw_mode().map_err(into_io_error)?;
execute!(write, EnterAlternateScreen).map_err(into_io_error)?;
Ok(AlternateScreen { inner: write })
}
}

impl<T: io::Write> io::Write for AlternateScreen<T> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.write(buf)
}

fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
}

impl<T: io::Write> Drop for AlternateScreen<T> {
fn drop(&mut self) {
disable_raw_mode().ok();
execute!(self.inner, LeaveAlternateScreen).ok();
}
}

pub fn new_terminal(
) -> Result<Terminal<CrosstermBackend<AlternateScreen<io::Stdout>>>, io::Error> {
let backend = CrosstermBackend::new(AlternateScreen::new(io::stdout())?);
Ok(Terminal::new(backend)?)
}

pub fn key_input_stream() -> futures_channel::mpsc::Receiver<Key> {
let (mut key_send, key_receive) = futures_channel::mpsc::channel::<Key>(1);
// This brings blocking key-handling into the async world
std::thread::spawn(move || -> Result<(), io::Error> {
unimplemented!("todo: key processing");
Ok(())
});
key_receive
}
}

#[cfg(not(any(feature = "termion", feature = "crossterm")))]
mod _impl {
use crate::tui::engine::input::Key;
Expand Down

0 comments on commit eaf904b

Please sign in to comment.