Able to add text and move around in editor now

This commit is contained in:
Andrew Dinh 2021-01-16 03:39:34 -08:00
parent 57113c6b9d
commit 277fe8092f
Signed by: andrewkdinh
GPG Key ID: 2B557D93C6C08B86
2 changed files with 161 additions and 15 deletions

View File

@ -32,7 +32,7 @@ pub(crate) struct Editor {
}
impl Editor {
/// Initialize a new editor from a file path
/// Initialize a new editor from a file path (read a single line)
pub(crate) fn new(file_path: String) -> Editor {
// let (reader, eof_reached) = create_reader(file_path);
let reader;
@ -49,7 +49,7 @@ impl Editor {
reader = Err("File doesn't exist".to_string());
eof_reached = true;
}
Editor {piece_table: PieceTable::new(),
let mut editor = Editor {piece_table: PieceTable::new(),
pt_index: 0,
file_path: file_path,
reader: reader,
@ -58,19 +58,50 @@ impl Editor {
row: 1,
col: 1,
col_want: 1,
};
if editor.read_lines(1) == 0 {
editor.lines.push(0);
} else {
editor.lines.push(editor.piece_table.text_len());
}
editor
}
/// Returns visible text
fn text(&mut self) -> &str {
self.piece_table.text()
}
/// Adds `text` at the current cursor position
fn add_text(&mut self, text: String) {
let mut num_lines = 0;
let mut last_line_len = self.col_want - 1;
for (i, line) in text.split("\n").enumerate() {
// TODO: Insert text to visual editor
if self.row + i - 1 >= self.lines.len() {
self.lines.push(line.len());
} else if i == 0 {
*(self.lines.get_mut(self.row + i - 1).unwrap()) += line.len();
} else {
self.lines.insert(self.row + i - 1, line.len());
}
num_lines += 1;
last_line_len = line.len();
}
self.piece_table.add_text(text, self.pt_index);
if num_lines == 1 {
self.right(last_line_len).unwrap();
} else {
self.down(num_lines - 1).unwrap();
self.goto_col(last_line_len + 1).unwrap();
println!("{:?}", self.lines);
}
}
/// Read `num_lines` from `reader`, updating `self.piece_table` & `self.lines`
/// Returns number of lines actually read
fn read_lines(&mut self, num_lines: usize) -> usize {
if self.eof_reached {
// panic!("EOF already reached");
return 0;
}
let mut lines_read = 0;
@ -95,6 +126,7 @@ impl Editor {
/// Read to EOF, updating `self.piece_table` & `self.lines`
fn read_to_eof(&mut self) {
// Maybe use self.read_lines(usize::MAX) instead?
if self.eof_reached {
return;
}
@ -120,15 +152,14 @@ impl Editor {
if self.row == 1 || num >= self.row {
return Err("Can't go up".to_string());
}
// Update self.pt_index
// self.pt_index -= self.col;
self.pt_index -= self.col + 1;
for i in 1..num {
self.pt_index -= self.lines.get(self.row - i).unwrap();
self.pt_index -= self.lines.get(self.row - i).unwrap() + 1;
}
self.row -= num;
let line_cols = self.lines.get(self.row).unwrap();
let line_cols = self.lines.get(self.row - 1).unwrap();
self.col = min(self.col_want, line_cols + 1);
// self.pt_index -= line_cols - self.col;
self.pt_index -= line_cols + 1 - self.col;
Ok(())
}
@ -141,18 +172,24 @@ impl Editor {
self.lines.push(0);
}
}
self.pt_index += self.lines.get(self.row - 1).unwrap() + 1 - self.col + 1;
for i in 1..num {
self.pt_index += self.lines.get(self.row + i - 1).unwrap() + 1;
}
self.row += num;
self.col = min(self.col_want, self.lines.get(self.row).unwrap() + 1);
self.col = min(self.col_want, self.lines.get(self.row - 1).unwrap() + 1);
self.pt_index += self.col - 1;
Ok(())
}
/// Move the cursor right `num` places
pub(crate) fn right(&mut self, num: usize) -> Result<(), String> {
let line_cols = self.lines.get(self.row).unwrap() + 1;
let line_cols = self.lines.get(self.row - 1).unwrap() + 1;
if self.col + num > line_cols {
return Err("Can't go right".to_string());
}
self.col += num;
self.pt_index += num;
self.col_want = self.col;
Ok(())
}
@ -163,9 +200,40 @@ impl Editor {
return Err("Can't go left".to_string());
}
self.col -= num;
self.pt_index -= num;
self.col_want = self.col;
Ok(())
}
/// Move to a certain column in the current row
pub(crate) fn goto_col(&mut self, col: usize) -> Result<(), String> {
if col > *self.lines.get(self.row - 1).unwrap() + 1 {
return Err("col greater than columns in row".to_string());
}
if self.col == col {
Ok(())
} else if col < self.col {
self.left(self.col - col)
} else {
self.right(col - self.col)
}
}
/// Move to a certain row
pub(crate) fn goto_row(&mut self, row: usize) -> Result<(), String> {
if self.row == row {
Ok(())
} else if row < self.row {
self.up(self.row - row)
} else {
self.down(row - self.row)
}
}
/// Move to the last column in the current row
pub(crate) fn goto_last_col(&mut self) -> Result<(), String> {
self.goto_col(*self.lines.get(self.row - 1).unwrap())
}
}
#[cfg(test)]
@ -173,9 +241,69 @@ mod tests {
use super::*;
#[test]
fn empty_file() {
// let mut editor = Editor::new("".to_string());
fn add_text() {
let mut editor = Editor::new("".to_string());
let mut want_str = "hello";
editor.add_text(want_str.to_string());
assert_eq!(editor.text(), want_str);
editor = Editor::new("".to_string());
want_str = "hello\nbye";
editor.add_text(want_str.to_string());
assert_eq!(editor.text(), want_str);
editor = Editor::new("".to_string());
editor.add_text("hello\n".to_string());
editor.add_text("bye".to_string());
want_str = "hello\nbye";
assert_eq!(editor.text(), want_str);
editor = Editor::new("".to_string());
editor.add_text("hello\n\n".to_string());
editor.add_text("bye".to_string());
want_str = "hello\n\nbye";
assert_eq!(editor.text(), want_str);
}
fn movement() {
let mut editor = Editor::new("".to_string());
let mut want_str = "hello\nbye";
editor.add_text("hello".to_string());
editor.down(1).unwrap();
editor.add_text("bye".to_string());
assert_eq!(editor.text(), want_str);
editor = Editor::new("".to_string());
want_str = "hello\nbye";
editor.add_text("h".to_string());
editor.down(1).unwrap();
editor.add_text("bye".to_string());
editor.up(1).unwrap();
editor.add_text("ello".to_string());
assert_eq!(editor.text(), want_str);
editor = Editor::new("".to_string());
want_str = "ab\nabcd";
editor.add_text("ab".to_string());
editor.down(1).unwrap();
editor.add_text("abc".to_string());
editor.up(1).unwrap();
editor.down(1).unwrap();
editor.add_text("d".to_string());
assert_eq!(editor.text(), want_str);
editor = Editor::new("".to_string());
want_str = "abcde\na\n\na";
editor.add_text("acd".to_string());
editor.down(1).unwrap();
editor.add_text("a".to_string());
editor.up(1).unwrap();
editor.add_text("b".to_string());
editor.goto_last_col().unwrap();
editor.add_text("e".to_string());
editor.down(3).unwrap();
editor.add_text("a".to_string());
assert_eq!(editor.text(), want_str);
}
}

View File

@ -6,7 +6,7 @@ pub(crate) struct PieceTable {
/// The main table, contains `TableEntry`'s
table: Vec<TableEntry>,
/// Original buffer
pub(crate) original_buffer: String,
original_buffer: String,
/// Add buffer
add_buffer: String,
/// All active text. Only to be used when `text_up_to_date == true`
@ -458,11 +458,29 @@ mod tests {
assert_eq!(piece_table.text_len, want_str.len());
assert_eq!(piece_table.text(), want_str);
piece_table = PieceTable::new();
piece_table.add_text("\n\n\n\n".to_string(), 0);
want_str = "\n\n\n\n";
assert_eq!(want_str.len(), 4);
assert_eq!(piece_table.text_len, want_str.len());
assert_eq!(piece_table.text(), want_str);
// TODO: Add support for graphemes
// https://stackoverflow.com/a/46290728
piece_table = PieceTable::new();
piece_table.add_text("😀".to_string(), 0);
want_str = "😀";
assert_eq!(want_str.len(), 4);
// assert_eq!(want_str.graphemes(true).count(), 1);
assert_eq!(want_str.graphemes(true).count(), 1);
assert_eq!(piece_table.text_len, want_str.len());
assert_eq!(piece_table.text(), want_str);
piece_table = PieceTable::new();
piece_table.add_text("".to_string(), 0);
want_str = "";
assert_eq!(want_str.len(), 3);
assert_eq!(want_str.chars().count(), 2);
assert_eq!(want_str.graphemes(true).count(), 1);
assert_eq!(piece_table.text_len, want_str.len());
assert_eq!(piece_table.text(), want_str);
}