From 3b6f7cdbf4e6096e02ca2ec58d9ea8b52fc07b5c Mon Sep 17 00:00:00 2001 From: Joe Bellus Date: Mon, 17 Oct 2022 01:57:56 -0400 Subject: [PATCH] Implemented Change Word Change word forward and backward were implemented in the editor_data and bound in the editor to "cw" and "cb" respectively. Scan word forward and scan word backward now utilize a shared function that gets the scan position. This is now also used for delete word forward/backward, so they can share logic Updated keybinds in README --- abacus-ui/README.org | 3 ++ abacus-ui/src/data/editor_data.rs | 63 +++++++++++++++++++++++-------- abacus-ui/src/editor.rs | 12 ++++++ 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/abacus-ui/README.org b/abacus-ui/README.org index dea358a..e1db715 100644 --- a/abacus-ui/README.org +++ b/abacus-ui/README.org @@ -32,6 +32,9 @@ In normal mode the cursor is a block and functional keybinds can be used for mov | w | Scan forward a word | | v | Mark selection | | x | Delete current character or selection | +| dd | Delete the current line | +| cw | Change word forward | +| cb | Change word backward | ** Insert mode In insert mode the cursor is a line and text can be edited. To return to normal mode use the ESC key. diff --git a/abacus-ui/src/data/editor_data.rs b/abacus-ui/src/data/editor_data.rs index eb69629..24c590a 100644 --- a/abacus-ui/src/data/editor_data.rs +++ b/abacus-ui/src/data/editor_data.rs @@ -104,37 +104,63 @@ impl EditorData { self.deselect(); } - pub fn word_scan_forward(&mut self) { - while self.cursor_pos < self.content.len_chars() { - self.cursor_pos += 1; - if !self - .current_char() - .map(|c| c.is_alphanumeric()) - .unwrap_or(false) + pub fn get_word_scan_forward_position(&mut self, skip_first: bool) -> usize { + if self.cursor_pos < self.content.len_chars() { + for (idx, ch) in self + .content + .chars_at(self.cursor_pos) + .skip(if skip_first { 1 } else { 0 }) + .enumerate() { - break; + if !ch.is_alphanumeric() { + return (idx + self.cursor_pos + 2).min(self.content.len_chars()); + } } - self.deselect(); + self.content.len_chars() + } else { + self.content.len_chars() } } - pub fn word_scan_backward(&mut self) { - if self.cursor_pos > 0 { - self.cursor_pos -= 1; + pub fn get_word_scan_backward_position(&mut self, skip_first: bool) -> usize { + let mut pos = self.cursor_pos; + if pos > 0 && skip_first { + pos -= 1; } - while self.cursor_pos > 0 { + while pos > 0 { if !self .content - .get_char(self.cursor_pos - 1) + .get_char(pos - 1) .map(|c| c.is_alphanumeric()) .unwrap_or(false) { break; } else { - self.cursor_pos -= 1; + pos -= 1; } - self.deselect(); } + pos + } + + pub fn delete_word_forward(&mut self) { + let end = self.get_word_scan_forward_position(false); + self.content.remove(self.cursor_pos..end); + } + + pub fn delete_word_backward(&mut self) { + let start = self.get_word_scan_backward_position(true); + self.content.remove(start..self.cursor_pos); + self.cursor_pos = start; + } + + pub fn word_scan_forward(&mut self) { + self.cursor_pos = self.get_word_scan_forward_position(true); + self.deselect(); + } + + pub fn word_scan_backward(&mut self) { + self.cursor_pos = self.get_word_scan_backward_position(true); + self.deselect(); } pub fn delete_char_forward(&mut self) { @@ -265,6 +291,11 @@ impl EditorData { self.deselect(); } + pub fn insert_mode(&mut self) { + self.mode = EditMode::Insert; + self.deselect(); + } + pub fn select_all(&mut self) { self.selection_pos = Some(0); self.cursor_pos = self.content.len_chars(); diff --git a/abacus-ui/src/editor.rs b/abacus-ui/src/editor.rs index 182c381..2fb6a80 100644 --- a/abacus-ui/src/editor.rs +++ b/abacus-ui/src/editor.rs @@ -36,6 +36,8 @@ mod keymap { pub const WORD_FORWARD: &str = "w"; pub const WORD_BACK: &str = "b"; pub const SELECT_MODE: &str = "v"; + pub const CHANGE_WORD_FORWARD: &str = "cw"; + pub const CHANGE_WORD_BACKWARD: &str = "cb"; #[derive(Debug, Default)] pub struct KeyList { @@ -63,6 +65,8 @@ mod keymap { WORD_FORWARD, WORD_BACK, SELECT_MODE, + CHANGE_WORD_FORWARD, + CHANGE_WORD_BACKWARD, ], } } @@ -360,6 +364,14 @@ impl Widget for AbacusEditor { Some(keymap::SELECT_MODE) => { data.selection_pos = Some(data.cursor_pos); } + Some(keymap::CHANGE_WORD_FORWARD) => { + data.delete_word_forward(); + data.insert_mode(); + } + Some(keymap::CHANGE_WORD_BACKWARD) => { + data.delete_word_backward(); + data.insert_mode(); + } _ => {} } }