Verified Commit 80274931 authored by Phil Booth's avatar Phil Booth

feat(cursor): implement word-end movement

parent 234f6726
Pipeline #32703652 passed with stage
in 2 minutes and 5 seconds
......@@ -18,7 +18,7 @@
#[cfg(test)]
mod test;
use tokens::{arena, TokenId};
use tokens::{arena, Token, TokenId};
#[derive(Debug, Default)]
pub struct Cursor {
......@@ -185,11 +185,7 @@ impl Cursor {
if delta >= 0 {
word.following_siblings()
} else {
let grapheme_id = self.grapheme_id.unwrap();
let at_word_start = arena().read(grapheme_id, &|grapheme| {
grapheme_id == word.first_child().unwrap()
});
if at_word_start {
if self.grapheme_id.unwrap() == word.first_child().unwrap() {
word.preceding_siblings()
} else {
word.iter(None, None)
......@@ -198,16 +194,25 @@ impl Cursor {
});
if delta >= 0 {
self.line_index += self.move_word_absolute(delta as usize, word_ids);
self.line_index +=
self.move_word_absolute(delta as usize, word_ids, &|word| word.first_child());
} else {
self.line_index -= self.move_word_absolute((0 - delta) as usize, word_ids.rev());
self.line_index -=
self.move_word_absolute((0 - delta) as usize, word_ids.rev(), &|word| {
word.first_child()
});
}
self.ideal_grapheme_index = self.grapheme_index;
}
}
fn move_word_absolute<I>(&mut self, absolute_delta: usize, word_ids: I) -> usize
fn move_word_absolute<I>(
&mut self,
absolute_delta: usize,
word_ids: I,
position: &Fn(&Token) -> Option<TokenId>,
) -> usize
where
I: Iterator<Item = TokenId>,
{
......@@ -234,36 +239,69 @@ impl Cursor {
if let Some(new_word_id) = new_word_id {
let (grapheme_id, line_id) =
arena().read(new_word_id, &|word| (word.first_child(), word.parent()));
self.grapheme_id = grapheme_id;
arena().read(new_word_id, &|word| (position(&word), word.parent()));
self.move_to_grapheme_on_line(grapheme_id, line_id);
}
line_count
}
fn move_to_grapheme_on_line(&mut self, grapheme_id: Option<TokenId>, line_id: Option<TokenId>) {
self.grapheme_id = grapheme_id;
self.grapheme_index = 0;
if let Some(grapheme_id) = grapheme_id {
if let Some(line_id) = line_id {
let first_word_id = arena().read(line_id, &|line| line.first_child().unwrap());
let first_grapheme_id =
arena().read(first_word_id, &|word| word.first_child().unwrap());
if let Some(grapheme_id) = self.grapheme_id {
if let Some(line_id) = line_id {
let first_word_id = arena().read(line_id, &|line| line.first_child().unwrap());
let first_grapheme_id =
arena().read(first_word_id, &|word| word.first_child().unwrap());
if grapheme_id != first_grapheme_id {
let second_grapheme_id =
arena().read(first_grapheme_id, &|grapheme| grapheme.next().unwrap());
if grapheme_id == first_grapheme_id {
self.grapheme_index = 0;
if grapheme_id == second_grapheme_id {
self.grapheme_index = 1;
} else {
let second_grapheme_id =
arena().read(first_grapheme_id, &|grapheme| grapheme.next().unwrap());
if grapheme_id == second_grapheme_id {
self.grapheme_index = 1;
} else {
let grapheme_ids = arena().read(second_grapheme_id, &|grapheme| {
grapheme.iter(None, Some(grapheme_id))
});
let line_length = arena().read(line_id, &|line| line.len());
self.grapheme_index =
self.move_grapheme_absolute(line_length, grapheme_ids);
}
let grapheme_ids = arena().read(second_grapheme_id, &|grapheme| {
grapheme.iter(None, Some(grapheme_id))
});
let line_length = arena().read(line_id, &|line| line.len());
self.grapheme_index =
self.move_grapheme_absolute(line_length, grapheme_ids);
}
}
}
}
}
line_count
pub fn move_to_word_end(&mut self, delta: isize) {
self.stick_to_line_end = false;
if let Some(word_id) = self.word_id() {
let word_ids = arena().read(word_id, &|word| {
if delta >= 0 {
if self.grapheme_id.unwrap() == word.last_child().unwrap() {
word.following_siblings()
} else {
word.iter(None, None)
}
} else {
word.preceding_siblings()
}
});
if delta >= 0 {
self.line_index +=
self.move_word_absolute(delta as usize, word_ids, &|word| word.last_child());
} else {
self.line_index -=
self.move_word_absolute((0 - delta) as usize, word_ids.rev(), &|word| {
word.last_child()
});
}
self.ideal_grapheme_index = self.grapheme_index;
}
}
}
......@@ -229,24 +229,24 @@ fn move_to_line_end() {
let mut cursor = Cursor::new(grapheme_id, 0, 0);
cursor.move_to_line_end();
assert_eq!(cursor.line_index(), 0);
assert_eq!(cursor.grapheme_index(), 1);
assert_eq!(cursor.line_index(), 0);
cursor.move_line(1);
assert_eq!(cursor.line_index(), 1);
assert_eq!(cursor.grapheme_index(), 2);
assert_eq!(cursor.line_index(), 1);
cursor.move_line(1);
assert_eq!(cursor.line_index(), 2);
assert_eq!(cursor.grapheme_index(), 3);
assert_eq!(cursor.line_index(), 2);
cursor.move_line(-1);
assert_eq!(cursor.line_index(), 1);
assert_eq!(cursor.grapheme_index(), 2);
assert_eq!(cursor.line_index(), 1);
cursor.move_line(1);
assert_eq!(cursor.line_index(), 2);
assert_eq!(cursor.grapheme_index(), 3);
assert_eq!(cursor.line_index(), 2);
}
#[test]
......@@ -320,3 +320,67 @@ fn move_word() {
assert_eq!(cursor.grapheme_index(), 2);
assert_eq!(cursor.line_index(), 0);
}
#[test]
fn move_to_word_end() {
let line_ids = parse::lines("00 111 2222\n33333").unwrap();
let word_id = arena().read(line_ids[0], &|line| line.first_child().unwrap());
let grapheme_id = arena().read(word_id, &|word| word.first_child());
let mut cursor = Cursor::new(grapheme_id, 0, 0);
cursor.move_to_word_end(1);
assert_eq!(cursor.grapheme_index(), 1);
assert_eq!(cursor.line_index(), 0);
cursor.move_line(1);
assert_eq!(cursor.grapheme_index(), 1);
assert_eq!(cursor.line_index(), 1);
cursor.move_line(-1);
assert_eq!(cursor.grapheme_index(), 1);
assert_eq!(cursor.line_index(), 0);
cursor.move_to_word_end(1);
assert_eq!(cursor.grapheme_index(), 5);
assert_eq!(cursor.line_index(), 0);
cursor.move_to_word_end(1);
assert_eq!(cursor.grapheme_index(), 10);
assert_eq!(cursor.line_index(), 0);
cursor.move_to_word_end(1);
assert_eq!(cursor.grapheme_index(), 4);
assert_eq!(cursor.line_index(), 1);
cursor.move_to_word_end(1);
assert_eq!(cursor.grapheme_index(), 4);
assert_eq!(cursor.line_index(), 1);
cursor.move_to_word_end(-1);
assert_eq!(cursor.grapheme_index(), 10);
assert_eq!(cursor.line_index(), 0);
cursor.move_to_word_end(-1);
assert_eq!(cursor.grapheme_index(), 5);
assert_eq!(cursor.line_index(), 0);
cursor.move_to_word_end(-1);
assert_eq!(cursor.grapheme_index(), 1);
assert_eq!(cursor.line_index(), 0);
cursor.move_to_word_end(-1);
assert_eq!(cursor.grapheme_index(), 1);
assert_eq!(cursor.line_index(), 0);
cursor.move_to_word_end(1);
assert_eq!(cursor.grapheme_index(), 5);
assert_eq!(cursor.line_index(), 0);
cursor.move_grapheme(-1);
assert_eq!(cursor.grapheme_index(), 4);
assert_eq!(cursor.line_index(), 0);
cursor.move_to_word_end(1);
assert_eq!(cursor.grapheme_index(), 5);
assert_eq!(cursor.line_index(), 0);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment