From 9a5e271ccfc8cc91377a58344045173add5a75d5 Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Fri, 27 Mar 2026 04:12:42 -0700 Subject: the hjkl commands are partly implemented it's now possible to move the cursor around the screen, but it doesn't interact with the buffer in any way. in particular it isn't forced to stay within the buffer, it just moves wherever. Force-Push: yes Change-Id: If56d044b97c761a2070ffc2cc3f541b35ef9965f --- src/main.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/terminal.rs | 4 ++- 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1753688..0625ccc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ mod types; struct Ivy { terminal: RwLock, buffer: RwLock, + window: RwLock, argument_files: Vec, } @@ -26,6 +27,18 @@ struct Buffer { has_end_newline: RwLock, } +struct Window { + /* The traditional order of writing "row, column" is the opposite of the + * traditional order of writing "x, y"; be mindful. An alternate approach + * would use "x" and "y" for all the names, which might arguably reduce + * confusion, but personally we find the ordering concern to be + * aesthetically pleasing, a quiet reminder of how much humans care about + * everything. + */ + cursor_column: RwLock, + cursor_row: RwLock, +} + fn main() -> ExitCode { smol::block_on(async { @@ -44,6 +57,7 @@ impl Ivy { Ivy { terminal: RwLock::new(Terminal::new().await), buffer: RwLock::new(Buffer::new().await), + window: RwLock::new(Window::new().await), argument_files: Vec::new(), } } @@ -118,10 +132,61 @@ impl Ivy { self.draw().await?; loop { - let c = self.terminal.write().await.read_char().await; - println!("c {:?}", c); - smol::Timer::after(std::time::Duration::from_millis(1000)).await; - return Ok(()); + let c = self.terminal.write().await.read_char().await?; + + match c { + 'h' => { + let window = self.window.write().await; + let mut column = window.cursor_column.write().await; + if *column > 0 { + *column -= 1; + } + + let mut terminal = self.terminal.write().await; + terminal.do_cursor_position( + *column, *window.cursor_row.read().await).await?; + terminal.stdout.flush().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?; + }, + + 'k' => { + let window = self.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?; + }, + + '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?; + }, + + _ => { + return Ok(()); + }, + } } } @@ -152,7 +217,9 @@ impl Ivy { terminal.stdout.write_all("\n status goes here".as_bytes()).await?; - terminal.do_cursor_position(0, 0).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(()) @@ -242,3 +309,14 @@ impl Buffer { } } } + + +impl Window { + pub async fn new() -> Self { + Window { + cursor_column: RwLock::new(0), + cursor_row: RwLock::new(0), + } + } +} + diff --git a/src/terminal.rs b/src/terminal.rs index d812069..de3ca4f 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -213,7 +213,9 @@ impl Terminal { } // vt220? vt100? - pub async fn do_cursor_position(&mut self, x: u64, y: u64) -> Result<()> { + pub async fn do_cursor_position(&mut self, x: usize, y: usize) + -> Result<()> + { self.do_escape(EscapeType::CSI, "H", &[y + 1, x + 1]).await } -- cgit 1.4.1