diff options
| author | Rose Hogenson <rosehogenson@posteo.net> | 2023-12-29 16:13:59 -0800 |
|---|---|---|
| committer | Rose Hogenson <rosehogenson@posteo.net> | 2023-12-29 16:13:59 -0800 |
| commit | da54c7c2c103c9b1c98f0c5179945b0122a1eef7 (patch) | |
| tree | c11c0a4595e7569bd99e946250ed01575cec27f9 /src | |
| parent | Keep track of cursor position. (diff) | |
| download | editor-da54c7c2c103c9b1c98f0c5179945b0122a1eef7.tar.zst | |
Support inserting text.
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 19 | ||||
| -rw-r--r-- | src/rope.rs | 54 | ||||
| -rw-r--r-- | src/term.rs | 4 |
3 files changed, 71 insertions, 6 deletions
diff --git a/src/main.rs b/src/main.rs index de25e9c..dd20c3f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,7 @@ fn edit(file: &OsStr) -> Result<(), String> { } }; - let r = match Rope::open(Path::new(file)) { + let mut r = match Rope::open(Path::new(file)) { Ok(r) => r, Err(err) => { return Err(format!("open file {}: {}", file.to_string_lossy(), err)); @@ -44,6 +44,7 @@ fn edit(file: &OsStr) -> Result<(), String> { break; } }; + // TODO: handle line-wrapping. let _ = line.print(&mut stdout); } let _ = stdout.write(b"\x1b[H"); @@ -113,15 +114,25 @@ fn edit(file: &OsStr) -> Result<(), String> { .line(cursor_row) .expect("cursor_row should always be valid") .len(); - if cursor_col == usize::from(size.ws_col - 1) || cursor_col >= len { + if cursor_col >= len { continue; } cursor_col += 1; move_cursor(&mut stdout, cursor_row, cursor_col); } Key::Char(c) => { - print!("{} ", c); - let _ = stdout.flush(); + let line = r + .line(cursor_row) + .expect("cursor_row should always be valid"); + cursor_col = std::cmp::min(cursor_col, line.len()); + r = line.insert(cursor_col, c); + move_cursor(&mut stdout, cursor_row, 0); + let _ = r + .line(cursor_row) + .expect("cursor_row should always be valid") + .print(&mut stdout); + cursor_col += 1; + move_cursor(&mut stdout, cursor_row, cursor_col); } } } diff --git a/src/rope.rs b/src/rope.rs index 3162e44..7d5ee28 100644 --- a/src/rope.rs +++ b/src/rope.rs @@ -132,6 +132,55 @@ impl Node { } } } + + fn insert(&self, pos: usize, c: u8) -> Node { + match self { + Node::Leaf(v) => { + if v.len() < MAX_NODE_SIZE { + let mut new_buf = vec![0; v.len() + 1]; + new_buf[..pos].copy_from_slice(&v[..pos]); + new_buf[pos] = c; + new_buf[pos + 1..].copy_from_slice(&v[pos..]); + return Node::Leaf(new_buf); + } + let mut buf_left = vec![0; pos + 1]; + buf_left[..pos].copy_from_slice(&v[..pos]); + buf_left[pos] = c; + let mut buf_right = Vec::new(); + buf_right.extend_from_slice(&v[pos..]); + let mut lines = self.lines(); + if c == b'\n' { + lines += 1; + } + return Node::Branch(Branch { + left: Rc::new(Node::Leaf(buf_left)), + right: Rc::new(Node::Leaf(buf_right)), + len: v.len() + 1, + lines: lines, + }); + } + Node::Branch(b) => { + let mut lines = self.lines(); + if c == b'\n' { + lines += 1; + } + if pos < b.left.len() { + return Node::Branch(Branch { + left: Rc::new(b.left.insert(pos, c)), + right: b.right.clone(), + len: b.len + 1, + lines: lines, + }); + } + return Node::Branch(Branch { + left: b.left.clone(), + right: Rc::new(b.right.insert(pos - b.left.len(), c)), + len: b.len + 1, + lines: lines, + }); + } + } + } } impl Display for Node { @@ -251,4 +300,9 @@ impl Slice { pub fn len(&self) -> usize { return self.end - self.start; } + + pub fn insert(&self, pos: usize, c: u8) -> Rope { + let Rope(buf) = &self.buf; + return Rope(Rc::new(buf.insert(self.start + pos, c))); + } } diff --git a/src/term.rs b/src/term.rs index 20098a0..2303fa2 100644 --- a/src/term.rs +++ b/src/term.rs @@ -67,7 +67,7 @@ pub enum Key { Down, Left, Right, - Char(char), + Char(u8), } pub fn read_key(stdin: &mut Stdin) -> Result<Key, String> { @@ -83,7 +83,7 @@ pub fn read_key(stdin: &mut Stdin) -> Result<Key, String> { return Ok(Key::CtrlQ); } if buf[0] != ESC { - return Ok(Key::Char(char::from(buf[0]))); + return Ok(Key::Char(buf[0])); } // Try to handle an escape sequence. let mut buf = vec![0; 2]; |
