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.rs | 76 |
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) } |