}
}
+ fn is_word_sep(c: char) -> bool {
+ c == ' '
+ }
+
fn is_word_boundary(&self, pos: usize) -> bool {
if !self.is_char_boundary(pos) {
false
- } else {
- match self.text[pos..].chars().next() {
- None => true, // end of string
-
- // not just before a space
- Some(c) => c != ' '
+ } else if let Some(prevpos) = self.prev_position(pos) {
+ let mut chars = self.text[prevpos..].chars();
+ let prevchar = chars.next().expect("We're not at end of string");
+ if let Some(thischar) = chars.next() {
+ Self::is_word_sep(prevchar) && !Self::is_word_sep(thischar)
+ } else {
+ true // end of string
}
+ } else {
+ true // start of string
}
}
- fn forward(&mut self) -> bool {
+ fn next_position(&self, pos: usize) -> Option<usize> {
let len = self.text.len();
- if self.point >= len {
- false
+ if pos >= len {
+ None
} else {
- self.point += 1;
- while !self.is_char_boundary(self.point) {
- self.point += 1;
+ let mut pos = pos + 1;
+ while !self.is_char_boundary(pos) {
+ pos += 1;
}
- true
+ Some(pos)
}
}
- fn backward(&mut self) -> bool {
- if self.point == 0 {
- false
+ fn prev_position(&self, pos: usize) -> Option<usize> {
+ if pos == 0 {
+ None
} else {
- self.point -= 1;
- while !self.is_char_boundary(self.point) {
- self.point -= 1;
+ let mut pos = pos - 1;
+ while !self.is_char_boundary(pos) {
+ pos -= 1;
}
- true
+ Some(pos)
+ }
+ }
+
+ fn forward(&mut self) -> bool {
+ match self.next_position(self.point) {
+ Some(pos) => { self.point = pos; true }
+ None => false
+ }
+ }
+
+ fn backward(&mut self) -> bool {
+ match self.prev_position(self.point) {
+ Some(pos) => { self.point = pos; true }
+ None => false
}
}
assert_eq!(ec.backward(), true);
}
+#[test]
+fn test_forward_backward_word() {
+ let mut ec = EditorCore {
+ text: "lorem ipsum dolor sit amet".to_owned(),
+ point: 0,
+ paste_buffer: "".to_owned(),
+ };
+
+ assert_eq!(ec.forward_word(), true);
+ assert_eq!(ec.point, 6); // ipsum
+ assert_eq!(ec.forward_word(), true);
+ assert_eq!(ec.point, 12); // dolor
+ assert_eq!(ec.forward_word(), true);
+ assert_eq!(ec.point, 18); // sit
+ assert_eq!(ec.forward_word(), true);
+ assert_eq!(ec.point, 22); // amet
+ assert_eq!(ec.forward_word(), true);
+ assert_eq!(ec.point, 26); // end of string
+ assert_eq!(ec.forward_word(), false);
+
+ assert_eq!(ec.backward_word(), true);
+ assert_eq!(ec.point, 22); // amet
+ assert_eq!(ec.backward_word(), true);
+ assert_eq!(ec.point, 18); // sit
+ assert_eq!(ec.backward_word(), true);
+ assert_eq!(ec.point, 12); // dolor
+ assert_eq!(ec.backward_word(), true);
+ assert_eq!(ec.point, 6); // ipsum
+ assert_eq!(ec.backward_word(), true);
+ assert_eq!(ec.point, 0); // lorem
+ assert_eq!(ec.backward_word(), false);
+}
+
#[test]
fn test_delete() {
let mut ec = EditorCore {
// buffer text.
let start_cell_index = self.layout
.partition_point(|cell| cell.y < y);
- if dbg!(start_cell_index) == self.layout.len() {
+ if start_cell_index == self.layout.len() {
return None; // y is after the end of the buffer
}
let start_pos = self.layout[start_cell_index].pos;