From 5a03628b1cafd8d06476f364242d0e149f4fad18 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 6 Jul 2020 08:53:21 +0800 Subject: [PATCH] Make sure conversions are always compiled --- crosstermion/src/input.rs | 105 ++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/crosstermion/src/input.rs b/crosstermion/src/input.rs index 902f9c0..7f72355 100644 --- a/crosstermion/src/input.rs +++ b/crosstermion/src/input.rs @@ -21,10 +21,11 @@ pub enum Key { Esc, } -#[cfg(feature = "crossterm")] -mod _impl { +mod convert { + #[cfg(any(feature = "crossterm", feature = "termion"))] use super::Key; + #[cfg(feature = "crossterm")] /// Convert from `crossterm::event::KeyEvent` impl std::convert::TryFrom for Key { type Error = crossterm::event::KeyEvent; @@ -59,20 +60,54 @@ mod _impl { } } + #[cfg(feature = "termion")] + /// Convert from `termion::event::Key` + impl std::convert::TryFrom for Key { + type Error = termion::event::Key; + + fn try_from(value: termion::event::Key) -> Result { + use termion::event::Key::*; + Ok(match value { + Backspace => Key::Backspace, + Left => Key::Left, + Right => Key::Right, + Up => Key::Up, + Down => Key::Down, + Home => Key::Home, + End => Key::End, + PageUp => Key::PageUp, + PageDown => Key::PageDown, + BackTab => Key::BackTab, + Delete => Key::Delete, + Insert => Key::Insert, + F(c) => Key::F(c), + Char(c) => Key::Char(c), + Alt(c) => Key::Alt(c), + Ctrl(c) => Key::Ctrl(c), + Null => Key::Null, + Esc => Key::Esc, + _ => return Err(value), + }) + } + } +} + +#[cfg(feature = "crossterm")] +mod _impl { /// Return a receiver of user input events to avoid blocking the main thread. /// /// Requires feature `input-thread` #[cfg(feature = "input-thread")] - pub fn key_input_channel() -> crossbeam_channel::Receiver { + pub fn key_input_channel() -> crossbeam_channel::Receiver { use std::convert::TryInto; - let (key_send, key_receive) = crossbeam_channel::bounded::(0); + let (key_send, key_receive) = crossbeam_channel::bounded::(0); std::thread::spawn(move || -> Result<(), std::io::Error> { loop { let event = crossterm::event::read().map_err(crate::crossterm::into_io_error)?; match event { crossterm::event::Event::Key(key) => { - let key: Result = key.try_into(); + let key: Result = key.try_into(); if let Ok(key) = key { if key_send.send(key).is_err() { break; @@ -88,16 +123,16 @@ mod _impl { } #[cfg(all(feature = "input-thread-flume", not(feature = "input-thread")))] - pub fn key_input_channel() -> flume::Receiver { + pub fn key_input_channel() -> flume::Receiver { use std::convert::TryInto; - let (key_send, key_receive) = flume::bounded::(0); + let (key_send, key_receive) = flume::bounded::(0); std::thread::spawn(move || -> Result<(), std::io::Error> { loop { let event = crossterm::event::read().map_err(crate::crossterm::into_io_error)?; match event { crossterm::event::Event::Key(key) => { - let key: Result = key.try_into(); + let key: Result = key.try_into(); if let Ok(key) = key { if key_send.send(key).is_err() { break; @@ -116,14 +151,14 @@ mod _impl { /// /// Requires the `input-async` feature. #[cfg(feature = "input-async")] - pub fn key_input_stream() -> impl futures_util::stream::Stream { + pub fn key_input_stream() -> impl futures_util::stream::Stream { use futures_util::StreamExt; use std::convert::TryFrom; crossterm::event::EventStream::new() .filter_map(|r| futures_util::future::ready(r.ok())) .filter_map(|e| { futures_util::future::ready(match e { - crossterm::event::Event::Key(key) => Key::try_from(key).ok(), + crossterm::event::Event::Key(key) => super::Key::try_from(key).ok(), _ => None, }) }) @@ -132,52 +167,20 @@ mod _impl { #[cfg(all(feature = "termion", not(feature = "crossterm")))] mod _impl { - use super::Key; - - /// Convert from `termion::event::Key` - impl std::convert::TryFrom for Key { - type Error = termion::event::Key; - - fn try_from(value: termion::event::Key) -> Result { - use termion::event::Key::*; - Ok(match value { - Backspace => Key::Backspace, - Left => Key::Left, - Right => Key::Right, - Up => Key::Up, - Down => Key::Down, - Home => Key::Home, - End => Key::End, - PageUp => Key::PageUp, - PageDown => Key::PageDown, - BackTab => Key::BackTab, - Delete => Key::Delete, - Insert => Key::Insert, - F(c) => Key::F(c), - Char(c) => Key::Char(c), - Alt(c) => Key::Alt(c), - Ctrl(c) => Key::Ctrl(c), - Null => Key::Null, - Esc => Key::Esc, - _ => return Err(value), - }) - } - } - /// Return a stream of user input events. /// /// Requires feature `futures-channel` #[cfg(feature = "input-async")] - pub fn key_input_stream() -> impl futures_util::stream::Stream { + pub fn key_input_stream() -> impl futures_util::stream::Stream { use futures_util::SinkExt; use std::{convert::TryInto, io}; use termion::input::TermRead; - let (mut key_send, key_receive) = futures_channel::mpsc::channel::(1); + let (mut key_send, key_receive) = futures_channel::mpsc::channel::(1); // This brings blocking key-handling into the async world std::thread::spawn(move || -> Result<(), io::Error> { for key in io::stdin().keys() { - let key: Result = key?.try_into(); + let key: Result = key?.try_into(); if let Ok(key) = key { if futures_executor::block_on(key_send.send(key)).is_err() { break; @@ -190,14 +193,14 @@ mod _impl { } #[cfg(feature = "input-thread")] - pub fn key_input_channel() -> crossbeam_channel::Receiver { + pub fn key_input_channel() -> crossbeam_channel::Receiver { use std::{convert::TryInto, io}; use termion::input::TermRead; - let (key_send, key_receive) = crossbeam_channel::bounded::(1); + let (key_send, key_receive) = crossbeam_channel::bounded::(1); std::thread::spawn(move || -> Result<(), io::Error> { for key in io::stdin().keys() { - let key: Result = key?.try_into(); + let key: Result = key?.try_into(); if let Ok(key) = key { if key_send.send(key).is_err() { break; @@ -210,14 +213,14 @@ mod _impl { } #[cfg(all(feature = "input-thread-flume", not(feature = "input-thread")))] - pub fn key_input_channel() -> flume::Receiver { + pub fn key_input_channel() -> flume::Receiver { use std::{convert::TryInto, io}; use termion::input::TermRead; - let (key_send, key_receive) = flume::bounded::(1); + let (key_send, key_receive) = flume::bounded::(1); std::thread::spawn(move || -> Result<(), io::Error> { for key in io::stdin().keys() { - let key: Result = key?.try_into(); + let key: Result = key?.try_into(); if let Ok(key) = key { if key_send.send(key).is_err() { break;