aboutsummaryrefslogtreecommitdiff
path: root/helix-core/src/surround.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-core/src/surround.rs')
-rw-r--r--helix-core/src/surround.rs75
1 files changed, 44 insertions, 31 deletions
diff --git a/helix-core/src/surround.rs b/helix-core/src/surround.rs
index 52f60cab..4d3ed5f5 100644
--- a/helix-core/src/surround.rs
+++ b/helix-core/src/surround.rs
@@ -1,3 +1,4 @@
+use crate::graphemes::next_grapheme_boundary;
use crate::{search, Selection};
use ropey::RopeSlice;
@@ -40,23 +41,34 @@ pub fn find_nth_pairs_pos(
) -> Option<(usize, usize)> {
let (open, close) = get_pair(ch);
- let (open_pos, close_pos) = if open == close {
- let prev = search::find_nth_prev(text, open, pos, n, true);
- let next = search::find_nth_next(text, close, pos, n, true);
- if text.char(pos) == open {
- // cursor is *on* a pair
- next.map(|n| (pos, n)).or_else(|| prev.map(|p| (p, pos)))?
+ if text.len_chars() < 2 || pos >= text.len_chars() {
+ return None;
+ }
+
+ if open == close {
+ 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)? + 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 {
- (prev?, next?)
+ Some((
+ search::find_nth_prev(text, open, pos, n)?,
+ search::find_nth_next(text, close, pos, n)? + 1,
+ ))
}
} else {
- (
+ Some((
find_nth_open_pair(text, open, close, pos, n)?,
- find_nth_close_pair(text, open, close, pos, n)?,
- )
- };
-
- Some((open_pos, close_pos))
+ next_grapheme_boundary(text, find_nth_close_pair(text, open, close, pos, n)?),
+ ))
+ }
}
fn find_nth_open_pair(
@@ -173,12 +185,13 @@ mod test {
let slice = doc.slice(..);
// cursor on [t]ext
- assert_eq!(find_nth_pairs_pos(slice, '(', 6, 1), Some((5, 10)));
- assert_eq!(find_nth_pairs_pos(slice, ')', 6, 1), Some((5, 10)));
+ assert_eq!(find_nth_pairs_pos(slice, '(', 6, 1), Some((5, 11)));
+ assert_eq!(find_nth_pairs_pos(slice, ')', 6, 1), Some((5, 11)));
// cursor on so[m]e
assert_eq!(find_nth_pairs_pos(slice, '(', 2, 1), None);
// cursor on bracket itself
- assert_eq!(find_nth_pairs_pos(slice, '(', 5, 1), Some((5, 10)));
+ assert_eq!(find_nth_pairs_pos(slice, '(', 5, 1), Some((5, 11)));
+ assert_eq!(find_nth_pairs_pos(slice, '(', 10, 1), Some((5, 11)));
}
#[test]
@@ -187,9 +200,9 @@ mod test {
let slice = doc.slice(..);
// cursor on go[o]d
- assert_eq!(find_nth_pairs_pos(slice, '(', 13, 1), Some((10, 15)));
- assert_eq!(find_nth_pairs_pos(slice, '(', 13, 2), Some((4, 21)));
- assert_eq!(find_nth_pairs_pos(slice, '(', 13, 3), Some((0, 27)));
+ assert_eq!(find_nth_pairs_pos(slice, '(', 13, 1), Some((10, 16)));
+ assert_eq!(find_nth_pairs_pos(slice, '(', 13, 2), Some((4, 22)));
+ assert_eq!(find_nth_pairs_pos(slice, '(', 13, 3), Some((0, 28)));
}
#[test]
@@ -198,14 +211,14 @@ mod test {
let slice = doc.slice(..);
// cursor on go[o]d
- assert_eq!(find_nth_pairs_pos(slice, '\'', 13, 1), Some((10, 15)));
- assert_eq!(find_nth_pairs_pos(slice, '\'', 13, 2), Some((4, 21)));
- assert_eq!(find_nth_pairs_pos(slice, '\'', 13, 3), Some((0, 27)));
+ assert_eq!(find_nth_pairs_pos(slice, '\'', 13, 1), Some((10, 16)));
+ assert_eq!(find_nth_pairs_pos(slice, '\'', 13, 2), Some((4, 22)));
+ assert_eq!(find_nth_pairs_pos(slice, '\'', 13, 3), Some((0, 28)));
// cursor on the quotes
- assert_eq!(find_nth_pairs_pos(slice, '\'', 10, 1), Some((10, 15)));
+ assert_eq!(find_nth_pairs_pos(slice, '\'', 10, 1), None);
// this is the best we can do since opening and closing pairs are same
- assert_eq!(find_nth_pairs_pos(slice, '\'', 0, 1), Some((0, 4)));
- assert_eq!(find_nth_pairs_pos(slice, '\'', 27, 1), Some((21, 27)));
+ assert_eq!(find_nth_pairs_pos(slice, '\'', 0, 1), Some((0, 5)));
+ assert_eq!(find_nth_pairs_pos(slice, '\'', 27, 1), Some((21, 28)));
}
#[test]
@@ -214,8 +227,8 @@ mod test {
let slice = doc.slice(..);
// cursor on go[o]d
- assert_eq!(find_nth_pairs_pos(slice, '(', 15, 1), Some((5, 24)));
- assert_eq!(find_nth_pairs_pos(slice, '(', 15, 2), Some((0, 31)));
+ assert_eq!(find_nth_pairs_pos(slice, '(', 15, 1), Some((5, 25)));
+ assert_eq!(find_nth_pairs_pos(slice, '(', 15, 2), Some((0, 32)));
}
#[test]
@@ -224,9 +237,9 @@ mod test {
let slice = doc.slice(..);
// cursor on go[o]d
- assert_eq!(find_nth_pairs_pos(slice, '{', 13, 1), Some((10, 15)));
- assert_eq!(find_nth_pairs_pos(slice, '[', 13, 1), Some((4, 21)));
- assert_eq!(find_nth_pairs_pos(slice, '(', 13, 1), Some((0, 27)));
+ assert_eq!(find_nth_pairs_pos(slice, '{', 13, 1), Some((10, 16)));
+ assert_eq!(find_nth_pairs_pos(slice, '[', 13, 1), Some((4, 22)));
+ assert_eq!(find_nth_pairs_pos(slice, '(', 13, 1), Some((0, 28)));
}
#[test]
@@ -243,7 +256,7 @@ mod test {
get_surround_pos(slice, &selection, '(', 1)
.unwrap()
.as_slice(),
- &[0, 5, 7, 13, 15, 23]
+ &[0, 6, 7, 14, 15, 24]
);
}