mirror of https://github.com/andrewkdinh/via.git
Able to add text and move around in editor now
This commit is contained in:
parent
57113c6b9d
commit
277fe8092f
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue