From 195dc95a1bdacfd76b4a03483b315c5d3ef703d6 Mon Sep 17 00:00:00 2001 From: sebashwa Date: Mon, 23 May 2022 11:01:14 +0200 Subject: [PATCH] Implement to move forwards in inputs Until the next occurence of a nonalphanumeric char. --- src/components/utils/input.rs | 69 ++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/src/components/utils/input.rs b/src/components/utils/input.rs index feb1d54..03db061 100644 --- a/src/components/utils/input.rs +++ b/src/components/utils/input.rs @@ -1,6 +1,7 @@ use super::{is_nonalphanumeric, is_whitespace}; use crate::components::compute_character_width; use crate::event::Key; +use std::ops::Range; use unicode_width::UnicodeWidthStr; pub struct Input { @@ -26,6 +27,10 @@ impl Input { self.value_str().width() as u16 } + fn width_for(&self, chars: &[char]) -> u16 { + chars.iter().collect::().width() as u16 + } + pub fn reset(&mut self) { self.value = Vec::new(); self.cursor_index = 0; @@ -40,12 +45,16 @@ impl Input { self.cursor_index == self.value.len() } - fn cursor_index_backwards_until(&self, char_fun: &dyn Fn(char) -> bool) -> usize { - let mut result = 0; + fn find_index_for_char_of_kind( + &self, + range: Range, + is_char_of_kind: &dyn Fn(char) -> bool, + ) -> Option { + let mut result = None; - for i in (0..self.cursor_index - 1).rev() { - if char_fun(self.value[i]) { - result = i + 1; + for i in range { + if is_char_of_kind(self.value[i]) { + result = Some(i); break; } } @@ -53,6 +62,24 @@ impl Input { return result; } + fn cursor_index_backwards_until(&self, is_char_of_kind: &dyn Fn(char) -> bool) -> usize { + let range = 0..self.cursor_index - 1; + + match self.find_index_for_char_of_kind(range, is_char_of_kind) { + Some(index) => index + 1, + None => 0, + } + } + + fn cursor_index_forwards_until(&self, is_char_of_kind: &dyn Fn(char) -> bool) -> usize { + let range = self.cursor_index + 1..self.value.len(); + + match self.find_index_for_char_of_kind(range, is_char_of_kind) { + Some(index) => index, + None => self.value.len(), + } + } + fn delete_left_until(&mut self, new_cursor_index: usize) { let mut tail = self.value.to_vec().drain(self.cursor_index..).collect(); @@ -100,6 +127,16 @@ impl Input { self.cursor_position = self.value_width(); return (Some(key), true); } + Key::Alt('f') => { + if self.cannot_go_right() { + return (Some(key), false); + } + + let new_cursor_index = self.cursor_index_forwards_until(&is_nonalphanumeric); + self.cursor_index = new_cursor_index; + self.cursor_position = self.width_for(&self.value[0..new_cursor_index]); + return (Some(key), true); + } Key::Left | Key::Ctrl('b') => { if self.cannot_go_left() { return (Some(key), false); @@ -127,10 +164,7 @@ impl Input { let new_cursor_index = self.cursor_index_backwards_until(&is_nonalphanumeric); self.cursor_index = new_cursor_index; - self.cursor_position = self.value[0..self.cursor_index] - .iter() - .collect::() - .width() as u16; + self.cursor_position = self.width_for(&self.value[0..new_cursor_index]); return (Some(key), true); } Key::Ctrl('w') => { @@ -283,7 +317,7 @@ mod test { } #[test] - fn test_goes_til_nonalphanumeric_for_alt_b() { + fn test_moves_backwards_til_nonalphanumeric_for_alt_b() { let mut input = Input::new(); input.value = vec!['a', '-', 'c', 'd']; input.cursor_index = 3; @@ -296,4 +330,19 @@ mod test { assert_eq!(input.value, vec!['a', '-', 'c', 'd']); assert_eq!(input.cursor_index, 2); } + + #[test] + fn test_moves_forwards_til_nonalphanumeric_for_alt_f() { + let mut input = Input::new(); + input.value = vec!['a', 'b', '-', 'c']; + input.cursor_index = 1; + input.cursor_position = input.value_width(); + + let (matched_key, input_changed) = input.handle_key(Key::Alt('f')); + + assert_eq!(matched_key, Some(Key::Alt('f'))); + assert_eq!(input_changed, true); + assert_eq!(input.value, vec!['a', 'b', '-', 'c']); + assert_eq!(input.cursor_index, 2); + } }