aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs19
-rw-r--r--src/rope.rs54
-rw-r--r--src/term.rs4
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];