From b2b69bf7b35f7501c237b7b93a21d26c747cc0d0 Mon Sep 17 00:00:00 2001 From: mars Date: Fri, 14 Apr 2023 20:59:59 -0400 Subject: [PATCH] Remove NormalState + simplify event-handling --- src/actions.rs | 4 +- src/main.rs | 195 +++++++++++++++++++------------------------------ 2 files changed, 78 insertions(+), 121 deletions(-) diff --git a/src/actions.rs b/src/actions.rs index f0bfa31..bc6e2f9 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -19,7 +19,7 @@ use std::collections::HashMap; -use crate::{Cursor, Direction, InsertState, Mode, NormalState, State}; +use crate::{Cursor, Direction, InsertState, Mode, State}; pub type Action = fn(&mut State); @@ -119,7 +119,7 @@ pub fn normal_mode(state: &mut State) { _ => {} } - state.mode = Mode::Normal(NormalState::default()); + state.mode = Mode::Normal; } pub fn visual_mode(state: &mut State) { diff --git a/src/main.rs b/src/main.rs index 0e3a5a0..6b48f45 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,11 +54,6 @@ pub struct Cursor { pub line: usize, } -#[derive(Clone, Debug, Default)] -pub struct NormalState { - pub error: Option, -} - #[derive(Clone, Debug, Default)] pub struct CommandState { pub buf: String, @@ -70,25 +65,20 @@ pub struct InsertState { append: bool, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub enum Mode { - Normal(NormalState), + #[default] + Normal, Command(CommandState), Visual, Insert(InsertState), } -impl Default for Mode { - fn default() -> Self { - Mode::Normal(Default::default()) - } -} - impl Mode { pub fn cursor_style(&self) -> cursor::SetCursorStyle { use cursor::SetCursorStyle as Style; match self { - Mode::Normal(_) => Style::SteadyBlock, + Mode::Normal => Style::SteadyBlock, Mode::Visual => Style::BlinkingBlock, Mode::Insert(_) => Style::BlinkingBar, Mode::Command(_) => Style::SteadyUnderScore, @@ -116,6 +106,7 @@ pub struct State { pub scroll: Cursor, pub size: (usize, usize), pub quit: bool, + pub error: Option, pub theme_tx: Sender, } @@ -139,6 +130,7 @@ impl State { scroll: Cursor::default(), size: (cols as usize, rows as usize), quit: false, + error: None, theme_tx, }) } @@ -154,22 +146,18 @@ impl State { let mut set_cursor_pos = None; let mut show_status_bar = false; - match &self.mode { - Mode::Command(CommandState { buf, cursor }) => { - let col = *cursor as u16 + 1; - let row = rows - 1; - out.queue(cursor::MoveTo(0, row))?; - write!(out, ":{}", buf)?; - set_cursor_pos = Some((col, row)); - show_status_bar = true; - } - Mode::Normal(NormalState { error: Some(error) }) => { - let error_style = styles.get_scope("error"); - out.queue(cursor::MoveTo(0, rows - 1))?; - error_style.print_styled(out, error)?; - show_status_bar = true; - } - _ => {} + if let Mode::Command(CommandState { buf, cursor }) = &self.mode { + let col = *cursor as u16 + 1; + let row = rows - 1; + out.queue(cursor::MoveTo(0, row))?; + write!(out, ":{}", buf)?; + set_cursor_pos = Some((col, row)); + show_status_bar = true; + } else if let Some(error) = self.error.as_ref() { + let error_style = styles.get_scope("error"); + out.queue(cursor::MoveTo(0, rows - 1))?; + error_style.print_styled(out, error)?; + show_status_bar = true; } // done with styles @@ -207,105 +195,82 @@ impl State { Ok(()) } - /// Sets the state to `Mode::Normal` with an error message. + /// Sets the current error message. pub fn set_error(&mut self, error: impl ToString) { - self.mode = Mode::Normal(NormalState { - error: Some(error.to_string()), - }); + self.error = Some(error.to_string()); } pub fn on_event(&mut self, event: Event) { - match &self.mode { - Mode::Normal(state) => self.on_normal_event(event, state.clone()), - Mode::Command(state) => self.on_command_event(event, state.clone()), - Mode::Visual => self.on_visual_event(event), - Mode::Insert(state) => self.on_insert_event(event, state.clone()), - } - } - - fn on_normal_event(&mut self, event: Event, mut state: NormalState) { // reset the error from the last event - state.error = None; - self.mode = Mode::Normal(state); + self.error = None; match event { - Event::Key(KeyEvent { code, .. }) => { - self.on_key(code); + Event::Resize(cols, rows) => { + self.size = (cols as usize, rows as usize); } - event => self.on_any_event(event), - } - } - - fn on_command_event(&mut self, event: Event, mut state: CommandState) { - match event { - Event::Key(KeyEvent { code, .. }) => match code { - KeyCode::Char(c) => { - state.buf.insert(state.cursor, c); - state.cursor += 1; + Event::Key(KeyEvent { code, .. }) => match &self.mode { + Mode::Normal | Mode::Visual => { + self.on_key(code); } - KeyCode::Backspace => { - if state.cursor > 0 { - state.cursor -= 1; - state.buf.remove(state.cursor); + Mode::Command(state) => self.on_command_key(code, state.clone()), + Mode::Insert(_) => { + if !self.on_key(code) { + if let KeyCode::Char(c) = code { + self.buffer.insert_char(self.cursor, c); + self.move_cursor(Direction::Right); + } } } - KeyCode::Delete if state.cursor < state.buf.len() => { + }, + _ => {} + } + } + + fn on_command_key(&mut self, code: KeyCode, mut state: CommandState) { + match code { + KeyCode::Char(c) => { + state.buf.insert(state.cursor, c); + state.cursor += 1; + } + KeyCode::Backspace => { + if state.cursor > 0 { + state.cursor -= 1; state.buf.remove(state.cursor); } - KeyCode::Left if state.cursor > 0 => { - state.cursor -= 1; - } - KeyCode::Right if state.cursor < state.buf.len() => { - state.cursor += 1; - } - KeyCode::Enter => { - // TODO add to command history - let result = self.execute_command(&state.buf); - let error = result.err(); - self.mode = Mode::Normal(NormalState { error }); - return; - } - KeyCode::Esc => { - self.mode = Mode::default(); - return; - } - _ => {} - }, - event => return self.on_any_event(event), + } + KeyCode::Delete if state.cursor < state.buf.len() => { + state.buf.remove(state.cursor); + } + KeyCode::Left if state.cursor > 0 => { + state.cursor -= 1; + } + KeyCode::Right if state.cursor < state.buf.len() => { + state.cursor += 1; + } + KeyCode::Enter => { + // TODO add to command history + let _ = self + .execute_command(&state.buf) + .map_err(|err| self.set_error(err)); + self.mode = Mode::Normal; + return; + } + KeyCode::Esc => { + self.mode = Mode::default(); + return; + } + _ => {} } self.mode = Mode::Command(state); } - fn on_visual_event(&mut self, event: Event) { - match event { - Event::Key(KeyEvent { code, .. }) => { - self.on_key(code); - } - event => self.on_any_event(event), - } - } - - fn on_insert_event(&mut self, event: Event, _state: InsertState) { - match event { - Event::Key(KeyEvent { code, .. }) => { - if !self.on_key(code) { - if let KeyCode::Char(c) = code { - self.buffer.insert_char(self.cursor, c); - self.move_cursor(Direction::Right); - } - } - } - event => self.on_any_event(event), - } - } - /// Processes a key press event. /// /// Returns `true` if the key was handled by a keybind, `false` otherwise. fn on_key(&mut self, key: Key) -> bool { let keybinds = match &self.mode { - Mode::Normal(_) => &self.config.keybinds.normal, + Mode::Normal => &self.config.keybinds.normal, Mode::Insert(_) => &self.config.keybinds.insert, Mode::Visual => &self.config.keybinds.visual, Mode::Command(_) => return false, // command mode is handled in [on_command_event] @@ -335,15 +300,6 @@ impl State { true } - fn on_any_event(&mut self, event: Event) { - match event { - Event::Resize(cols, rows) => { - self.size = (cols as usize, rows as usize); - } - _ => {} - } - } - fn write_buffer(&mut self, file: OsString) -> Result<()> { self.last_saved = self.buffer.as_ref().clone(); let out = self.buffer.as_ref().bytes().collect::>(); @@ -365,7 +321,7 @@ impl State { let file = OsString::from(part); self.file = Some(file.clone()); file - }, + } None => { return Err(format!("{}: No file name.", command)); } @@ -379,9 +335,10 @@ impl State { match keybind { Keybind::Action(action) => action(self), Keybind::Command(command) => { - let result = self.execute_command(&command); - let error = result.err(); - self.mode = Mode::Normal(NormalState { error }); + let _ = self + .execute_command(&command) + .map_err(|err| self.set_error(err)); + self.mode = Mode::Normal; return; } }