From 46bed3055b52bc916360249f0a08f9686b22332a Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Sat, 6 Jan 2024 13:09:29 -0800 Subject: Support inserting newline. --- src/main.rs | 105 ++++++++++++++++++++++++++++++++++++++++++------------------ src/rope.rs | 23 ++++++++++--- 2 files changed, 91 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 4c93cb7..3745553 100644 --- a/src/main.rs +++ b/src/main.rs @@ -114,6 +114,64 @@ impl State { write!(stdout(), "\x1b[{}G", self.cursor_col+1)?; return Ok(()); } + + fn up(&mut self) -> Result<(), Box> { + if self.cursor_row == 0 && self.row_start == 0 { + return Ok(()); + } + if self.cursor_row == 0 { + self.row_start -= 1; + self.repaint_all()?; + } else { + self.cursor_row -= 1; + } + return Ok(()); + } + + fn down(&mut self) -> Result<(), Box> { + if self.row_start+self.cursor_row == self.buf.lines() { + return Ok(()); + } + let size = term::size()?; + if self.cursor_row == usize::from(size.ws_row - 1) { + self.row_start += 1; + self.repaint_all()?; + } else { + self.cursor_row += 1; + } + return Ok(()); + } + + fn left(&mut self) -> Result<(), Box> { + if self.cursor_col > self.line_cols { + self.cursor_col = self.line_cols; + } + if self.cursor_col == 0 && self.cursor_row == 0 { + return Ok(()); + } + if self.cursor_col == 0 { + self.up()?; + self.repaint_line_full()?; + self.cursor_col = self.line_cols; + } else { + self.cursor_col -= 1; + } + return Ok(()); + } + + fn right(&mut self) -> Result<(), Box> { + let size = term::size()?; + if self.cursor_col >= self.line_cols && self.cursor_row == usize::from(size.ws_row-1) { + return Ok(()); + } + if self.cursor_col >= self.line_cols { + self.down()?; + self.cursor_col = 0; + } else { + self.cursor_col += 1; + } + return Ok(()); + } } fn edit(file: &OsStr) -> Result<(), Box> { @@ -143,51 +201,34 @@ fn edit(file: &OsStr) -> Result<(), Box> { let _ = state.buf.save(Path::new(file)); } Key::Up => { - if state.cursor_row == 0 && state.row_start == 0 { - continue; - } - if state.cursor_row == 0 { - state.row_start -= 1; - let _ = state.repaint_all(); - } else { - state.cursor_row -= 1; - } + let _ = state.up(); let _ = state.repaint_line_full(); let _ = stdout().flush(); } Key::Down => { - if state.row_start+state.cursor_row == state.buf.lines() { - continue; - } - if state.cursor_row == usize::from(size.ws_row - 1) { - state.row_start += 1; - let _ = state.repaint_all(); - } else { - state.cursor_row += 1; - } + let _ = state.down(); let _ = state.repaint_line_full(); let _ = stdout().flush(); } Key::Left => { - state.cursor_col = std::cmp::min(state.cursor_col, state.line_cols); - if state.cursor_col == 0 { - state.cursor_row -= 1; - let _ = state.repaint_line_full(); - state.cursor_col = state.line_cols; - let _ = state.repaint_line_full(); - } else { - state.cursor_col -= 1; - let _ = state.repaint_line_full(); - } + let _ = state.left(); + let _ = state.repaint_line_full(); let _ = stdout().flush(); } Key::Right => { - if state.cursor_col >= state.line_cols { - state.cursor_row += 1; - state.cursor_col = 0; + let _ = state.right(); + let _ = state.repaint_line_full(); + let _ = stdout().flush(); + } + Key::Char(b'\r') => { + state.buf = state.buf.insert(state.buf.line_idx(state.row_start+state.cursor_row)+state.line_offset, b'\n'); + if state.cursor_row == usize::from(size.ws_row - 1) { + state.row_start += 1; } else { - state.cursor_col += 1; + state.cursor_row += 1; } + state.cursor_col = 0; + let _ = state.repaint_all(); let _ = state.repaint_line_full(); let _ = stdout().flush(); } diff --git a/src/rope.rs b/src/rope.rs index 11a030b..5454557 100644 --- a/src/rope.rs +++ b/src/rope.rs @@ -152,11 +152,24 @@ impl Rope { new_buf[pos + 1..].copy_from_slice(&l.bytes()[pos..]); return Rope::leaf(new_buf); } - let mut buf_left = vec![0; pos + 1]; - buf_left[..pos].copy_from_slice(&l.bytes()[..pos]); - buf_left[pos] = c; - let mut buf_right = Vec::new(); - buf_right.extend_from_slice(&l.bytes()[pos..]); + let half = MAX_NODE_SIZE / 2; + let mut buf_left; + let mut buf_right; + if pos <= half { + buf_left = vec![0; half+1]; + buf_right = vec![0; half]; + buf_left[..pos].copy_from_slice(&l.bytes()[..pos]); + buf_left[pos] = c; + buf_left[pos+1..].copy_from_slice(&l.bytes()[pos..half]); + buf_right.copy_from_slice(&l.bytes()[half..]); + } else { + buf_left = vec![0; half]; + buf_right = vec![0; half+1]; + buf_left.copy_from_slice(&l.bytes()[..half]); + buf_right[..pos-half].copy_from_slice(&l.bytes()[half..pos]); + buf_right[pos-half] = c; + buf_right[pos-half+1..].copy_from_slice(&l.bytes()[pos..]); + } return Rope::leaf(buf_left).concat(&Rope::leaf(buf_right)); } Rope(Node::Branch(b)) => { -- cgit v1.3.1