diff options
author | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2020-02-08 20:58:03 -0500 |
---|---|---|
committer | Jiayi Zhao <jeff.no.zhao@gmail.com> | 2020-02-08 20:58:55 -0500 |
commit | 656582a6c867c25667661be9b327b4cc73859d7d (patch) | |
tree | fe03a1822b752a747da099aeb33a610fb3590067 /src/util | |
parent | 7a603efb9b3024438bdce8899fd21bcf353e3832 (diff) |
change to using termion's keyboard handling
- user input is now on a seperate thread
- this allows for other threads to be added as well
- keymap configs have changed to be more user friendly
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/event.rs | 83 | ||||
-rw-r--r-- | src/util/key_mapping.rs | 64 | ||||
-rw-r--r-- | src/util/mod.rs | 78 |
3 files changed, 225 insertions, 0 deletions
diff --git a/src/util/event.rs b/src/util/event.rs new file mode 100644 index 0000000..c6559cf --- /dev/null +++ b/src/util/event.rs @@ -0,0 +1,83 @@ +use std::io; +use std::sync::mpsc; +use std::thread; +use std::time::Duration; + +use termion::event::Key; +use termion::input::TermRead; + +#[derive(Debug)] +pub enum Event<I> { + Input(I), + Tick, +} + +#[derive(Debug, Clone, Copy)] +pub struct Config { + pub tick_rate: Duration, +} + +impl Default for Config { + fn default() -> Config { + Config { + tick_rate: Duration::from_millis(250), + } + } +} + +/// 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 { + rx: mpsc::Receiver<Event<Key>>, + input_handle: thread::JoinHandle<()>, +// tick_handle: thread::JoinHandle<()>, +} + +impl Events { + pub fn new() -> Events { + Events::with_config(Config::default()) + } + + pub fn with_config(config: Config) -> Events { + let (tx, rx) = mpsc::channel(); + let input_handle = { + let tx = tx.clone(); + thread::spawn(move || { + let stdin = io::stdin(); + for evt in stdin.keys() { + match evt { + Ok(key) => { + if let Err(e) = tx.send(Event::Input(key)) { + eprintln!("Err: {:#?}", e); + return; + } + } + Err(e) => {} + } + } + }) + }; +/* + let tick_handle = { + let tx = tx.clone(); + thread::spawn(move || { + let tx = tx.clone(); + loop { + tx.send(Event::Tick).unwrap(); + thread::sleep(config.tick_rate); + } + }) + }; +*/ + Events { + rx, + input_handle, +// tick_handle, + } + } + + pub fn next(&self) -> Result<Event<Key>, mpsc::RecvError> { + self.rx.recv() + } +} + diff --git a/src/util/key_mapping.rs b/src/util/key_mapping.rs new file mode 100644 index 0000000..9d7c182 --- /dev/null +++ b/src/util/key_mapping.rs @@ -0,0 +1,64 @@ +use termion::event::Key; + +pub fn str_to_key(s: &str) -> Option<Key> { + if s.len() == 0 { + return None; + } + + let key = match s { + "backspace" => Some(Key::Backspace), + "left" => Some(Key::Left), + "right" => Some(Key::Right), + "up" => Some(Key::Up), + "down" => Some(Key::Down), + "home" => Some(Key::Home), + "end" => Some(Key::End), + "page_up" => Some(Key::PageUp), + "page_down" => Some(Key::PageDown), + "delete" => Some(Key::Delete), + "insert" => Some(Key::Insert), + "escape" => Some(Key::Esc), + "tab" => Some(Key::BackTab), + "f1" => Some(Key::F(1)), + "f2" => Some(Key::F(2)), + "f3" => Some(Key::F(3)), + "f4" => Some(Key::F(4)), + "f5" => Some(Key::F(5)), + "f6" => Some(Key::F(6)), + "f7" => Some(Key::F(7)), + "f8" => Some(Key::F(8)), + "f9" => Some(Key::F(9)), + "f10" => Some(Key::F(10)), + "f11" => Some(Key::F(11)), + "f12" => Some(Key::F(12)), + _ => None, + }; + + if let Some(a) = key { + return key; + } + + if s.starts_with("ctrl+") { + let ch = s.chars().skip("ctrl+".len()).next(); + let key = match ch { + Some(ch) => Some(Key::Ctrl(ch)), + None => None, + }; + return key; + } else if s.starts_with("alt+") { + let ch = s.chars().skip("alt+".len()).next(); + let key = match ch { + Some(ch) => Some(Key::Alt(ch)), + None => None, + }; + return key; + } else if s.len() == 1 { + let ch = s.chars().next(); + let key = match ch { + Some(ch) => Some(Key::Char(ch)), + None => None, + }; + return key; + } + return None; +} diff --git a/src/util/mod.rs b/src/util/mod.rs new file mode 100644 index 0000000..94ead10 --- /dev/null +++ b/src/util/mod.rs @@ -0,0 +1,78 @@ +pub mod event; +pub mod key_mapping; + +use rand::distributions::{Distribution, Uniform}; +use rand::rngs::ThreadRng; + +#[derive(Clone)] +pub struct RandomSignal { + distribution: Uniform<u64>, + rng: ThreadRng, +} + +impl RandomSignal { + pub fn new(lower: u64, upper: u64) -> RandomSignal { + RandomSignal { + distribution: Uniform::new(lower, upper), + rng: rand::thread_rng(), + } + } +} + +impl Iterator for RandomSignal { + type Item = u64; + fn next(&mut self) -> Option<u64> { + Some(self.distribution.sample(&mut self.rng)) + } +} + +#[derive(Clone)] +pub struct SinSignal { + x: f64, + interval: f64, + period: f64, + scale: f64, +} + +impl SinSignal { + pub fn new(interval: f64, period: f64, scale: f64) -> SinSignal { + SinSignal { + x: 0.0, + interval, + period, + scale, + } + } +} + +impl Iterator for SinSignal { + type Item = (f64, f64); + fn next(&mut self) -> Option<Self::Item> { + let point = (self.x, (self.x * 1.0 / self.period).sin() * self.scale); + self.x += self.interval; + Some(point) + } +} + +pub struct TabsState<'a> { + pub titles: Vec<&'a str>, + pub index: usize, +} + +impl<'a> TabsState<'a> { + pub fn new(titles: Vec<&'a str>) -> TabsState { + TabsState { titles, index: 0 } + } + pub fn next(&mut self) { + self.index = (self.index + 1) % self.titles.len(); + } + + pub fn previous(&mut self) { + if self.index > 0 { + self.index -= 1; + } else { + self.index = self.titles.len() - 1; + } + } +} + |