From 7b2d4b4724cb9458ceed8d88ed58a4bfe0ea4092 Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Fri, 27 Mar 2026 04:27:16 -0700 Subject: added a handle_movement() abstraction right now, the main thing it takes care of is checking whether it's actually necessary to move the cursor, and doing it. the hope is to be very parsimonious of bandwidth, like to 1980s standards, and to also be deliberate about making sure the portions of the screen that are redrawn follow logically from the user's actions. this is meant to help in high-latency situations as well as with screen readers. also, it just feels right. Force-Push: yes Change-Id: Ib26ae484a34e0aaa0e8382f5ad4966226bada223 --- src/main.rs | 148 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 89 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 0625ccc..ea151c8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -128,6 +128,41 @@ impl Ivy { Ok(()) } + async fn draw(&mut self) -> Result<()> { + let mut terminal = self.terminal.write().await; + let buffer = self.buffer.read().await; + + let height = *terminal.height.read().await; + + let mut screen_y = 0; + for logical_y in 0 .. height - 1 { + if let Some(span) = buffer.line_span(logical_y).await { + if logical_y > 0 { + terminal.stdout.write_all("\n".as_bytes()).await?; + } + + terminal.stdout.write_all(&buffer.contents.read().await[span]).await?; + + screen_y = logical_y + 1; + } else { + break; + } + } + + for _ in screen_y .. height - 1 { + terminal.stdout.write_all("\n~".as_bytes()).await?; + } + + terminal.stdout.write_all("\n status goes here".as_bytes()).await?; + + let window = self.window.read().await; + terminal.do_cursor_position(*window.cursor_column.read().await, + *window.cursor_row.read().await).await?; + terminal.stdout.flush().await?; + + Ok(()) + } + async fn interact(&mut self) -> Result<()> { self.draw().await?; @@ -136,51 +171,51 @@ impl Ivy { match c { 'h' => { - let window = self.window.write().await; - let mut column = window.cursor_column.write().await; - if *column > 0 { - *column -= 1; - } + self.handle_movement(async |ivy: &mut Ivy| { + let window = ivy.window.write().await; - let mut terminal = self.terminal.write().await; - terminal.do_cursor_position( - *column, *window.cursor_row.read().await).await?; - terminal.stdout.flush().await?; + let mut column = window.cursor_column.write().await; + if *column > 0 { + *column -= 1; + } + + Ok(()) + }).await?; }, 'j' => { - let window = self.window.write().await; - let mut row = window.cursor_row.write().await; - *row += 1; - - let mut terminal = self.terminal.write().await; - terminal.do_cursor_position( - *window.cursor_column.read().await, *row).await?; - terminal.stdout.flush().await?; + self.handle_movement(async |ivy: &mut Ivy| { + let window = ivy.window.write().await; + + let mut row = window.cursor_row.write().await; + *row += 1; + + Ok(()) + }).await?; }, 'k' => { - let window = self.window.write().await; - let mut row = window.cursor_row.write().await; - if *row > 0 { - *row -= 1; - } + self.handle_movement(async |ivy: &mut Ivy| { + let window = ivy.window.write().await; + + let mut row = window.cursor_row.write().await; + if *row > 0 { + *row -= 1; + } - let mut terminal = self.terminal.write().await; - terminal.do_cursor_position( - *window.cursor_column.read().await, *row).await?; - terminal.stdout.flush().await?; + Ok(()) + }).await?; }, 'l' => { - let window = self.window.write().await; - let mut column = window.cursor_column.write().await; - *column += 1; - - let mut terminal = self.terminal.write().await; - terminal.do_cursor_position( - *column, *window.cursor_row.read().await).await?; - terminal.stdout.flush().await?; + self.handle_movement(async |ivy: &mut Ivy| { + let window = ivy.window.write().await; + + let mut column = window.cursor_column.write().await; + *column += 1; + + Ok(()) + }).await?; }, _ => { @@ -190,37 +225,32 @@ impl Ivy { } } - async fn draw(&mut self) -> Result<()> { - let mut terminal = self.terminal.write().await; - let buffer = self.buffer.read().await; - - let height = *terminal.height.read().await; + async fn handle_movement(&mut self, + movement: impl AsyncFn(&mut Ivy) -> Result<()>) + -> Result<()> + { + let (old_row, old_column) = { + let window = self.window.read().await; - let mut screen_y = 0; - for logical_y in 0 .. height - 1 { - if let Some(span) = buffer.line_span(logical_y).await { - if logical_y > 0 { - terminal.stdout.write_all("\n".as_bytes()).await?; - } + (*window.cursor_row.read().await, + *window.cursor_column.read().await) + }; - terminal.stdout.write_all(&buffer.contents.read().await[span]).await?; + movement(self).await?; - screen_y = logical_y + 1; - } else { - break; - } - } + let (new_row, new_column) = { + let window = self.window.read().await; - for _ in screen_y .. height - 1 { - terminal.stdout.write_all("\n~".as_bytes()).await?; - } + (*window.cursor_row.read().await, + *window.cursor_column.read().await) + }; - terminal.stdout.write_all("\n status goes here".as_bytes()).await?; + if old_row != new_row || old_column != new_column { + 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).await?; - terminal.stdout.flush().await?; + terminal.do_cursor_position(new_column, new_row).await?; + terminal.stdout.flush().await?; + } Ok(()) } -- cgit 1.4.1