diff --git a/src/buffer/line.rs b/src/buffer/line.rs index 2bc0bd8..cd6e168 100644 --- a/src/buffer/line.rs +++ b/src/buffer/line.rs @@ -316,6 +316,7 @@ impl Line { pub fn grapheme_iter<'a>(&'a self) -> LineGraphemeIter<'a> { LineGraphemeIter { graphemes: self.text.grapheme_iter(), + grapheme_count: None, ending: self.ending, done: false, } @@ -326,6 +327,18 @@ impl Line { pub fn grapheme_iter_at_index<'a>(&'a self, index: usize) -> LineGraphemeIter<'a> { LineGraphemeIter { graphemes: self.text.grapheme_iter_at_index(index), + grapheme_count: None, + ending: self.ending, + done: false, + } + } + + + /// Returns an iterator over the graphemes of the line + pub fn grapheme_iter_at_index_with_max_length<'a>(&'a self, index: usize, length: usize) -> LineGraphemeIter<'a> { + LineGraphemeIter { + graphemes: self.text.grapheme_iter_at_index(index), + grapheme_count: Some(length), ending: self.ending, done: false, } @@ -422,6 +435,7 @@ pub const LINE_ENDINGS: [&'static str; 9] = ["", /// An iterator over the graphemes of a Line pub struct LineGraphemeIter<'a> { graphemes: RopeGraphemeIter<'a>, + grapheme_count: Option, ending: LineEnding, done: bool, } @@ -443,7 +457,14 @@ impl<'a> Iterator for LineGraphemeIter<'a> { if self.done { return None; } + else if let Some(0) = self.grapheme_count { + return None; + } else { + if let Some(ref mut i) = self.grapheme_count { + *i -= 1; + } + let g = self.graphemes.next(); if let Some(_) = g { return g; diff --git a/src/formatter.rs b/src/formatter.rs index 26b7b19..627eb99 100644 --- a/src/formatter.rs +++ b/src/formatter.rs @@ -47,7 +47,7 @@ pub trait LineFormatter { let (line_block, col_i_adjusted) = block_index_and_offset(col_i); // Get an iter into the right block - let g_iter = line.grapheme_iter_at_index(line_block * LINE_BLOCK_LENGTH); + let g_iter = line.grapheme_iter_at_index_with_max_length(line_block * LINE_BLOCK_LENGTH, LINE_BLOCK_LENGTH); return self.index_to_v2d(g_iter, col_i_adjusted).1; } @@ -64,7 +64,7 @@ pub trait LineFormatter { // Find the right block in the line, and the index within that block let (line_block, col_i_adjusted) = block_index_and_offset(col_i); - let (mut y, x) = self.index_to_v2d(buf.get_line(line_i).grapheme_iter_at_index(line_block*LINE_BLOCK_LENGTH), col_i_adjusted); + let (mut y, x) = self.index_to_v2d(buf.get_line(line_i).grapheme_iter_at_index_with_max_length(line_block*LINE_BLOCK_LENGTH, LINE_BLOCK_LENGTH), col_i_adjusted); let mut new_y = y as isize + offset; // First, find the right line while keeping track of the vertical offset @@ -72,7 +72,7 @@ pub trait LineFormatter { let mut block_index: usize = line_block; loop { line = buf.get_line(line_i); - let (h, _) = self.dimensions(line.grapheme_iter_at_index(line_block*LINE_BLOCK_LENGTH)); + let (h, _) = self.dimensions(line.grapheme_iter_at_index_with_max_length(line_block*LINE_BLOCK_LENGTH, LINE_BLOCK_LENGTH)); if new_y >= 0 && new_y < h as isize { y = new_y as usize; @@ -110,7 +110,7 @@ pub trait LineFormatter { else { block_index -= 1; } - let (h, _) = self.dimensions(line.grapheme_iter_at_index(line_block*LINE_BLOCK_LENGTH)); + let (h, _) = self.dimensions(line.grapheme_iter_at_index_with_max_length(line_block*LINE_BLOCK_LENGTH, LINE_BLOCK_LENGTH)); new_y += h as isize; } else { @@ -121,7 +121,7 @@ pub trait LineFormatter { // Next, convert the resulting coordinates back into buffer-wide // coordinates. - col_i = (block_index * LINE_BLOCK_LENGTH) + self.v2d_to_index(line.grapheme_iter_at_index(block_index*LINE_BLOCK_LENGTH), (y, x), rounding); + col_i = (block_index * LINE_BLOCK_LENGTH) + self.v2d_to_index(line.grapheme_iter_at_index_with_max_length(block_index*LINE_BLOCK_LENGTH, LINE_BLOCK_LENGTH), (y, x), rounding); return buf.line_col_to_index((line_i, col_i)); } @@ -136,8 +136,8 @@ pub trait LineFormatter { let start_index = line_block * LINE_BLOCK_LENGTH; // Calculate the horizontal position - let (v, _) = self.index_to_v2d(line.grapheme_iter_at_index(start_index), col_i_adjusted); - let mut new_col_i = start_index + self.v2d_to_index(line.grapheme_iter_at_index(start_index), (v, horizontal), (RoundingBehavior::Floor, rounding)); + let (v, _) = self.index_to_v2d(line.grapheme_iter_at_index_with_max_length(start_index, LINE_BLOCK_LENGTH), col_i_adjusted); + let mut new_col_i = start_index + self.v2d_to_index(line.grapheme_iter_at_index_with_max_length(start_index, LINE_BLOCK_LENGTH), (v, horizontal), (RoundingBehavior::Floor, rounding)); // Make sure we're not pushing the index off the end of the line if (line_i + 1) < buf.line_count()