summary refs log tree commit diff
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-03-27 12:32:17 -0700
committerIrene Knapp <ireneista@irenes.space>2026-03-27 12:32:17 -0700
commitcde5c0194b8300e31cab77aeb31e67c071f5deb0 (patch)
tree540b9a37275ee235f3e2632486f9d4a9c104fec7
parenta52b286d6c8e2000c416f23eece0b930fe8ec4e9 (diff)
refactor screen drawing to be invokable row by row HEAD main
and use it to make scrolling efficient in terms of redraws! yay!

Force-Push: yes
Change-Id: Ib6de76f6ca1603c4e7a0f11e9a4f2371a145b7c6
-rw-r--r--src/main.rs51
1 files changed, 40 insertions, 11 deletions
diff --git a/src/main.rs b/src/main.rs
index b94b274..9b2a2e7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -133,19 +133,30 @@ impl Ivy {
     Ok(())
   }
 
-  async fn draw(&mut self) -> Result<()> {
-    let mut terminal = self.terminal.write().await;
-    let buffer = self.buffer.read().await;
+  async fn draw_all(&mut self) -> Result<()> {
+    let height = *self.terminal.read().await.height.read().await;
 
-    let height = *terminal.height.read().await;
+    self.draw_range(0 .. height - 1).await?;
+    self.draw_status_line().await?;
+    self.fix_cursor_position().await?;
+
+    self.terminal.write().await.stdout.flush().await?;
+
+    Ok(())
+  }
 
+  async fn draw_range(&mut self, range: Range<usize>) -> Result<()> {
+    let mut terminal = self.terminal.write().await;
     let window = self.window.read().await;
+    let buffer = self.buffer.read().await;
     let scroll_top = *window.scroll_top.read().await;
 
-    let mut screen_y = 0;
-    for i in 0 .. height - 1 {
+    terminal.do_cursor_position(0, range.start).await?;
+
+    let mut screen_y = range.start;
+    for i in range.clone() {
       if let Some(span) = buffer.line_span(i + scroll_top).await {
-        if i > 0 {
+        if i > range.start {
           terminal.stdout.write_all("\n".as_bytes()).await?;
         }
 
@@ -157,24 +168,35 @@ impl Ivy {
       }
     }
 
-    for _ in screen_y .. height - 1 {
+    for _ in screen_y .. range.end {
       terminal.stdout.write_all("\n~".as_bytes()).await?;
     }
 
+    Ok(())
+  }
+
+  async fn draw_status_line(&mut self) -> Result<()> {
+    let mut terminal = self.terminal.write().await;
+    let height = *terminal.height.read().await;
+
     terminal.do_cursor_position(0, height).await?;
     terminal.stdout.write_all("        status goes here".as_bytes()).await?;
 
+    Ok(())
+  }
+
+  async fn fix_cursor_position(&mut self) -> Result<()> {
+    let mut terminal = self.terminal.write().await;
     let window = self.window.read().await;
     terminal.do_cursor_position(*window.cursor_column.read().await,
                                 *window.cursor_row.read().await
                                 - *window.scroll_top.read().await).await?;
-    terminal.stdout.flush().await?;
 
     Ok(())
   }
 
   async fn interact(&mut self) -> Result<()> {
-    self.draw().await?;
+    self.draw_all().await?;
 
     loop {
       let c = self.terminal.write().await.read_char().await?;
@@ -391,9 +413,16 @@ impl Ivy {
       let difference = new_scroll_top as isize - old_scroll_top as isize;
       if (difference.abs() as usize) < height {
         self.terminal.write().await.scroll(difference).await?;
+
+        if difference > 0 {
+          self.draw_range((height as isize - difference) as usize
+                          .. height).await?;
+        } else {
+          self.draw_range(0 .. difference.abs() as usize).await?;
+        }
       } else {
         self.terminal.write().await.clear().await?;
-        self.draw().await?;
+        self.draw_all().await?;
       }
     }