2023-04-13 14:09:59 +02:00
|
|
|
use crossterm::event::{KeyEvent, MouseEvent};
|
|
|
|
use std::fmt;
|
|
|
|
use std::sync::mpsc;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum EventError {
|
|
|
|
Send(Event),
|
|
|
|
Recv,
|
|
|
|
Io(std::io::Error),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for EventError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
match *self {
|
|
|
|
Self::Send(ref e) => write!(f, "failed to send event: {e:?}"),
|
|
|
|
Self::Recv => write!(f, "receive event call failed"),
|
|
|
|
Self::Io(ref e) => {
|
|
|
|
write!(f, "an I/O error was triggered during event handling: {e}")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<mpsc::SendError<Event>> for EventError {
|
|
|
|
fn from(err: mpsc::SendError<Event>) -> EventError {
|
|
|
|
EventError::Send(err.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<mpsc::RecvError> for EventError {
|
|
|
|
fn from(_: mpsc::RecvError) -> EventError {
|
|
|
|
EventError::Recv
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
|
|
pub enum Event {
|
|
|
|
Key(KeyEvent),
|
|
|
|
Mouse(MouseEvent),
|
|
|
|
Resize(u16, u16),
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct EventChannel {
|
|
|
|
sender: mpsc::Sender<Event>,
|
|
|
|
receiver: mpsc::Receiver<Event>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct EventSender {
|
|
|
|
sender: mpsc::Sender<Event>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct EventReceiver {
|
|
|
|
receiver: mpsc::Receiver<Event>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EventChannel {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
let (sender, receiver) = mpsc::channel();
|
|
|
|
EventChannel { sender, receiver }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn sender(&self) -> EventSender {
|
|
|
|
EventSender {
|
|
|
|
sender: self.sender.clone(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn receiver(self) -> EventReceiver {
|
|
|
|
EventReceiver {
|
|
|
|
receiver: self.receiver,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EventSender {
|
|
|
|
pub fn send(&self, event: Event) -> Result<(), EventError> {
|
|
|
|
Ok(self.sender.send(event)?)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EventReceiver {
|
|
|
|
pub fn recv(&self) -> Result<Event, EventError> {
|
|
|
|
Ok(self.receiver.recv()?)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use std::io;
|
|
|
|
|
|
|
|
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers};
|
|
|
|
|
2024-01-22 23:01:34 +01:00
|
|
|
use super::*;
|
2023-04-13 14:09:59 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn event_sender() {
|
|
|
|
let channel = EventChannel::new();
|
|
|
|
let sender = channel.sender();
|
|
|
|
let receiver = channel.receiver();
|
|
|
|
let event = Event::Key(KeyEvent::new(KeyCode::Up, KeyModifiers::empty()));
|
|
|
|
|
|
|
|
let result = sender.send(event);
|
|
|
|
assert!(result.is_ok());
|
|
|
|
|
|
|
|
drop(receiver);
|
|
|
|
let result = sender.send(event);
|
|
|
|
assert!(result.is_err());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn event_receiver() {
|
|
|
|
let channel = EventChannel::new();
|
|
|
|
let sender = channel.sender();
|
|
|
|
let receiver = channel.receiver();
|
|
|
|
let event = Event::Key(KeyEvent::new(KeyCode::Up, KeyModifiers::empty()));
|
|
|
|
|
|
|
|
sender.send(event).unwrap();
|
|
|
|
let result = receiver.recv();
|
|
|
|
assert!(result.is_ok());
|
|
|
|
|
|
|
|
drop(sender);
|
|
|
|
let result = receiver.recv();
|
|
|
|
assert!(result.is_err());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn errors() {
|
|
|
|
let send_err = EventError::Send(Event::Key(KeyEvent {
|
|
|
|
code: KeyCode::Up,
|
|
|
|
modifiers: KeyModifiers::empty(),
|
|
|
|
kind: KeyEventKind::Press,
|
|
|
|
state: KeyEventState::NONE,
|
|
|
|
}));
|
|
|
|
let recv_err = EventError::Recv;
|
|
|
|
let io_err = EventError::Io(io::Error::new(io::ErrorKind::Interrupted, "interrupted"));
|
|
|
|
|
|
|
|
assert!(!send_err.to_string().is_empty());
|
|
|
|
assert!(!recv_err.to_string().is_empty());
|
|
|
|
assert!(!io_err.to_string().is_empty());
|
|
|
|
|
|
|
|
assert!(!format!("{:?}", send_err).is_empty());
|
|
|
|
assert!(!format!("{:?}", recv_err).is_empty());
|
|
|
|
assert!(!format!("{:?}", io_err).is_empty());
|
|
|
|
}
|
|
|
|
}
|