summary refs log tree commit diff
path: root/src/main.rs
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-06-07 15:03:00 -0700
committerIrene Knapp <ireneista@irenes.space>2026-06-07 15:03:00 -0700
commit59576466ec7f3f743664b303a3eb8a6c4a613d5c (patch)
treea5412392b4649fb8e092e7cfdab930a19005aa26 /src/main.rs
parentfd8a530e27c93d7484a90e2b96ad765436d0dad3 (diff)
WIP cold commit, seems to be trying to factor out some duplication?
Force-Push: yes
Change-Id: Idf2d1f8c2ad744dc35cbb1a8a131e05efc18a32c
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
index 59d3baa..8532f28 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -52,6 +52,39 @@ enum MovementColumnBehavior {
 }
 
 
+struct Position {
+  byte_offset: usize,
+  row: usize,
+  column: usize,
+}
+
+impl Position {
+  pub fn zero() -> Self {
+    Position {
+      byte_offset: 0,
+      row: 0,
+      column: 0,
+    }
+  }
+
+  pub fn advance(&mut self, c: char) {
+    if c == '\n' {
+      self.row += 1;
+      self.column = 0;
+      self.byte_offset += 1;
+    } else {
+      self.column += 1;
+      self.byte_offset += 1;
+    }
+  }
+}
+
+enum ScanStep<State, Output> {
+  Continue(State),
+  End(Output),
+}
+
+
 fn main() -> ExitCode {
   smol::block_on(async {
     if let Err(e) = Ivy::new().await.run().await {
@@ -499,6 +532,74 @@ impl Ivy {
     Ok(())
   }
 
+  async fn scan_forward<State, Output>(&mut self,
+                mut position: Position, mut state: State,
+                test: impl AsyncFn(Position, State, Decode)
+                          -> Result<ScanStep<State, Output>)
+      -> Result<Option<Output>>
+  {
+    let mut offset = 0;
+    let mut state = initial;
+
+    loop {
+      let sub_span = range.start + offset .. range.end;
+      let mut contents = buffer.contents.write().await;
+      let mut cursor = Cursor::new(&mut contents[range]);
+
+      if let Ok(decode) = encoding::read_utf8_char(&mut cursor).await {
+        offset += decode.skipped_bytes;
+
+        match test(state, offset, decode)? {
+          Continue(new_state) => {
+            state = new_state;
+            offset += decode.found_bytes;
+          }
+          End(result) => {
+            return Ok(Some(result));
+          }
+        }
+      } else {
+        return Ok(None);
+      }
+    }
+  }
+
+  async fn next_word_boundary(&mut self) -> Result<()> {
+    let row = *self.window.read().await.cursor_row.read().await;
+    let buffer = self.buffer.write().await;
+
+    if let Some(row_span) = buffer.line_span(row).await {
+      let mut offset = 0;
+      loop {
+        let sub_span = row_span.start + offset .. row_span.end;
+        let mut contents = buffer.contents.write().await;
+        let mut cursor = Cursor::new(&mut contents[sub_span]);
+
+        if let Ok(decode) = encoding::read_utf8_char(&mut cursor).await {
+          offset += decode.skipped_bytes;
+
+          if offset > 0 && !decode.c.is_alphanumeric() && decode.c != '_' {
+            break;
+          } else {
+            offset += decode.found_bytes;
+          }
+        } else {
+          break;
+        }
+      }
+
+      let window = self.window.write().await;
+      *window.cursor_column.write().await = offset;
+      *window.neutral_column.write().await = offset;
+    } else {
+      let window = self.window.write().await;
+      *window.cursor_column.write().await = 0;
+      *window.neutral_column.write().await = 0;
+    }
+
+    Ok(())
+  }
+
   async fn scroll_to_cursor(&mut self) -> Result<()> {
     let old_scroll_top = *self.window.read().await.scroll_top.read().await;