Skip to content

Commit 5c10541

Browse files
author
Antonio Scandurra
committed
Refactor and write tests
1 parent d59a460 commit 5c10541

File tree

3 files changed

+81
-34
lines changed

3 files changed

+81
-34
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,10 @@ Once we get the basic collaboration experience down, we'll be looking to expand
183183
* [x] Horizontal scrolling
184184
* [ ] Word- and line-based cursor movements
185185
* [ ] Move To Beginning Of Line
186-
* [ ] Move To Beginning Of Word
186+
* [x] Move To Beginning Of Word
187187
* [ ] Move To Bottom
188188
* [ ] Move To End Of Line
189-
* [ ] Move To End Of Word
189+
* [x] Move To End Of Word
190190
* [ ] Move To Top
191191
* [ ] Select To Beginning Of Line
192192
* [ ] Select To Beginning Of Word

xray_core/src/buffer_view.rs

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use movement;
44
use notify_cell::NotifyCell;
55
use serde_json;
66
use std::cell::{Cell, Ref, RefCell};
7-
use std::char::decode_utf16;
87
use std::cmp::{self, Ordering};
98
use std::ops::Range;
109
use std::rc::Rc;
@@ -547,21 +546,9 @@ impl BufferView {
547546
.borrow_mut()
548547
.mutate_selections(self.selection_set_id, |buffer, selections| {
549548
for selection in selections.iter_mut() {
550-
let mut head = buffer.point_for_anchor(selection.head()).unwrap();
551-
// TODO: remove this once the iterator returns char instances.
552-
let mut char_iter = decode_utf16(buffer.backward_iter_starting_at_point(head))
553-
.map(|c| c.unwrap());
554-
let skip_alphanumeric = char_iter.next().map_or(false, |c| c.is_alphanumeric());
555-
head = movement::left(buffer, head);
556-
for character in char_iter {
557-
if skip_alphanumeric == character.is_alphanumeric() {
558-
head = movement::left(buffer, head);
559-
} else {
560-
break;
561-
}
562-
}
563-
564-
let anchor = buffer.anchor_before_point(head).unwrap();
549+
let old_head = buffer.point_for_anchor(selection.head()).unwrap();
550+
let new_head = movement::beginning_of_word(buffer, old_head);
551+
let anchor = buffer.anchor_before_point(new_head).unwrap();
565552
selection.start = anchor.clone();
566553
selection.end = anchor;
567554
selection.goal_column = None;
@@ -577,21 +564,9 @@ impl BufferView {
577564
.borrow_mut()
578565
.mutate_selections(self.selection_set_id, |buffer, selections| {
579566
for selection in selections.iter_mut() {
580-
let mut head = buffer.point_for_anchor(selection.head()).unwrap();
581-
// TODO: remove this once the iterator returns char instances.
582-
let mut char_iter =
583-
decode_utf16(buffer.iter_starting_at_point(head)).map(|c| c.unwrap());
584-
let skip_alphanumeric = char_iter.next().map_or(false, |c| c.is_alphanumeric());
585-
head = movement::right(buffer, head);
586-
for character in char_iter {
587-
if skip_alphanumeric == character.is_alphanumeric() {
588-
head = movement::right(buffer, head);
589-
} else {
590-
break;
591-
}
592-
}
593-
594-
let anchor = buffer.anchor_before_point(head).unwrap();
567+
let old_head = buffer.point_for_anchor(selection.head()).unwrap();
568+
let new_head = movement::end_of_word(buffer, old_head);
569+
let anchor = buffer.anchor_before_point(new_head).unwrap();
595570
selection.start = anchor.clone();
596571
selection.end = anchor;
597572
selection.goal_column = None;
@@ -1071,6 +1046,47 @@ mod tests {
10711046
assert_eq!(render_selections(&editor), vec![empty_selection(0, 1)]);
10721047
}
10731048

1049+
#[test]
1050+
fn test_move_to_beginning_or_end_of_word() {
1051+
let mut editor = BufferView::new(Rc::new(RefCell::new(Buffer::new(0))), 0, None);
1052+
editor.buffer.borrow_mut().edit(&[0..0], "abc def\nghi.jkl");
1053+
assert_eq!(render_selections(&editor), vec![empty_selection(0, 0)]);
1054+
1055+
editor.move_to_end_of_word();
1056+
assert_eq!(render_selections(&editor), vec![empty_selection(0, 3)]);
1057+
editor.move_to_end_of_word();
1058+
assert_eq!(render_selections(&editor), vec![empty_selection(0, 4)]);
1059+
editor.move_to_end_of_word();
1060+
assert_eq!(render_selections(&editor), vec![empty_selection(0, 7)]);
1061+
editor.move_to_end_of_word();
1062+
assert_eq!(render_selections(&editor), vec![empty_selection(1, 0)]);
1063+
editor.move_to_end_of_word();
1064+
assert_eq!(render_selections(&editor), vec![empty_selection(1, 3)]);
1065+
editor.move_to_end_of_word();
1066+
assert_eq!(render_selections(&editor), vec![empty_selection(1, 4)]);
1067+
editor.move_to_end_of_word();
1068+
assert_eq!(render_selections(&editor), vec![empty_selection(1, 7)]);
1069+
editor.move_to_end_of_word();
1070+
assert_eq!(render_selections(&editor), vec![empty_selection(1, 7)]);
1071+
1072+
editor.move_to_beginning_of_word();
1073+
assert_eq!(render_selections(&editor), vec![empty_selection(1, 4)]);
1074+
editor.move_to_beginning_of_word();
1075+
assert_eq!(render_selections(&editor), vec![empty_selection(1, 3)]);
1076+
editor.move_to_beginning_of_word();
1077+
assert_eq!(render_selections(&editor), vec![empty_selection(1, 0)]);
1078+
editor.move_to_beginning_of_word();
1079+
assert_eq!(render_selections(&editor), vec![empty_selection(0, 7)]);
1080+
editor.move_to_beginning_of_word();
1081+
assert_eq!(render_selections(&editor), vec![empty_selection(0, 4)]);
1082+
editor.move_to_beginning_of_word();
1083+
assert_eq!(render_selections(&editor), vec![empty_selection(0, 3)]);
1084+
editor.move_to_beginning_of_word();
1085+
assert_eq!(render_selections(&editor), vec![empty_selection(0, 0)]);
1086+
editor.move_to_beginning_of_word();
1087+
assert_eq!(render_selections(&editor), vec![empty_selection(0, 0)]);
1088+
}
1089+
10741090
#[test]
10751091
fn test_backspace() {
10761092
let mut editor = BufferView::new(Rc::new(RefCell::new(Buffer::new(0))), 0, None);

xray_core/src/movement.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use std::cmp;
21
use buffer::{Buffer, Point};
2+
use std::char::decode_utf16;
3+
use std::cmp;
34

45
pub fn left(buffer: &Buffer, mut point: Point) -> Point {
56
if point.column > 0 {
@@ -46,3 +47,33 @@ pub fn down(buffer: &Buffer, mut point: Point, goal_column: Option<u32>) -> (Poi
4647

4748
(point, goal_column)
4849
}
50+
51+
pub fn beginning_of_word(buffer: &Buffer, mut point: Point) -> Point {
52+
// TODO: remove this once the iterator returns char instances.
53+
let mut iter = decode_utf16(buffer.backward_iter_starting_at_point(point)).map(|c| c.unwrap());
54+
let skip_alphanumeric = iter.next().map_or(false, |c| c.is_alphanumeric());
55+
point = left(buffer, point);
56+
for character in iter {
57+
if skip_alphanumeric == character.is_alphanumeric() {
58+
point = left(buffer, point);
59+
} else {
60+
break;
61+
}
62+
}
63+
point
64+
}
65+
66+
pub fn end_of_word(buffer: &Buffer, mut point: Point) -> Point {
67+
// TODO: remove this once the iterator returns char instances.
68+
let mut iter = decode_utf16(buffer.iter_starting_at_point(point)).map(|c| c.unwrap());
69+
let skip_alphanumeric = iter.next().map_or(false, |c| c.is_alphanumeric());
70+
point = right(buffer, point);
71+
for character in iter {
72+
if skip_alphanumeric == character.is_alphanumeric() {
73+
point = right(buffer, point);
74+
} else {
75+
break;
76+
}
77+
}
78+
point
79+
}

0 commit comments

Comments
 (0)