From 90f9cd6d6275048db664afa4139e7f2bdfaeacb0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= <blaz@mxxn.io>
Date: Wed, 10 Mar 2021 17:50:46 +0900
Subject: [PATCH] search: draft f/t

---
 helix-core/src/search.rs | 69 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 helix-core/src/search.rs

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))
+}