diff options
Diffstat (limited to 'src/event.rs')
-rw-r--r-- | src/event.rs | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/event.rs b/src/event.rs new file mode 100644 index 0000000..da9330e --- /dev/null +++ b/src/event.rs @@ -0,0 +1,109 @@ +use std::io; +use std::path; +use std::process; +use std::sync::mpsc; +use std::thread; + +use signal_hook::consts::signal; +use signal_hook::iterator::exfiltrator::SignalOnly; +use signal_hook::iterator::SignalsInfo; + +use termion::event::Event; +use termion::input::TermRead; + +use crate::io::IoWorkerProgress; + +#[derive(Debug)] +pub enum AppEvent { + Termion(Event), + IoWorkerProgress(IoWorkerProgress), + IoWorkerResult(io::Result<IoWorkerProgress>), + PreviewDir(io::Result<path::PathBuf>), + PreviewFile(process::Output), + Signal(i32), + // Filesystem(notify::Result), +} + +#[derive(Debug, Clone, Copy)] +pub struct Config {} + +impl Default for Config { + fn default() -> Config { + Config {} + } +} + +/// A small event handler that wrap termion input and tick events. Each event +/// type is handled in its own thread and returned to a common `Receiver` +pub struct Events { + pub event_tx: mpsc::Sender<AppEvent>, + event_rx: mpsc::Receiver<AppEvent>, + pub input_tx: mpsc::SyncSender<()>, +} + +impl Events { + pub fn new() -> Self { + Events::with_config() + } + + pub fn with_config() -> Self { + let (input_tx, input_rx) = mpsc::sync_channel(1); + let (event_tx, event_rx) = mpsc::channel(); + + // signal thread + let event_tx2 = event_tx.clone(); + let _ = thread::spawn(move || { + let sigs = vec![signal::SIGWINCH]; + let mut signals = SignalsInfo::<SignalOnly>::new(&sigs).unwrap(); + for signal in &mut signals { + if let Err(e) = event_tx2.send(AppEvent::Signal(signal)) { + eprintln!("Signal thread send err: {:#?}", e); + return; + } + } + }); + + // input thread + let event_tx2 = event_tx.clone(); + let _ = thread::spawn(move || { + let stdin = io::stdin(); + let mut events = stdin.events(); + match events.next() { + Some(event) => match event { + Ok(event) => { + if let Err(e) = event_tx2.send(AppEvent::Termion(event)) { + eprintln!("Input thread send err: {:#?}", e); + return; + } + } + Err(_) => return, + }, + None => return, + } + + while input_rx.recv().is_ok() { + if let Some(Ok(event)) = events.next() { + if let Err(e) = event_tx2.send(AppEvent::Termion(event)) { + eprintln!("Input thread send err: {:#?}", e); + return; + } + } + } + }); + + Events { + event_tx, + event_rx, + input_tx, + } + } + + pub fn next(&self) -> Result<AppEvent, mpsc::RecvError> { + let event = self.event_rx.recv()?; + Ok(event) + } + + pub fn flush(&self) { + let _ = self.input_tx.send(()); + } +} |