From 9ebe2361a98fca58ca2e363419733b8ee790c49b Mon Sep 17 00:00:00 2001 From: Joscha Date: Sun, 7 Aug 2022 00:25:53 +0200 Subject: [PATCH] Move cursor one word left/right --- src/ui/util.rs | 4 ++++ src/ui/widgets/editor.rs | 44 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/ui/util.rs b/src/ui/util.rs index 67e258f..402372f 100644 --- a/src/ui/util.rs +++ b/src/ui/util.rs @@ -54,6 +54,8 @@ pub fn list_editor_key_bindings( // Cursor movement bindings.binding("ctrl+b, ←", "move cursor left"); bindings.binding("ctrl+f, →", "move cursor right"); + bindings.binding("alt+b, ctrl+←", "move cursor left a word"); + bindings.binding("alt+f, ctrl+→", "move cursor right a word"); bindings.binding("ctrl+a, home", "move cursor to start of line"); bindings.binding("ctrl+e, end", "move cursor to end of line"); bindings.binding("↑/↓", "move cursor up/down"); @@ -86,6 +88,8 @@ pub fn handle_editor_key_event( // Cursor movement key!(Ctrl + 'b') | key!(Left) => editor.move_cursor_left(terminal.frame()), key!(Ctrl + 'f') | key!(Right) => editor.move_cursor_right(terminal.frame()), + key!(Alt + 'b') | key!(Ctrl + Left) => editor.move_cursor_left_a_word(terminal.frame()), + key!(Alt + 'f') | key!(Ctrl + Right) => editor.move_cursor_right_a_word(terminal.frame()), key!(Ctrl + 'a') | key!(Home) => editor.move_cursor_to_start_of_line(terminal.frame()), key!(Ctrl + 'e') | key!(End) => editor.move_cursor_to_end_of_line(terminal.frame()), key!(Up) => editor.move_cursor_up(terminal.frame()), diff --git a/src/ui/widgets/editor.rs b/src/ui/widgets/editor.rs index 20f4a38..cae62ca 100644 --- a/src/ui/widgets/editor.rs +++ b/src/ui/widgets/editor.rs @@ -237,6 +237,42 @@ impl InnerEditorState { } } + fn move_cursor_left_a_word(&mut self, frame: &mut Frame) { + let boundaries = self.grapheme_boundaries(); + let mut encountered_word = false; + for (start, end) in boundaries.iter().zip(boundaries.iter().skip(1)).rev() { + if *end == self.idx { + let g = &self.text[*start..*end]; + let whitespace = g.chars().all(|c| c.is_whitespace()); + if encountered_word && whitespace { + break; + } else if !whitespace { + encountered_word = true; + } + self.idx = *start; + } + } + self.record_cursor_col(frame); + } + + fn move_cursor_right_a_word(&mut self, frame: &mut Frame) { + let boundaries = self.grapheme_boundaries(); + let mut encountered_word = false; + for (start, end) in boundaries.iter().zip(boundaries.iter().skip(1)) { + if *start == self.idx { + let g = &self.text[*start..*end]; + let whitespace = g.chars().all(|c| c.is_whitespace()); + if encountered_word && whitespace { + break; + } else if !whitespace { + encountered_word = true; + } + self.idx = *end; + } + } + self.record_cursor_col(frame); + } + fn move_cursor_to_start_of_line(&mut self, frame: &mut Frame) { let boundaries = self.line_boundaries(); let (line, _, _) = self.cursor_line(&boundaries); @@ -329,6 +365,14 @@ impl EditorState { self.0.lock().move_cursor_right(frame); } + pub fn move_cursor_left_a_word(&self, frame: &mut Frame) { + self.0.lock().move_cursor_left_a_word(frame); + } + + pub fn move_cursor_right_a_word(&self, frame: &mut Frame) { + self.0.lock().move_cursor_right_a_word(frame); + } + pub fn move_cursor_to_start_of_line(&self, frame: &mut Frame) { self.0.lock().move_cursor_to_start_of_line(frame); }