Implement <Alt-f> to move forwards in inputs

Until the next occurence of a nonalphanumeric char.
pull/154/head
sebashwa 2 years ago
parent f108b28d5f
commit 195dc95a1b

@ -1,6 +1,7 @@
use super::{is_nonalphanumeric, is_whitespace}; use super::{is_nonalphanumeric, is_whitespace};
use crate::components::compute_character_width; use crate::components::compute_character_width;
use crate::event::Key; use crate::event::Key;
use std::ops::Range;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
pub struct Input { pub struct Input {
@ -26,6 +27,10 @@ impl Input {
self.value_str().width() as u16 self.value_str().width() as u16
} }
fn width_for(&self, chars: &[char]) -> u16 {
chars.iter().collect::<String>().width() as u16
}
pub fn reset(&mut self) { pub fn reset(&mut self) {
self.value = Vec::new(); self.value = Vec::new();
self.cursor_index = 0; self.cursor_index = 0;
@ -40,12 +45,16 @@ impl Input {
self.cursor_index == self.value.len() self.cursor_index == self.value.len()
} }
fn cursor_index_backwards_until(&self, char_fun: &dyn Fn(char) -> bool) -> usize { fn find_index_for_char_of_kind(
let mut result = 0; &self,
range: Range<usize>,
is_char_of_kind: &dyn Fn(char) -> bool,
) -> Option<usize> {
let mut result = None;
for i in (0..self.cursor_index - 1).rev() { for i in range {
if char_fun(self.value[i]) { if is_char_of_kind(self.value[i]) {
result = i + 1; result = Some(i);
break; break;
} }
} }
@ -53,6 +62,24 @@ impl Input {
return result; 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) { fn delete_left_until(&mut self, new_cursor_index: usize) {
let mut tail = self.value.to_vec().drain(self.cursor_index..).collect(); let mut tail = self.value.to_vec().drain(self.cursor_index..).collect();
@ -100,6 +127,16 @@ impl Input {
self.cursor_position = self.value_width(); self.cursor_position = self.value_width();
return (Some(key), true); 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') => { Key::Left | Key::Ctrl('b') => {
if self.cannot_go_left() { if self.cannot_go_left() {
return (Some(key), false); return (Some(key), false);
@ -127,10 +164,7 @@ impl Input {
let new_cursor_index = self.cursor_index_backwards_until(&is_nonalphanumeric); let new_cursor_index = self.cursor_index_backwards_until(&is_nonalphanumeric);
self.cursor_index = new_cursor_index; self.cursor_index = new_cursor_index;
self.cursor_position = self.value[0..self.cursor_index] self.cursor_position = self.width_for(&self.value[0..new_cursor_index]);
.iter()
.collect::<String>()
.width() as u16;
return (Some(key), true); return (Some(key), true);
} }
Key::Ctrl('w') => { Key::Ctrl('w') => {
@ -283,7 +317,7 @@ mod test {
} }
#[test] #[test]
fn test_goes_til_nonalphanumeric_for_alt_b() { fn test_moves_backwards_til_nonalphanumeric_for_alt_b() {
let mut input = Input::new(); let mut input = Input::new();
input.value = vec!['a', '-', 'c', 'd']; input.value = vec!['a', '-', 'c', 'd'];
input.cursor_index = 3; input.cursor_index = 3;
@ -296,4 +330,19 @@ mod test {
assert_eq!(input.value, vec!['a', '-', 'c', 'd']); assert_eq!(input.value, vec!['a', '-', 'c', 'd']);
assert_eq!(input.cursor_index, 2); 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);
}
} }

Loading…
Cancel
Save