Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-core/src/search.rs')
-rw-r--r--helix-core/src/search.rs76
1 files changed, 48 insertions, 28 deletions
diff --git a/helix-core/src/search.rs b/helix-core/src/search.rs
index 81cb4129..7cbc58d6 100644
--- a/helix-core/src/search.rs
+++ b/helix-core/src/search.rs
@@ -1,3 +1,4 @@
+use crate::movement::Direction;
use crate::RopeSlice;
// TODO: switch to std::str::Pattern when it is stable.
@@ -17,51 +18,70 @@ impl<F: Fn(&char) -> bool> CharMatcher for F {
}
}
-pub fn find_nth_next<M: CharMatcher>(
+// Finds the positions of the nth matching character in given direction
+// starting from the pos gap-index (see Range struct for explanation)
+pub fn find_nth_char<M: CharMatcher>(
+ mut n: usize,
text: RopeSlice,
char_matcher: M,
mut pos: usize,
- n: usize,
+ direction: Direction,
) -> Option<usize> {
- if pos >= text.len_chars() || n == 0 {
+ if n == 0 {
return None;
}
- let mut chars = text.chars_at(pos);
+ let mut chars = text.get_chars_at(pos)?;
- for _ in 0..n {
- loop {
+ match direction {
+ Direction::Forward => loop {
let c = chars.next()?;
-
+ if char_matcher.char_match(c) {
+ n -= 1;
+ if n == 0 {
+ return Some(pos);
+ }
+ }
pos += 1;
-
+ },
+ Direction::Backward => loop {
+ let c = chars.prev()?;
+ pos -= 1;
if char_matcher.char_match(c) {
- break;
+ n -= 1;
+ if n == 0 {
+ return Some(pos);
+ }
}
- }
- }
-
- Some(pos - 1)
+ },
+ };
}
-pub fn find_nth_prev(text: RopeSlice, ch: char, mut pos: usize, n: usize) -> Option<usize> {
- if pos == 0 || n == 0 {
- return None;
- }
+#[cfg(test)]
+mod test {
+ use super::*;
+ use crate::movement::Direction;
- let mut chars = text.chars_at(pos);
+ #[test]
+ fn test_find_nth_char() {
+ let text = RopeSlice::from("aa ⌚aa \r\n aa");
- for _ in 0..n {
- loop {
- let c = chars.prev()?;
+ // Forward direction
+ assert_eq!(find_nth_char(1, text, 'a', 5, Direction::Forward), Some(5));
+ assert_eq!(find_nth_char(2, text, 'a', 5, Direction::Forward), Some(10));
+ assert_eq!(find_nth_char(3, text, 'a', 5, Direction::Forward), Some(11));
+ assert_eq!(find_nth_char(4, text, 'a', 5, Direction::Forward), None);
- pos -= 1;
+ // Backward direction
+ assert_eq!(find_nth_char(1, text, 'a', 5, Direction::Backward), Some(4));
+ assert_eq!(find_nth_char(2, text, 'a', 5, Direction::Backward), Some(1));
+ assert_eq!(find_nth_char(3, text, 'a', 5, Direction::Backward), Some(0));
+ assert_eq!(find_nth_char(4, text, 'a', 5, Direction::Backward), None);
- if c == ch {
- break;
- }
- }
+ // Edge cases
+ assert_eq!(find_nth_char(0, text, 'a', 5, Direction::Forward), None); // n = 0
+ assert_eq!(find_nth_char(1, text, 'x', 5, Direction::Forward), None); // Not found
+ assert_eq!(find_nth_char(1, text, 'a', 20, Direction::Forward), None); // Beyond text
+ assert_eq!(find_nth_char(1, text, 'a', 0, Direction::Backward), None); // At start going backward
}
-
- Some(pos)
}