aboutsummaryrefslogtreecommitdiff
path: root/helix-core/src/search.rs
diff options
context:
space:
mode:
Diffstat (limited to 'helix-core/src/search.rs')
-rw-r--r--helix-core/src/search.rs69
1 files changed, 69 insertions, 0 deletions
diff --git a/helix-core/src/search.rs b/helix-core/src/search.rs
new file mode 100644
index 00000000..7d790d66
--- /dev/null
+++ b/helix-core/src/search.rs
@@ -0,0 +1,69 @@
+use crate::RopeSlice;
+
+pub fn find_nth_next(text: RopeSlice, ch: char, pos: usize, n: usize) -> Option<usize> {
+ // start searching right after pos
+ let mut byte_idx = text.char_to_byte(pos + 1);
+
+ let (mut chunks, mut chunk_byte_idx, _chunk_char_idx, _chunk_line_idx) =
+ text.chunks_at_byte(byte_idx);
+
+ let mut chunk = chunks.next().unwrap_or("");
+
+ chunk = &chunk[(byte_idx - chunk_byte_idx)..];
+
+ for _ in 0..n {
+ loop {
+ match chunk.find(ch) {
+ Some(pos) => {
+ byte_idx += pos;
+ chunk = &chunk[pos + 1..];
+ break;
+ }
+ None => match chunks.next() {
+ Some(next_chunk) => {
+ byte_idx += chunk.len();
+ chunk = next_chunk;
+ }
+ None => {
+ log::info!("no more chunks");
+ return None;
+ }
+ },
+ }
+ }
+ }
+ Some(text.byte_to_char(byte_idx))
+}
+
+pub fn find_nth_prev(text: RopeSlice, ch: char, pos: usize, n: usize) -> Option<usize> {
+ // start searching right before pos
+ let mut byte_idx = text.char_to_byte(pos.saturating_sub(1));
+
+ let (mut chunks, mut chunk_byte_idx, _chunk_char_idx, _chunk_line_idx) =
+ text.chunks_at_byte(byte_idx);
+
+ let mut chunk = chunks.prev().unwrap_or("");
+
+ // start searching from pos
+ chunk = &chunk[..=byte_idx - chunk_byte_idx];
+
+ for _ in 0..n {
+ loop {
+ match chunk.rfind(ch) {
+ Some(pos) => {
+ byte_idx = chunk_byte_idx + pos;
+ chunk = &chunk[..pos];
+ break;
+ }
+ None => match chunks.prev() {
+ Some(prev_chunk) => {
+ chunk_byte_idx -= chunk.len();
+ chunk = prev_chunk;
+ }
+ None => return None,
+ },
+ }
+ }
+ }
+ Some(text.byte_to_char(byte_idx))
+}