From 62fe2477fb8bbbfbca34779b992979f9c1a8ba53 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sat, 11 Dec 2021 17:54:10 -0500 Subject: move key handling into the main event loop --- src/action.rs | 7 ++ src/main.rs | 17 +--- src/state.rs | 253 ++++++++++++++++++++++++++++++---------------------------- 3 files changed, 139 insertions(+), 138 deletions(-) diff --git a/src/action.rs b/src/action.rs index 2cb28c1..ff0402b 100644 --- a/src/action.rs +++ b/src/action.rs @@ -1,5 +1,6 @@ #[derive(Debug)] pub enum Action { + Key(textmode::Key), Render, ForceRedraw, Run(String), @@ -67,6 +68,7 @@ impl Reader { #[derive(Default)] struct Pending { + key: std::collections::VecDeque, render: Option<()>, force_redraw: Option<()>, run: std::collections::VecDeque, @@ -84,6 +86,7 @@ impl Pending { fn has_action(&self) -> bool { self.done + || !self.key.is_empty() || self.render.is_some() || self.force_redraw.is_some() || !self.run.is_empty() @@ -97,6 +100,9 @@ impl Pending { if self.done { return None; } + if !self.key.is_empty() { + return Some(Action::Key(self.key.pop_front().unwrap())); + } if self.size.is_some() { return Some(Action::Resize(self.size.take().unwrap())); } @@ -124,6 +130,7 @@ impl Pending { fn new_action(&mut self, action: &Option) { match action { + Some(Action::Key(key)) => self.key.push_back(key.clone()), Some(Action::Render) => self.render = Some(()), Some(Action::ForceRedraw) => self.force_redraw = Some(()), Some(Action::Run(cmd)) => self.run.push_back(cmd.to_string()), diff --git a/src/main.rs b/src/main.rs index 6f7046b..1a15f6e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,11 +61,9 @@ async fn async_main() -> anyhow::Result<()> { let (action_w, action_r) = async_std::channel::unbounded(); - let state = state::State::new(get_offset()); + let mut state = state::State::new(get_offset()); state.render(&mut output, true).await.unwrap(); - let state = util::mutex(state); - { let mut signals = signal_hook_async_std::Signals::new(&[ signal_hook::consts::signal::SIGWINCH, @@ -81,15 +79,10 @@ async fn async_main() -> anyhow::Result<()> { resize(&action_w).await; { - let state = async_std::sync::Arc::clone(&state); let action_w = action_w.clone(); async_std::task::spawn(async move { while let Some(key) = input.read_key().await.unwrap() { - if let Some(action) = - state.lock_arc().await.handle_key(key).await - { - action_w.send(action).await.unwrap(); - } + action_w.send(action::Action::Key(key)).await.unwrap(); } }); } @@ -117,11 +110,7 @@ async fn async_main() -> anyhow::Result<()> { let action_reader = action::Reader::new(action_r); while let Some(action) = action_reader.recv().await { - state - .lock_arc() - .await - .handle_action(action, &mut output, &action_w) - .await; + state.handle_action(action, &mut output, &action_w).await; } Ok(()) diff --git a/src/state.rs b/src/state.rs index 6ecfa07..f086334 100644 --- a/src/state.rs +++ b/src/state.rs @@ -23,130 +23,6 @@ impl State { } } - pub async fn handle_key( - &mut self, - key: textmode::Key, - ) -> Option { - if self.escape { - self.escape = false; - self.handle_key_escape(key).await - } else if key == textmode::Key::Ctrl(b'e') { - self.escape = true; - None - } else { - match self.focus { - crate::action::Focus::Readline => { - self.readline - .handle_key(key, self.history.entry_count()) - .await - } - crate::action::Focus::History(idx) => { - self.history.handle_key(key, idx).await; - None - } - crate::action::Focus::Scrolling(_) => { - self.handle_key_escape(key).await - } - } - } - } - - async fn handle_key_escape( - &mut self, - key: textmode::Key, - ) -> Option { - match key { - textmode::Key::Ctrl(b'd') => { - return Some(crate::action::Action::Quit); - } - textmode::Key::Ctrl(b'e') => { - self.set_focus( - crate::action::Focus::Scrolling(self.focus_idx()), - None, - ) - .await; - } - textmode::Key::Ctrl(b'l') => { - return Some(crate::action::Action::ForceRedraw); - } - textmode::Key::Ctrl(b'm') => { - let idx = self.focus_idx(); - let (focus, entry) = if let Some(idx) = idx { - let entry = self.history.entry(idx).await; - (entry.running(), Some(entry)) - } else { - (true, None) - }; - if focus { - self.set_focus( - idx.map_or(crate::action::Focus::Readline, |idx| { - crate::action::Focus::History(idx) - }), - entry, - ) - .await; - } - } - textmode::Key::Char(' ') => { - if let Some(idx) = self.focus_idx() { - let entry = self.history.entry(idx).await; - self.readline.set_input(&entry.cmd()); - self.set_focus( - crate::action::Focus::Readline, - Some(entry), - ) - .await; - } - } - textmode::Key::Char('e') => { - if let crate::action::Focus::History(idx) = self.focus { - self.history - .handle_key(textmode::Key::Ctrl(b'e'), idx) - .await; - } - } - textmode::Key::Char('f') => { - if let Some(idx) = self.focus_idx() { - let mut entry = self.history.entry(idx).await; - let mut focus = crate::action::Focus::History(idx); - if let crate::action::Focus::Scrolling(_) = self.focus { - entry.set_fullscreen(true); - } else { - entry.toggle_fullscreen(); - if !entry.should_fullscreen() && !entry.running() { - focus = - crate::action::Focus::Scrolling(Some(idx)); - } - } - self.set_focus(focus, Some(entry)).await; - } - } - textmode::Key::Char('j') | textmode::Key::Down => { - self.set_focus( - crate::action::Focus::Scrolling( - self.scroll_down(self.focus_idx()), - ), - None, - ) - .await; - } - textmode::Key::Char('k') | textmode::Key::Up => { - self.set_focus( - crate::action::Focus::Scrolling( - self.scroll_up(self.focus_idx()), - ), - None, - ) - .await; - } - textmode::Key::Char('r') => { - self.set_focus(crate::action::Focus::Readline, None).await; - } - _ => {} - } - Some(crate::action::Action::Render) - } - pub async fn render( &self, out: &mut textmode::Output, @@ -246,6 +122,11 @@ impl State { ) { let mut hard_refresh = false; match action { + crate::action::Action::Key(key) => { + if let Some(action) = self.handle_key(key).await { + action_w.send(action).await.unwrap(); + } + } crate::action::Action::Render => { // for instance, if we are rerendering because of command // output, that output could increase the number of lines of @@ -295,6 +176,130 @@ impl State { self.render(out, hard_refresh).await.unwrap(); } + async fn handle_key( + &mut self, + key: textmode::Key, + ) -> Option { + if self.escape { + self.escape = false; + self.handle_key_escape(key).await + } else if key == textmode::Key::Ctrl(b'e') { + self.escape = true; + None + } else { + match self.focus { + crate::action::Focus::Readline => { + self.readline + .handle_key(key, self.history.entry_count()) + .await + } + crate::action::Focus::History(idx) => { + self.history.handle_key(key, idx).await; + None + } + crate::action::Focus::Scrolling(_) => { + self.handle_key_escape(key).await + } + } + } + } + + async fn handle_key_escape( + &mut self, + key: textmode::Key, + ) -> Option { + match key { + textmode::Key::Ctrl(b'd') => { + return Some(crate::action::Action::Quit); + } + textmode::Key::Ctrl(b'e') => { + self.set_focus( + crate::action::Focus::Scrolling(self.focus_idx()), + None, + ) + .await; + } + textmode::Key::Ctrl(b'l') => { + return Some(crate::action::Action::ForceRedraw); + } + textmode::Key::Ctrl(b'm') => { + let idx = self.focus_idx(); + let (focus, entry) = if let Some(idx) = idx { + let entry = self.history.entry(idx).await; + (entry.running(), Some(entry)) + } else { + (true, None) + }; + if focus { + self.set_focus( + idx.map_or(crate::action::Focus::Readline, |idx| { + crate::action::Focus::History(idx) + }), + entry, + ) + .await; + } + } + textmode::Key::Char(' ') => { + if let Some(idx) = self.focus_idx() { + let entry = self.history.entry(idx).await; + self.readline.set_input(&entry.cmd()); + self.set_focus( + crate::action::Focus::Readline, + Some(entry), + ) + .await; + } + } + textmode::Key::Char('e') => { + if let crate::action::Focus::History(idx) = self.focus { + self.history + .handle_key(textmode::Key::Ctrl(b'e'), idx) + .await; + } + } + textmode::Key::Char('f') => { + if let Some(idx) = self.focus_idx() { + let mut entry = self.history.entry(idx).await; + let mut focus = crate::action::Focus::History(idx); + if let crate::action::Focus::Scrolling(_) = self.focus { + entry.set_fullscreen(true); + } else { + entry.toggle_fullscreen(); + if !entry.should_fullscreen() && !entry.running() { + focus = + crate::action::Focus::Scrolling(Some(idx)); + } + } + self.set_focus(focus, Some(entry)).await; + } + } + textmode::Key::Char('j') | textmode::Key::Down => { + self.set_focus( + crate::action::Focus::Scrolling( + self.scroll_down(self.focus_idx()), + ), + None, + ) + .await; + } + textmode::Key::Char('k') | textmode::Key::Up => { + self.set_focus( + crate::action::Focus::Scrolling( + self.scroll_up(self.focus_idx()), + ), + None, + ) + .await; + } + textmode::Key::Char('r') => { + self.set_focus(crate::action::Focus::Readline, None).await; + } + _ => {} + } + Some(crate::action::Action::Render) + } + async fn default_scene( &self, focus: crate::action::Focus, -- cgit v1.2.3-54-g00ecf