diff --git a/src/input.rs b/src/input.rs index b8cd089..78f798b 100644 --- a/src/input.rs +++ b/src/input.rs @@ -9,14 +9,26 @@ use unicode_width::{UnicodeWidthChar, UnicodeWidthStr}; // TODO: add punctuation. const SEPARATORS: [char; 3] = [' ', '\t', '\n']; +#[derive(Debug, PartialEq)] +pub enum InputMode { + /// Insert mode. For inserting new text. + Insert, + + /// Normal mode. For navigation and manipulation of text. Use Escape to come back to Normal + /// mode from any other mode. + Normal, +} + #[derive(Debug)] pub enum InputEvent { None, Exit, Text(String), + Mode(InputMode), } pub struct Input { + mode: InputMode, stdout: W, string: Vec, clipboard: Vec, @@ -27,6 +39,7 @@ pub struct Input { impl Input { pub fn new(stdout: W) -> Input { Input { + mode: InputMode::Insert, stdout, string: Vec::new(), clipboard: Vec::new(), @@ -35,10 +48,15 @@ impl Input { } } + pub fn with_mode(&mut self, mode: InputMode) { + self.mode = mode + } + #[cfg(test)] fn from(stdout: W, input: &str) -> Input { let string: Vec = input.chars().collect(); Input { + mode: InputMode::Insert, stdout, cursor: string.len(), string, @@ -73,8 +91,19 @@ impl Input { } pub fn handle_key(&mut self, code: KeyCode, modifiers: KeyModifiers) -> Result { + // Escape always changes input mode back to Normal. + if let KeyCode::Esc = code { + return Ok(InputEvent::Mode(InputMode::Normal)); + } + + match self.mode { + InputMode::Insert => self.handle_key_mode_input(code, modifiers), + _ => Ok(InputEvent::None) + } + } + + pub fn handle_key_mode_input(&mut self, code: KeyCode, modifiers: KeyModifiers) -> Result { match (code, modifiers) { - (KeyCode::Esc, _) => return Ok(InputEvent::Exit), (KeyCode::Char('d'), KeyModifiers::CONTROL) => return Ok(InputEvent::Exit), (KeyCode::Char('l'), KeyModifiers::CONTROL) => { self.stdout @@ -325,4 +354,16 @@ mod test { } Ok(()) } + + #[test] + fn mode_change_normal() -> Result<()> { + let mut stdout = Vec::new(); + let mut input = Input::new(&mut stdout); + let event = input.handle_key(KeyCode::Esc, KeyModifiers::NONE)?; + match event { + InputEvent::Mode(mode) => assert_eq!(mode, InputMode::Normal), + evt => panic!("Wrong event: {evt:?}"), + } + Ok(()) + } } diff --git a/src/main.rs b/src/main.rs index dba1a20..bced54b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -149,6 +149,7 @@ impl<'a> ChatTab<'a> { Event::Key(event) => { match self.input.handle_key(event.code, event.modifiers) { Ok(InputEvent::Exit) => break, + Ok(InputEvent::Mode(mode)) => self.input.with_mode(mode), Ok(InputEvent::Text(message)) => { /* let item = logger::Item::Message(logger::LogMessage {