diff --git a/Cargo.toml b/Cargo.toml index 390bb24..ef9e7f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -default = ["crossterm-backend"] +default = ["termion-backend"] termion-backend = ["tui/termion", "termion"] crossterm-backend = ["tui/crossterm", "crossterm"] diff --git a/src/app.rs b/src/app.rs index 8248ebf..46700fd 100644 --- a/src/app.rs +++ b/src/app.rs @@ -25,8 +25,6 @@ use tui::{ use crate::util::{Key}; -use crossterm::event::KeyCode; - pub fn cmp(t1: &Task, t2: &Task) -> Ordering { let urgency1 = match &t1.uda()["urgency"] { UDAValue::Str(_) => 0.0, diff --git a/src/util.rs b/src/util.rs index a9ec723..af50311 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,17 +1,24 @@ -use std::io::{stdout, Write}; - -#[cfg(feature = "crossterm")] -use crossterm::event; #[cfg(feature = "crossterm")] use crossterm::{ - event::{DisableMouseCapture, EnableMouseCapture, KeyCode}, + event::{self, DisableMouseCapture, EnableMouseCapture, KeyCode}, execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; - #[cfg(feature = "crossterm")] use tui::{backend::CrosstermBackend, Terminal}; + +#[cfg(all(feature = "termion", not(feature = "crossterm")))] +use termion::{ + event, + input::{TermRead,MouseTerminal}, + raw::{IntoRawMode, RawTerminal}, + screen::AlternateScreen, +}; +#[cfg(all(feature = "termion", not(feature = "crossterm")))] +use tui::{backend::TermionBackend, Terminal}; + +use std::io::{self, Write}; use std::{sync::mpsc, thread, time::Duration}; #[derive(Debug, Clone, Copy)] @@ -49,34 +56,45 @@ impl Default for EventConfig { } } -/// An occurred event. +#[derive(Debug, Clone, Copy)] pub enum Event { - /// An input event occurred. Input(I), - /// An tick event occurred. Tick, } #[cfg(feature = "crossterm")] -pub fn setup_terminal() -> Terminal> { +pub fn setup_terminal() -> Terminal> { enable_raw_mode().unwrap(); - let mut stdout = stdout(); + let mut stdout = io::stdout(); execute!(stdout, EnterAlternateScreen, EnableMouseCapture).unwrap(); let backend = CrosstermBackend::new(stdout); Terminal::new(backend).unwrap() } #[cfg(feature = "crossterm")] -pub fn destruct_terminal(mut terminal: Terminal>) { +pub fn destruct_terminal(mut terminal: Terminal>) { disable_raw_mode().unwrap(); - execute!(stdout(), LeaveAlternateScreen, DisableMouseCapture).unwrap(); + execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture).unwrap(); terminal.show_cursor().unwrap(); } +#[cfg(all(feature = "termion", not(feature = "crossterm")))] +pub fn setup_terminal() -> Terminal>>>> { + let stdout = io::stdout().into_raw_mode().unwrap(); + let stdout = MouseTerminal::from(stdout); + let stdout = AlternateScreen::from(stdout); + let backend = TermionBackend::new(stdout); + Terminal::new(backend).unwrap() +} + +#[cfg(all(feature = "termion", not(feature = "crossterm")))] +pub fn destruct_terminal(terminal: Terminal>>>> ) { +} + + pub struct Events { rx: mpsc::Receiver>, - tx: mpsc::Sender>, } impl Events { @@ -88,6 +106,7 @@ impl Events { }) } + #[cfg(feature = "crossterm")] pub fn with_config(config: EventConfig) -> Events { use crossterm::event::{KeyCode::*, KeyModifiers}; let (tx, rx) = mpsc::channel(); @@ -130,10 +149,59 @@ impl Events { event_tx.send(Event::Tick).unwrap(); } }); - - Events { rx, tx } + Events { rx } } + #[cfg(all(feature = "termion", not(feature = "crossterm")))] + pub fn with_config(config: EventConfig) -> Events { + use termion::event::Key::*; + let (tx, rx) = mpsc::channel(); + let input_handle = { + let tx = tx.clone(); + thread::spawn(move || { + let stdin = io::stdin(); + for evt in stdin.keys() { + if let Ok(key) = evt { + let key = match key { + 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, + _ => Key::Null, + }; + if let Err(err) = tx.send(Event::Input(key)) { + eprintln!("{}", err); + return; + } + } + } + }) + }; + let tick_handle = { + thread::spawn(move || loop { + if tx.send(Event::Tick).is_err() { + break; + } + thread::sleep(config.tick_rate); + }) + }; + Events {rx} + } + /// Attempts to read an event. /// This function will block the current thread. pub fn next(&self) -> Result, mpsc::RecvError> {