From 40a943a422623f0533fbac40285164709b86b5a0 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Mon, 13 Dec 2021 02:53:20 -0500 Subject: more rearranging --- src/state.rs | 436 ----------------------------------------------------------- 1 file changed, 436 deletions(-) delete mode 100644 src/state.rs (limited to 'src/state.rs') diff --git a/src/state.rs b/src/state.rs deleted file mode 100644 index cdc3cdb..0000000 --- a/src/state.rs +++ /dev/null @@ -1,436 +0,0 @@ -#[derive(Copy, Clone, Debug)] -enum Focus { - Readline, - History(usize), - Scrolling(Option), -} - -#[derive(Copy, Clone, Debug)] -enum Scene { - Readline, - Fullscreen, -} - -pub enum Action { - Refresh, - HardRefresh, - Resize(u16, u16), - Quit, -} - -pub struct State { - readline: crate::readline::Readline, - history: crate::history::History, - focus: Focus, - scene: Scene, - escape: bool, - hide_readline: bool, - offset: time::UtcOffset, -} - -impl State { - pub fn new(offset: time::UtcOffset) -> Self { - Self { - readline: crate::readline::Readline::new(), - history: crate::history::History::new(), - focus: Focus::Readline, - scene: Scene::Readline, - escape: false, - hide_readline: false, - offset, - } - } - - pub async fn render( - &self, - out: &mut impl textmode::Textmode, - ) -> anyhow::Result<()> { - out.clear(); - match self.scene { - Scene::Readline => match self.focus { - Focus::Readline => { - self.history - .render( - out, - self.readline.lines(), - None, - false, - self.offset, - ) - .await?; - self.readline - .render( - out, - self.history.entry_count(), - true, - self.offset, - ) - .await?; - } - Focus::History(idx) => { - if self.hide_readline { - self.history - .render(out, 0, Some(idx), false, self.offset) - .await?; - } else { - self.history - .render( - out, - self.readline.lines(), - Some(idx), - false, - self.offset, - ) - .await?; - let pos = out.screen().cursor_position(); - self.readline - .render( - out, - self.history.entry_count(), - false, - self.offset, - ) - .await?; - out.move_to(pos.0, pos.1); - } - } - Focus::Scrolling(idx) => { - self.history - .render( - out, - self.readline.lines(), - idx, - true, - self.offset, - ) - .await?; - self.readline - .render( - out, - self.history.entry_count(), - idx.is_none(), - self.offset, - ) - .await?; - out.hide_cursor(true); - } - }, - Scene::Fullscreen => { - if let Focus::History(idx) = self.focus { - self.history.render_fullscreen(out, idx).await; - } else { - unreachable!(); - } - } - } - Ok(()) - } - - pub async fn handle_event( - &mut self, - event: crate::event::Event, - event_w: &async_std::channel::Sender, - ) -> Option { - match event { - crate::event::Event::Key(key) => { - return 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 { - Focus::Readline => { - self.handle_key_readline(key, event_w.clone()) - .await - } - Focus::History(idx) => { - self.handle_key_history(key, idx).await; - None - } - Focus::Scrolling(_) => { - self.handle_key_escape(key).await - } - } - }; - } - crate::event::Event::Resize(new_size) => { - self.readline.resize(new_size).await; - self.history.resize(new_size).await; - return Some(Action::Resize(new_size.0, new_size.1)); - } - crate::event::Event::ProcessOutput => { - // the number of visible lines may have changed, so make sure - // the focus is still visible - self.history - .make_focus_visible( - self.readline.lines(), - self.focus_idx(), - matches!(self.focus, Focus::Scrolling(_)), - ) - .await; - } - crate::event::Event::ProcessAlternateScreen => { - self.scene = self.default_scene(self.focus, None).await; - } - crate::event::Event::ProcessExit => { - if let Some(idx) = self.focus_idx() { - let entry = self.history.entry(idx).await; - if !entry.running() { - self.set_focus( - if self.hide_readline { - Focus::Readline - } else { - Focus::Scrolling(Some(idx)) - }, - Some(entry), - ) - .await; - } - } - } - crate::event::Event::ClockTimer => {} - }; - Some(Action::Refresh) - } - - async fn handle_key_escape( - &mut self, - key: textmode::Key, - ) -> Option { - match key { - textmode::Key::Ctrl(b'd') => { - return Some(Action::Quit); - } - textmode::Key::Ctrl(b'e') => { - self.set_focus(Focus::Scrolling(self.focus_idx()), None) - .await; - } - textmode::Key::Ctrl(b'l') => { - return Some(Action::HardRefresh); - } - 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(Focus::Readline, |idx| { - 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(Focus::Readline, Some(entry)).await; - } - } - textmode::Key::Char('e') => { - if let Focus::History(idx) = self.focus { - self.handle_key_history(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 = Focus::History(idx); - if let Focus::Scrolling(_) = self.focus { - entry.set_fullscreen(true); - } else { - entry.toggle_fullscreen(); - if !entry.should_fullscreen() && !entry.running() { - focus = Focus::Scrolling(Some(idx)); - } - } - self.set_focus(focus, Some(entry)).await; - } - } - textmode::Key::Char('j') | textmode::Key::Down => { - self.set_focus( - Focus::Scrolling(self.scroll_down(self.focus_idx())), - None, - ) - .await; - } - textmode::Key::Char('k') | textmode::Key::Up => { - self.set_focus( - Focus::Scrolling(self.scroll_up(self.focus_idx())), - None, - ) - .await; - } - textmode::Key::Char('n') => { - self.set_focus(self.next_running().await, None).await; - } - textmode::Key::Char('p') => { - self.set_focus(self.prev_running().await, None).await; - } - textmode::Key::Char('r') => { - self.set_focus(Focus::Readline, None).await; - } - _ => { - return None; - } - } - Some(Action::Refresh) - } - - async fn handle_key_readline( - &mut self, - key: textmode::Key, - event_w: async_std::channel::Sender, - ) -> Option { - match key { - textmode::Key::Char(c) => { - self.readline.add_input(&c.to_string()); - } - textmode::Key::Ctrl(b'c') => self.readline.clear_input(), - textmode::Key::Ctrl(b'd') => { - return Some(Action::Quit); - } - textmode::Key::Ctrl(b'l') => { - return Some(Action::HardRefresh); - } - textmode::Key::Ctrl(b'm') => { - let cmd = self.readline.input(); - self.readline.clear_input(); - let idx = - self.history.run(&cmd, event_w.clone()).await.unwrap(); - self.set_focus(Focus::History(idx), None).await; - self.hide_readline = true; - } - textmode::Key::Ctrl(b'u') => self.readline.clear_backwards(), - textmode::Key::Backspace => self.readline.backspace(), - textmode::Key::Left => self.readline.cursor_left(), - textmode::Key::Right => self.readline.cursor_right(), - textmode::Key::Up => { - let entry_count = self.history.entry_count(); - if entry_count > 0 { - self.set_focus( - Focus::Scrolling(Some(entry_count - 1)), - None, - ) - .await; - } - } - _ => return None, - } - Some(Action::Refresh) - } - - async fn handle_key_history(&mut self, key: textmode::Key, idx: usize) { - self.history - .entry(idx) - .await - .send_input(key.into_bytes()) - .await; - } - - async fn default_scene( - &self, - focus: Focus, - entry: Option>, - ) -> Scene { - match focus { - Focus::Readline | Focus::Scrolling(_) => Scene::Readline, - Focus::History(idx) => { - let fullscreen = if let Some(entry) = entry { - entry.should_fullscreen() - } else { - self.history.entry(idx).await.should_fullscreen() - }; - if fullscreen { - Scene::Fullscreen - } else { - Scene::Readline - } - } - } - } - - async fn set_focus( - &mut self, - new_focus: Focus, - entry: Option>, - ) { - self.focus = new_focus; - self.hide_readline = false; - self.scene = self.default_scene(new_focus, entry).await; - // passing entry into default_scene above consumes it, which means - // that the mutex lock will be dropped before we call into - // make_focus_visible, which is important because otherwise we might - // get a deadlock depending on what is visible - self.history - .make_focus_visible( - self.readline.lines(), - self.focus_idx(), - matches!(self.focus, Focus::Scrolling(_)), - ) - .await; - } - - fn focus_idx(&self) -> Option { - match self.focus { - Focus::History(idx) => Some(idx), - Focus::Readline => None, - Focus::Scrolling(idx) => idx, - } - } - - fn scroll_up(&self, idx: Option) -> Option { - idx.map_or_else( - || { - let count = self.history.entry_count(); - if count == 0 { - None - } else { - Some(count - 1) - } - }, - |idx| Some(idx.saturating_sub(1)), - ) - } - - fn scroll_down(&self, idx: Option) -> Option { - idx.and_then(|idx| { - if idx >= self.history.entry_count() - 1 { - None - } else { - Some(idx + 1) - } - }) - } - - async fn next_running(&self) -> Focus { - let count = self.history.entry_count(); - let cur = self.focus_idx().unwrap_or(count); - for idx in ((cur + 1)..count).chain(0..cur) { - if self.history.entry(idx).await.running() { - return Focus::History(idx); - } - } - self.focus_idx().map_or(Focus::Readline, Focus::History) - } - - async fn prev_running(&self) -> Focus { - let count = self.history.entry_count(); - let cur = self.focus_idx().unwrap_or(count); - for idx in ((cur + 1)..count).chain(0..cur).rev() { - if self.history.entry(idx).await.running() { - return Focus::History(idx); - } - } - self.focus_idx().map_or(Focus::Readline, Focus::History) - } -} -- cgit v1.2.3-54-g00ecf