Finished converting codebase back to plain Rope's.

Everything appears to be working identically to how it was before converting
back.
This commit is contained in:
Nathan Vegdahl 2015-02-22 18:13:10 -08:00
parent fee6fc21a3
commit 9c462ee332
4 changed files with 295 additions and 11 deletions

View File

@ -37,6 +37,15 @@ impl Buffer {
} }
pub fn new_from_str(s: &str) -> Buffer {
Buffer {
text: Rope::new_from_str(s),
file_path: None,
undo_stack: UndoStack::new(),
}
}
pub fn new_from_file(path: &Path) -> IoResult<Buffer> { pub fn new_from_file(path: &Path) -> IoResult<Buffer> {
let mut f = BufferedReader::new(try!(File::open(path))); let mut f = BufferedReader::new(try!(File::open(path)));
let string = f.read_to_string().unwrap(); let string = f.read_to_string().unwrap();

View File

@ -47,7 +47,7 @@ pub trait LineFormatter {
let (line_block, col_i_adjusted) = block_index_and_offset(col_i); let (line_block, col_i_adjusted) = block_index_and_offset(col_i);
// Get an iter into the right block // Get an iter into the right block
let g_iter = line.grapheme_iter_between_indices(line_block * LINE_BLOCK_LENGTH, line_block * (LINE_BLOCK_LENGTH+1)); let g_iter = line.grapheme_iter_between_indices(line_block * LINE_BLOCK_LENGTH, (line_block+1) * LINE_BLOCK_LENGTH);
return self.index_to_v2d(g_iter, col_i_adjusted).1; return self.index_to_v2d(g_iter, col_i_adjusted).1;
} }
@ -64,7 +64,7 @@ pub trait LineFormatter {
// Find the right block in the line, and the index within that block // Find the right block in the line, and the index within that block
let (line_block, col_i_adjusted) = block_index_and_offset(col_i); let (line_block, col_i_adjusted) = block_index_and_offset(col_i);
let (mut y, x) = self.index_to_v2d(buf.get_line(line_i).grapheme_iter_between_indices(line_block*LINE_BLOCK_LENGTH, line_block*(LINE_BLOCK_LENGTH+1)), col_i_adjusted); let (mut y, x) = self.index_to_v2d(buf.get_line(line_i).grapheme_iter_between_indices(line_block * LINE_BLOCK_LENGTH, (line_block+1) * LINE_BLOCK_LENGTH), col_i_adjusted);
let mut new_y = y as isize + offset; let mut new_y = y as isize + offset;
// First, find the right line while keeping track of the vertical offset // First, find the right line while keeping track of the vertical offset
@ -72,7 +72,7 @@ pub trait LineFormatter {
let mut block_index: usize = line_block; let mut block_index: usize = line_block;
loop { loop {
line = buf.get_line(line_i); line = buf.get_line(line_i);
let (h, _) = self.dimensions(line.grapheme_iter_between_indices(line_block*LINE_BLOCK_LENGTH, line_block*(LINE_BLOCK_LENGTH+1))); let (h, _) = self.dimensions(line.grapheme_iter_between_indices(line_block * LINE_BLOCK_LENGTH, (line_block+1) * LINE_BLOCK_LENGTH));
if new_y >= 0 && new_y < h as isize { if new_y >= 0 && new_y < h as isize {
y = new_y as usize; y = new_y as usize;
@ -110,7 +110,7 @@ pub trait LineFormatter {
else { else {
block_index -= 1; block_index -= 1;
} }
let (h, _) = self.dimensions(line.grapheme_iter_between_indices(line_block*LINE_BLOCK_LENGTH, line_block*(LINE_BLOCK_LENGTH+1))); let (h, _) = self.dimensions(line.grapheme_iter_between_indices(line_block * LINE_BLOCK_LENGTH, (line_block+1) * LINE_BLOCK_LENGTH));
new_y += h as isize; new_y += h as isize;
} }
else { else {
@ -121,12 +121,15 @@ pub trait LineFormatter {
// Next, convert the resulting coordinates back into buffer-wide // Next, convert the resulting coordinates back into buffer-wide
// coordinates. // coordinates.
col_i = (block_index * LINE_BLOCK_LENGTH) + self.v2d_to_index(line.grapheme_iter_between_indices(line_block*LINE_BLOCK_LENGTH, line_block*(LINE_BLOCK_LENGTH+1)), (y, x), rounding); col_i = (block_index * LINE_BLOCK_LENGTH) + self.v2d_to_index(line.grapheme_iter_between_indices(line_block * LINE_BLOCK_LENGTH, (line_block+1) * LINE_BLOCK_LENGTH), (y, x), rounding);
return buf.line_col_to_index((line_i, col_i)); return buf.line_col_to_index((line_i, col_i));
} }
/// Takes a grapheme index and a desired visual horizontal position, and
/// returns a grapheme index on the same visual line as the given index,
/// but offset to have the desired horizontal position.
fn index_set_horizontal_v2d(&self, buf: &Buffer, index: usize, horizontal: usize, rounding: RoundingBehavior) -> usize { fn index_set_horizontal_v2d(&self, buf: &Buffer, index: usize, horizontal: usize, rounding: RoundingBehavior) -> usize {
let (line_i, col_i) = buf.index_to_line_col(index); let (line_i, col_i) = buf.index_to_line_col(index);
let line = buf.get_line(line_i); let line = buf.get_line(line_i);

View File

@ -83,6 +83,7 @@ impl LineFormatter for ConsoleLineFormatter {
for (_, pos, _) in self.iter(g_iter) { for (_, pos, _) in self.iter(g_iter) {
if pos.0 > v2d.0 { if pos.0 > v2d.0 {
i -= 1;
break; break;
} }
else if pos.0 == v2d.0 && pos.1 >= v2d.1 { else if pos.0 == v2d.0 && pos.1 >= v2d.1 {
@ -162,3 +163,279 @@ fn grapheme_vis_width_at_vis_pos(g: &str, pos: usize, tab_width: usize) -> usize
} }
} }
} }
#[cfg(test)]
mod tests {
#![allow(unused_imports)]
use super::*;
use formatter::LineFormatter;
use formatter::RoundingBehavior::{Round, Floor, Ceiling};
use buffer::Buffer;
#[test]
fn dimensions_1() {
let text = "Hello there, stranger!"; // 22 graphemes long
let mut f = ConsoleLineFormatter::new(4);
f.wrap_width = 80;
assert_eq!(f.dimensions(text.graphemes(true)), (1, 22));
}
#[test]
fn dimensions_2() {
let text = "Hello there, stranger! How are you doing this fine day?"; // 56 graphemes long
let mut f = ConsoleLineFormatter::new(4);
f.wrap_width = 12;
assert_eq!(f.dimensions(text.graphemes(true)), (5, 12));
}
#[test]
fn index_to_v2d_1() {
let text = "Hello there, stranger!"; // 22 graphemes long
let mut f = ConsoleLineFormatter::new(4);
f.wrap_width = 80;
assert_eq!(f.index_to_v2d(text.graphemes(true), 0), (0, 0));
assert_eq!(f.index_to_v2d(text.graphemes(true), 5), (0, 5));
assert_eq!(f.index_to_v2d(text.graphemes(true), 22), (0, 22));
assert_eq!(f.index_to_v2d(text.graphemes(true), 23), (0, 22));
}
#[test]
fn index_to_v2d_2() {
let text = "Hello there, stranger! How are you doing this fine day?"; // 56 graphemes long
let mut f = ConsoleLineFormatter::new(4);
f.wrap_width = 12;
assert_eq!(f.index_to_v2d(text.graphemes(true), 0), (0, 0));
assert_eq!(f.index_to_v2d(text.graphemes(true), 5), (0, 5));
assert_eq!(f.index_to_v2d(text.graphemes(true), 11), (0, 11));
assert_eq!(f.index_to_v2d(text.graphemes(true), 12), (1, 0));
assert_eq!(f.index_to_v2d(text.graphemes(true), 15), (1, 3));
assert_eq!(f.index_to_v2d(text.graphemes(true), 23), (1, 11));
assert_eq!(f.index_to_v2d(text.graphemes(true), 24), (2, 0));
assert_eq!(f.index_to_v2d(text.graphemes(true), 28), (2, 4));
assert_eq!(f.index_to_v2d(text.graphemes(true), 35), (2, 11));
assert_eq!(f.index_to_v2d(text.graphemes(true), 36), (3, 0));
assert_eq!(f.index_to_v2d(text.graphemes(true), 43), (3, 7));
assert_eq!(f.index_to_v2d(text.graphemes(true), 47), (3, 11));
assert_eq!(f.index_to_v2d(text.graphemes(true), 48), (4, 0));
assert_eq!(f.index_to_v2d(text.graphemes(true), 50), (4, 2));
assert_eq!(f.index_to_v2d(text.graphemes(true), 56), (4, 8));
assert_eq!(f.index_to_v2d(text.graphemes(true), 57), (4, 8));
}
#[test]
fn v2d_to_index_1() {
let text = "Hello there, stranger!"; // 22 graphemes long
let mut f = ConsoleLineFormatter::new(4);
f.wrap_width = 80;
assert_eq!(f.v2d_to_index(text.graphemes(true), (0,0), (Floor, Floor)), 0);
assert_eq!(f.v2d_to_index(text.graphemes(true), (0,5), (Floor, Floor)), 5);
assert_eq!(f.v2d_to_index(text.graphemes(true), (0,22), (Floor, Floor)), 22);
assert_eq!(f.v2d_to_index(text.graphemes(true), (0,23), (Floor, Floor)), 22);
assert_eq!(f.v2d_to_index(text.graphemes(true), (1,0), (Floor, Floor)), 22);
assert_eq!(f.v2d_to_index(text.graphemes(true), (1,1), (Floor, Floor)), 22);
}
#[test]
fn v2d_to_index_2() {
let text = "Hello there, stranger! How are you doing this fine day?"; // 56 graphemes long
let mut f = ConsoleLineFormatter::new(4);
f.wrap_width = 12;
assert_eq!(f.v2d_to_index(text.graphemes(true), (0,0), (Floor, Floor)), 0);
assert_eq!(f.v2d_to_index(text.graphemes(true), (0,11), (Floor, Floor)), 11);
assert_eq!(f.v2d_to_index(text.graphemes(true), (0,12), (Floor, Floor)), 11);
assert_eq!(f.v2d_to_index(text.graphemes(true), (1,0), (Floor, Floor)), 12);
assert_eq!(f.v2d_to_index(text.graphemes(true), (1,11), (Floor, Floor)), 23);
assert_eq!(f.v2d_to_index(text.graphemes(true), (1,12), (Floor, Floor)), 23);
assert_eq!(f.v2d_to_index(text.graphemes(true), (2,0), (Floor, Floor)), 24);
assert_eq!(f.v2d_to_index(text.graphemes(true), (2,11), (Floor, Floor)), 35);
assert_eq!(f.v2d_to_index(text.graphemes(true), (2,12), (Floor, Floor)), 35);
assert_eq!(f.v2d_to_index(text.graphemes(true), (3,0), (Floor, Floor)), 36);
assert_eq!(f.v2d_to_index(text.graphemes(true), (3,11), (Floor, Floor)), 47);
assert_eq!(f.v2d_to_index(text.graphemes(true), (3,12), (Floor, Floor)), 47);
assert_eq!(f.v2d_to_index(text.graphemes(true), (4,0), (Floor, Floor)), 48);
assert_eq!(f.v2d_to_index(text.graphemes(true), (4,7), (Floor, Floor)), 55);
assert_eq!(f.v2d_to_index(text.graphemes(true), (4,8), (Floor, Floor)), 56);
assert_eq!(f.v2d_to_index(text.graphemes(true), (4,9), (Floor, Floor)), 56);
}
#[test]
fn index_to_horizontal_v2d_1() {
let b = Buffer::new_from_str("Hello there, stranger!\nHow are you doing this fine day?"); // 55 graphemes long
let mut f = ConsoleLineFormatter::new(4);
f.wrap_width = 80;
assert_eq!(f.index_to_horizontal_v2d(&b, 0), 0);
assert_eq!(f.index_to_horizontal_v2d(&b, 5), 5);
assert_eq!(f.index_to_horizontal_v2d(&b, 26), 3);
assert_eq!(f.index_to_horizontal_v2d(&b, 55), 32);
assert_eq!(f.index_to_horizontal_v2d(&b, 56), 32);
}
#[test]
fn index_to_horizontal_v2d_2() {
let b = Buffer::new_from_str("Hello there, stranger!\nHow are you doing this fine day?"); // 55 graphemes long
let mut f = ConsoleLineFormatter::new(4);
f.wrap_width = 12;
assert_eq!(f.index_to_horizontal_v2d(&b, 0), 0);
assert_eq!(f.index_to_horizontal_v2d(&b, 11), 11);
assert_eq!(f.index_to_horizontal_v2d(&b, 12), 0);
assert_eq!(f.index_to_horizontal_v2d(&b, 22), 10);
assert_eq!(f.index_to_horizontal_v2d(&b, 23), 0);
assert_eq!(f.index_to_horizontal_v2d(&b, 34), 11);
assert_eq!(f.index_to_horizontal_v2d(&b, 35), 0);
assert_eq!(f.index_to_horizontal_v2d(&b, 46), 11);
assert_eq!(f.index_to_horizontal_v2d(&b, 47), 0);
assert_eq!(f.index_to_horizontal_v2d(&b, 55), 8);
assert_eq!(f.index_to_horizontal_v2d(&b, 56), 8);
}
#[test]
fn index_set_horizontal_v2d_1() {
let b = Buffer::new_from_str("Hello there, stranger!\nHow are you doing this fine day?"); // 55 graphemes long
let mut f = ConsoleLineFormatter::new(4);
f.wrap_width = 80;
assert_eq!(f.index_set_horizontal_v2d(&b, 0, 0, Floor), 0);
assert_eq!(f.index_set_horizontal_v2d(&b, 0, 22, Floor), 22);
assert_eq!(f.index_set_horizontal_v2d(&b, 0, 23, Floor), 22);
assert_eq!(f.index_set_horizontal_v2d(&b, 8, 0, Floor), 0);
assert_eq!(f.index_set_horizontal_v2d(&b, 8, 22, Floor), 22);
assert_eq!(f.index_set_horizontal_v2d(&b, 8, 23, Floor), 22);
assert_eq!(f.index_set_horizontal_v2d(&b, 22, 0, Floor), 0);
assert_eq!(f.index_set_horizontal_v2d(&b, 22, 22, Floor), 22);
assert_eq!(f.index_set_horizontal_v2d(&b, 22, 23, Floor), 22);
assert_eq!(f.index_set_horizontal_v2d(&b, 23, 0, Floor), 23);
assert_eq!(f.index_set_horizontal_v2d(&b, 23, 32, Floor), 55);
assert_eq!(f.index_set_horizontal_v2d(&b, 23, 33, Floor), 55);
assert_eq!(f.index_set_horizontal_v2d(&b, 28, 0, Floor), 23);
assert_eq!(f.index_set_horizontal_v2d(&b, 28, 32, Floor), 55);
assert_eq!(f.index_set_horizontal_v2d(&b, 28, 33, Floor), 55);
assert_eq!(f.index_set_horizontal_v2d(&b, 55, 0, Floor), 23);
assert_eq!(f.index_set_horizontal_v2d(&b, 55, 32, Floor), 55);
assert_eq!(f.index_set_horizontal_v2d(&b, 55, 33, Floor), 55);
}
#[test]
fn index_set_horizontal_v2d_2() {
let b = Buffer::new_from_str("Hello there, stranger! How are you doing this fine day?"); // 55 graphemes long
let mut f = ConsoleLineFormatter::new(4);
f.wrap_width = 12;
assert_eq!(f.index_set_horizontal_v2d(&b, 0, 0, Floor), 0);
assert_eq!(f.index_set_horizontal_v2d(&b, 0, 11, Floor), 11);
assert_eq!(f.index_set_horizontal_v2d(&b, 0, 12, Floor), 11);
assert_eq!(f.index_set_horizontal_v2d(&b, 8, 0, Floor), 0);
assert_eq!(f.index_set_horizontal_v2d(&b, 8, 11, Floor), 11);
assert_eq!(f.index_set_horizontal_v2d(&b, 8, 12, Floor), 11);
assert_eq!(f.index_set_horizontal_v2d(&b, 11, 0, Floor), 0);
assert_eq!(f.index_set_horizontal_v2d(&b, 11, 11, Floor), 11);
assert_eq!(f.index_set_horizontal_v2d(&b, 11, 12, Floor), 11);
assert_eq!(f.index_set_horizontal_v2d(&b, 12, 0, Floor), 12);
assert_eq!(f.index_set_horizontal_v2d(&b, 12, 11, Floor), 23);
assert_eq!(f.index_set_horizontal_v2d(&b, 12, 12, Floor), 23);
assert_eq!(f.index_set_horizontal_v2d(&b, 17, 0, Floor), 12);
assert_eq!(f.index_set_horizontal_v2d(&b, 17, 11, Floor), 23);
assert_eq!(f.index_set_horizontal_v2d(&b, 17, 12, Floor), 23);
assert_eq!(f.index_set_horizontal_v2d(&b, 23, 0, Floor), 12);
assert_eq!(f.index_set_horizontal_v2d(&b, 23, 11, Floor), 23);
assert_eq!(f.index_set_horizontal_v2d(&b, 23, 12, Floor), 23);
}
#[test]
fn index_offset_vertical_v2d_1() {
let b = Buffer::new_from_str("Hello there, stranger!\nHow are you doing this fine day?"); // 55 graphemes long
let mut f = ConsoleLineFormatter::new(4);
f.wrap_width = 80;
assert_eq!(f.index_offset_vertical_v2d(&b, 0, 0, (Floor, Floor)), 0);
assert_eq!(f.index_offset_vertical_v2d(&b, 0, 1, (Floor, Floor)), 23);
assert_eq!(f.index_offset_vertical_v2d(&b, 23, -1, (Floor, Floor)), 0);
assert_eq!(f.index_offset_vertical_v2d(&b, 2, 0, (Floor, Floor)), 2);
assert_eq!(f.index_offset_vertical_v2d(&b, 2, 1, (Floor, Floor)), 25);
assert_eq!(f.index_offset_vertical_v2d(&b, 25, -1, (Floor, Floor)), 2);
assert_eq!(f.index_offset_vertical_v2d(&b, 22, 0, (Floor, Floor)), 22);
assert_eq!(f.index_offset_vertical_v2d(&b, 22, 1, (Floor, Floor)), 45);
assert_eq!(f.index_offset_vertical_v2d(&b, 45, -1, (Floor, Floor)), 22);
assert_eq!(f.index_offset_vertical_v2d(&b, 54, 0, (Floor, Floor)), 54);
assert_eq!(f.index_offset_vertical_v2d(&b, 54, 1, (Floor, Floor)), 55);
assert_eq!(f.index_offset_vertical_v2d(&b, 54, -1, (Floor, Floor)), 22);
}
#[test]
fn index_offset_vertical_v2d_2() {
let b = Buffer::new_from_str("Hello there, stranger! How are you doing this fine day?"); // 55 graphemes long
let mut f = ConsoleLineFormatter::new(4);
f.wrap_width = 12;
assert_eq!(f.index_offset_vertical_v2d(&b, 0, 0, (Floor, Floor)), 0);
assert_eq!(f.index_offset_vertical_v2d(&b, 0, 1, (Floor, Floor)), 12);
assert_eq!(f.index_offset_vertical_v2d(&b, 0, 2, (Floor, Floor)), 24);
assert_eq!(f.index_offset_vertical_v2d(&b, 0, 0, (Floor, Floor)), 0);
assert_eq!(f.index_offset_vertical_v2d(&b, 12, -1, (Floor, Floor)), 0);
assert_eq!(f.index_offset_vertical_v2d(&b, 24, -2, (Floor, Floor)), 0);
assert_eq!(f.index_offset_vertical_v2d(&b, 4, 0, (Floor, Floor)), 4);
assert_eq!(f.index_offset_vertical_v2d(&b, 4, 1, (Floor, Floor)), 16);
assert_eq!(f.index_offset_vertical_v2d(&b, 4, 2, (Floor, Floor)), 28);
assert_eq!(f.index_offset_vertical_v2d(&b, 4, 0, (Floor, Floor)), 4);
assert_eq!(f.index_offset_vertical_v2d(&b, 16, -1, (Floor, Floor)), 4);
assert_eq!(f.index_offset_vertical_v2d(&b, 28, -2, (Floor, Floor)), 4);
assert_eq!(f.index_offset_vertical_v2d(&b, 11, 0, (Floor, Floor)), 11);
assert_eq!(f.index_offset_vertical_v2d(&b, 11, 1, (Floor, Floor)), 23);
assert_eq!(f.index_offset_vertical_v2d(&b, 11, 2, (Floor, Floor)), 35);
assert_eq!(f.index_offset_vertical_v2d(&b, 11, 0, (Floor, Floor)), 11);
assert_eq!(f.index_offset_vertical_v2d(&b, 23, -1, (Floor, Floor)), 11);
assert_eq!(f.index_offset_vertical_v2d(&b, 35, -2, (Floor, Floor)), 11);
}
}

View File

@ -15,11 +15,6 @@
- Loading/saving code for different encodings. - Loading/saving code for different encodings.
- Auto-detecting text encodings from file data (this one will be tricky). - Auto-detecting text encodings from file data (this one will be tricky).
- Switch back to using a Rope directly, instead of using a tree of lines.
The code for everything is sufficiently clear now that doing this shouldn't
be difficult, as the needed API's are pretty obvious. And then we have
fewer moving parts. Yay!
- Word wrap. - Word wrap.
- Get non-wrapping text working again. - Get non-wrapping text working again.
- File opening by entering path - File opening by entering path