Skip to content

Commit

Permalink
Make sure conversions are always compiled
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Jul 6, 2020
1 parent 11d6665 commit 5a03628
Showing 1 changed file with 54 additions and 51 deletions.
105 changes: 54 additions & 51 deletions crosstermion/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<crossterm::event::KeyEvent> for Key {
type Error = crossterm::event::KeyEvent;
Expand Down Expand Up @@ -59,20 +60,54 @@ mod _impl {
}
}

#[cfg(feature = "termion")]
/// Convert from `termion::event::Key`
impl std::convert::TryFrom<termion::event::Key> for Key {
type Error = termion::event::Key;

fn try_from(value: termion::event::Key) -> Result<Self, Self::Error> {
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<Key> {
pub fn key_input_channel() -> crossbeam_channel::Receiver<super::Key> {
use std::convert::TryInto;

let (key_send, key_receive) = crossbeam_channel::bounded::<Key>(0);
let (key_send, key_receive) = crossbeam_channel::bounded::<super::Key>(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, _> = key.try_into();
let key: Result<super::Key, _> = key.try_into();
if let Ok(key) = key {
if key_send.send(key).is_err() {
break;
Expand All @@ -88,16 +123,16 @@ mod _impl {
}

#[cfg(all(feature = "input-thread-flume", not(feature = "input-thread")))]
pub fn key_input_channel() -> flume::Receiver<Key> {
pub fn key_input_channel() -> flume::Receiver<super::Key> {
use std::convert::TryInto;

let (key_send, key_receive) = flume::bounded::<Key>(0);
let (key_send, key_receive) = flume::bounded::<super::Key>(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, _> = key.try_into();
let key: Result<super::Key, _> = key.try_into();
if let Ok(key) = key {
if key_send.send(key).is_err() {
break;
Expand All @@ -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<Item = Key> {
pub fn key_input_stream() -> impl futures_util::stream::Stream<Item = super::Key> {
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,
})
})
Expand All @@ -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<termion::event::Key> for Key {
type Error = termion::event::Key;

fn try_from(value: termion::event::Key) -> Result<Self, Self::Error> {
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<Item = Key> {
pub fn key_input_stream() -> impl futures_util::stream::Stream<Item = super::Key> {
use futures_util::SinkExt;
use std::{convert::TryInto, io};
use termion::input::TermRead;

let (mut key_send, key_receive) = futures_channel::mpsc::channel::<Key>(1);
let (mut key_send, key_receive) = futures_channel::mpsc::channel::<super::Key>(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, _> = key?.try_into();
let key: Result<super::Key, _> = key?.try_into();
if let Ok(key) = key {
if futures_executor::block_on(key_send.send(key)).is_err() {
break;
Expand All @@ -190,14 +193,14 @@ mod _impl {
}

#[cfg(feature = "input-thread")]
pub fn key_input_channel() -> crossbeam_channel::Receiver<Key> {
pub fn key_input_channel() -> crossbeam_channel::Receiver<super::Key> {
use std::{convert::TryInto, io};
use termion::input::TermRead;

let (key_send, key_receive) = crossbeam_channel::bounded::<Key>(1);
let (key_send, key_receive) = crossbeam_channel::bounded::<super::Key>(1);
std::thread::spawn(move || -> Result<(), io::Error> {
for key in io::stdin().keys() {
let key: Result<Key, _> = key?.try_into();
let key: Result<super::Key, _> = key?.try_into();
if let Ok(key) = key {
if key_send.send(key).is_err() {
break;
Expand All @@ -210,14 +213,14 @@ mod _impl {
}

#[cfg(all(feature = "input-thread-flume", not(feature = "input-thread")))]
pub fn key_input_channel() -> flume::Receiver<Key> {
pub fn key_input_channel() -> flume::Receiver<super::Key> {
use std::{convert::TryInto, io};
use termion::input::TermRead;

let (key_send, key_receive) = flume::bounded::<Key>(1);
let (key_send, key_receive) = flume::bounded::<super::Key>(1);
std::thread::spawn(move || -> Result<(), io::Error> {
for key in io::stdin().keys() {
let key: Result<Key, _> = key?.try_into();
let key: Result<super::Key, _> = key?.try_into();
if let Ok(key) = key {
if key_send.send(key).is_err() {
break;
Expand Down

0 comments on commit 5a03628

Please sign in to comment.