diff options
author | Nathan Vegdahl | 2021-07-24 14:44:11 +0000 |
---|---|---|
committer | Nathan Vegdahl | 2021-07-24 14:44:11 +0000 |
commit | f96b8b769b3c7457935b5c02db870af97036f7b6 (patch) | |
tree | a730fd2e970d6349e0f11b450f1e58b2c79d010b /helix-core/src | |
parent | 20723495d3ee82047bc7584e9eca1424d1256f4c (diff) |
Switch to a cleaner range-head moving abstraction.
Also fix a bunch of bugs related to it.
Diffstat (limited to 'helix-core/src')
-rw-r--r-- | helix-core/src/movement.rs | 35 | ||||
-rw-r--r-- | helix-core/src/search.rs | 26 | ||||
-rw-r--r-- | helix-core/src/selection.rs | 20 | ||||
-rw-r--r-- | helix-core/src/surround.rs | 13 |
4 files changed, 38 insertions, 56 deletions
diff --git a/helix-core/src/movement.rs b/helix-core/src/movement.rs index 7f3a5ef4..80d19501 100644 --- a/helix-core/src/movement.rs +++ b/helix-core/src/movement.rs @@ -42,20 +42,18 @@ pub fn move_horizontally( }; // Compute the new position. - let mut new_pos = if dir == Direction::Backward { + let new_pos = if dir == Direction::Backward { nth_prev_grapheme_boundary(slice, pos, count) } else { nth_next_grapheme_boundary(slice, pos, count) }; - // Shift forward one grapheme if needed, for the - // visual 1-width cursor. - if behaviour == Extend && new_pos >= range.anchor { - new_pos = next_grapheme_boundary(slice, new_pos); - }; - // Compute the final new range. - range.put(slice, new_pos, behaviour == Extend) + if behaviour == Extend { + range.move_head(slice, new_pos, true) + } else { + Range::point(new_pos) + } } pub fn move_vertically( @@ -78,14 +76,17 @@ pub fn move_vertically( let horiz = range.horiz.unwrap_or(col as u32); // Compute the new position. - let new_pos = { + let (new_pos, new_row) = { let new_row = if dir == Direction::Backward { row.saturating_sub(count) } else { (row + count).min(slice.len_lines().saturating_sub(1)) }; let new_col = col.max(horiz as usize); - pos_at_coords(slice, Position::new(new_row, new_col), true) + ( + pos_at_coords(slice, Position::new(new_row, new_col), true), + new_row, + ) }; // Compute the new range according to the type of movement. @@ -97,15 +98,13 @@ pub fn move_vertically( }, Movement::Extend => { - let new_head = if new_pos >= range.anchor { - next_grapheme_boundary(slice, new_pos) + if slice.line(new_row).len_chars() > 0 { + let mut new_range = range.move_head(slice, new_pos, true); + new_range.horiz = Some(horiz); + new_range } else { - new_pos - }; - - let mut new_range = range.put(slice, new_head, true); - new_range.horiz = Some(horiz); - new_range + range + } } } } diff --git a/helix-core/src/search.rs b/helix-core/src/search.rs index d4eb11a9..243ac227 100644 --- a/helix-core/src/search.rs +++ b/helix-core/src/search.rs @@ -1,12 +1,6 @@ use crate::RopeSlice; -pub fn find_nth_next( - text: RopeSlice, - ch: char, - mut pos: usize, - n: usize, - inclusive: bool, -) -> Option<usize> { +pub fn find_nth_next(text: RopeSlice, ch: char, mut pos: usize, n: usize) -> Option<usize> { if pos >= text.len_chars() || n == 0 { return None; } @@ -25,20 +19,10 @@ pub fn find_nth_next( } } - if !inclusive { - pos -= 1; - } - - Some(pos) + Some(pos - 1) } -pub fn find_nth_prev( - text: RopeSlice, - ch: char, - mut pos: usize, - n: usize, - inclusive: bool, -) -> Option<usize> { +pub fn find_nth_prev(text: RopeSlice, ch: char, mut pos: usize, n: usize) -> Option<usize> { if pos == 0 || n == 0 { return None; } @@ -57,9 +41,5 @@ pub fn find_nth_prev( } } - if !inclusive { - pos += 1; - } - Some(pos) } diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs index e40fceb1..cef68212 100644 --- a/helix-core/src/selection.rs +++ b/helix-core/src/selection.rs @@ -248,18 +248,18 @@ impl Range { } } - /// Moves the `Range` to `char_idx`. If `extend == true`, then only the head - /// is moved to `char_idx`, and the anchor is adjusted only as needed to - /// preserve 1-width range semantics. + /// Moves the head of the `Range` to `char_idx`, adjusting the anchor + /// as needed to preserve 1-width range semantics. + /// + /// `block_cursor` specifies whether it should treat `char_idx` as a block + /// cursor position or as a range-end position. /// /// This method assumes that the range and `char_idx` are already properly /// grapheme-aligned. #[must_use] #[inline] - pub fn put(self, text: RopeSlice, char_idx: usize, extend: bool) -> Range { - let anchor = if !extend { - char_idx - } else if self.head >= self.anchor && char_idx < self.anchor { + pub fn move_head(self, text: RopeSlice, char_idx: usize, block_cursor: bool) -> Range { + let anchor = if self.head >= self.anchor && char_idx < self.anchor { next_grapheme_boundary(text, self.anchor) } else if self.head < self.anchor && char_idx >= self.anchor { prev_grapheme_boundary(text, self.anchor) @@ -267,7 +267,11 @@ impl Range { self.anchor }; - Range::new(anchor, char_idx) + if block_cursor && anchor <= char_idx { + Range::new(anchor, next_grapheme_boundary(text, char_idx)) + } else { + Range::new(anchor, char_idx) + } } // groupAt diff --git a/helix-core/src/surround.rs b/helix-core/src/surround.rs index af357c96..4d3ed5f5 100644 --- a/helix-core/src/surround.rs +++ b/helix-core/src/surround.rs @@ -49,19 +49,18 @@ pub fn find_nth_pairs_pos( if Some(open) == text.get_char(pos) { // Special case: cursor is directly on a matching char. match pos { - 0 => Some((pos, search::find_nth_next(text, close, pos + 1, n, true)?)), - _ if (pos + 1) == text.len_chars() => Some(( - search::find_nth_prev(text, open, pos, n, true)?, - text.len_chars(), - )), + 0 => Some((pos, search::find_nth_next(text, close, pos + 1, n)? + 1)), + _ if (pos + 1) == text.len_chars() => { + Some((search::find_nth_prev(text, open, pos, n)?, text.len_chars())) + } // We return no match because there's no way to know which // side of the char we should be searching on. _ => None, } } else { Some(( - search::find_nth_prev(text, open, pos, n, true)?, - search::find_nth_next(text, close, pos, n, true)?, + search::find_nth_prev(text, open, pos, n)?, + search::find_nth_next(text, close, pos, n)? + 1, )) } } else { |