Reorganized the code a bit, and started updating unit tests.
This commit is contained in:
parent
518b9a7e42
commit
0557f5f6ce
61
src/buffer/line_formatter.rs
Normal file
61
src/buffer/line_formatter.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
use buffer::line::Line;
|
||||||
|
use std::cmp::min;
|
||||||
|
|
||||||
|
#[derive(Copy, PartialEq)]
|
||||||
|
pub enum RoundingBehavior {
|
||||||
|
Round,
|
||||||
|
Floor,
|
||||||
|
Ceiling,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub trait LineFormatter {
|
||||||
|
fn single_line_height(&self) -> usize;
|
||||||
|
|
||||||
|
fn dimensions(&self, line: &Line) -> (usize, usize);
|
||||||
|
|
||||||
|
fn index_to_v2d(&self, line: &Line, index: usize) -> (usize, usize);
|
||||||
|
|
||||||
|
fn v2d_to_index(&self, line: &Line, v2d: (usize, usize), rounding: (RoundingBehavior, RoundingBehavior)) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================================================================
|
||||||
|
// A simple implementation of LineFormatter, for testing purposes
|
||||||
|
//================================================================
|
||||||
|
|
||||||
|
pub struct TestLineFormatter {
|
||||||
|
tab_width: u8
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestLineFormatter {
|
||||||
|
pub fn new() -> TestLineFormatter {
|
||||||
|
TestLineFormatter {
|
||||||
|
tab_width: 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LineFormatter for TestLineFormatter {
|
||||||
|
fn single_line_height(&self) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dimensions(&self, line: &Line) -> (usize, usize) {
|
||||||
|
(1, line.grapheme_count())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn index_to_v2d(&self, line: &Line, index: usize) -> (usize, usize) {
|
||||||
|
(0, min(line.grapheme_count(), index))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn v2d_to_index(&self, line: &Line, v2d: (usize, usize), rounding: (RoundingBehavior, RoundingBehavior)) -> usize {
|
||||||
|
if v2d.0 > 0 {
|
||||||
|
line.grapheme_count()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
min(line.grapheme_count(), v2d.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,10 +6,11 @@ use self::line::{Line, LineEnding};
|
||||||
use self::node::{BufferNode, BufferNodeGraphemeIter, BufferNodeLineIter};
|
use self::node::{BufferNode, BufferNodeGraphemeIter, BufferNodeLineIter};
|
||||||
use self::undo_stack::{UndoStack};
|
use self::undo_stack::{UndoStack};
|
||||||
use self::undo_stack::Operation::*;
|
use self::undo_stack::Operation::*;
|
||||||
use line_formatter::{LineFormatter, RoundingBehavior};
|
use self::line_formatter::{LineFormatter, RoundingBehavior};
|
||||||
use string_utils::{is_line_ending, grapheme_count};
|
use string_utils::{is_line_ending, grapheme_count};
|
||||||
|
|
||||||
pub mod line;
|
pub mod line;
|
||||||
|
pub mod line_formatter;
|
||||||
mod node;
|
mod node;
|
||||||
mod undo_stack;
|
mod undo_stack;
|
||||||
|
|
||||||
|
@ -503,11 +504,12 @@ impl<'a> Iterator for BufferLineIter<'a> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::line_formatter::TestLineFormatter;
|
||||||
use super::{Buffer, BufferGraphemeIter, BufferLineIter};
|
use super::{Buffer, BufferGraphemeIter, BufferLineIter};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_text() {
|
fn insert_text() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hello 世界!", 0);
|
buf.insert_text("Hello 世界!", 0);
|
||||||
|
|
||||||
|
@ -530,7 +532,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_text_with_newlines() {
|
fn insert_text_with_newlines() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hello\n 世界\r\n!", 0);
|
buf.insert_text("Hello\n 世界\r\n!", 0);
|
||||||
|
|
||||||
|
@ -555,7 +557,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_text_in_non_empty_buffer_1() {
|
fn insert_text_in_non_empty_buffer_1() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hello\n 世界\r\n!", 0);
|
buf.insert_text("Hello\n 世界\r\n!", 0);
|
||||||
buf.insert_text("Again ", 0);
|
buf.insert_text("Again ", 0);
|
||||||
|
@ -587,7 +589,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_text_in_non_empty_buffer_2() {
|
fn insert_text_in_non_empty_buffer_2() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hello\n 世界\r\n!", 0);
|
buf.insert_text("Hello\n 世界\r\n!", 0);
|
||||||
buf.insert_text(" again", 5);
|
buf.insert_text(" again", 5);
|
||||||
|
@ -619,7 +621,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_text_in_non_empty_buffer_3() {
|
fn insert_text_in_non_empty_buffer_3() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hello\n 世界\r\n!", 0);
|
buf.insert_text("Hello\n 世界\r\n!", 0);
|
||||||
buf.insert_text("again", 6);
|
buf.insert_text("again", 6);
|
||||||
|
@ -650,7 +652,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_text_in_non_empty_buffer_4() {
|
fn insert_text_in_non_empty_buffer_4() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hello\n 世界\r\n!", 0);
|
buf.insert_text("Hello\n 世界\r\n!", 0);
|
||||||
buf.insert_text("again", 11);
|
buf.insert_text("again", 11);
|
||||||
|
@ -681,7 +683,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_text_in_non_empty_buffer_5() {
|
fn insert_text_in_non_empty_buffer_5() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hello\n 世界\r\n!", 0);
|
buf.insert_text("Hello\n 世界\r\n!", 0);
|
||||||
buf.insert_text("again", 2);
|
buf.insert_text("again", 2);
|
||||||
|
@ -713,7 +715,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_text_in_non_empty_buffer_6() {
|
fn insert_text_in_non_empty_buffer_6() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hello\n 世界\r\n!", 0);
|
buf.insert_text("Hello\n 世界\r\n!", 0);
|
||||||
buf.insert_text("again", 8);
|
buf.insert_text("again", 8);
|
||||||
|
@ -745,7 +747,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn insert_text_in_non_empty_buffer_7() {
|
fn insert_text_in_non_empty_buffer_7() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hello\n 世界\r\n!", 0);
|
buf.insert_text("Hello\n 世界\r\n!", 0);
|
||||||
buf.insert_text("\nag\n\nain\n", 2);
|
buf.insert_text("\nag\n\nain\n", 2);
|
||||||
|
@ -781,7 +783,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_text_1() {
|
fn remove_text_1() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
|
@ -825,7 +827,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_text_2() {
|
fn remove_text_2() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
|
@ -860,7 +862,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_text_3() {
|
fn remove_text_3() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
|
@ -895,7 +897,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_text_4() {
|
fn remove_text_4() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
|
@ -936,7 +938,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_text_5() {
|
fn remove_text_5() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
|
@ -971,7 +973,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_text_6() {
|
fn remove_text_6() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hello\nworld!", 0);
|
buf.insert_text("Hello\nworld!", 0);
|
||||||
assert!(buf.grapheme_count() == 12);
|
assert!(buf.grapheme_count() == 12);
|
||||||
|
@ -992,7 +994,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_text_7() {
|
fn remove_text_7() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\nworld!", 0);
|
buf.insert_text("Hi\nthere\nworld!", 0);
|
||||||
assert!(buf.grapheme_count() == 15);
|
assert!(buf.grapheme_count() == 15);
|
||||||
|
@ -1015,7 +1017,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_text_8() {
|
fn remove_text_8() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hello\nworld!", 0);
|
buf.insert_text("Hello\nworld!", 0);
|
||||||
assert!(buf.grapheme_count() == 12);
|
assert!(buf.grapheme_count() == 12);
|
||||||
|
@ -1037,7 +1039,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_text_9() {
|
fn remove_text_9() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hello\nworld!", 0);
|
buf.insert_text("Hello\nworld!", 0);
|
||||||
assert!(buf.grapheme_count() == 12);
|
assert!(buf.grapheme_count() == 12);
|
||||||
|
@ -1063,7 +1065,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_text_10() {
|
fn remove_text_10() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("12\n34\n56\n78", 0);
|
buf.insert_text("12\n34\n56\n78", 0);
|
||||||
assert!(buf.grapheme_count() == 11);
|
assert!(buf.grapheme_count() == 11);
|
||||||
|
@ -1085,7 +1087,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_text_11() {
|
fn remove_text_11() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("1234567890", 0);
|
buf.insert_text("1234567890", 0);
|
||||||
assert!(buf.grapheme_count() == 10);
|
assert!(buf.grapheme_count() == 10);
|
||||||
|
@ -1112,7 +1114,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn move_text_1() {
|
fn move_text_1() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
|
@ -1157,7 +1159,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn move_text_2() {
|
fn move_text_2() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
|
@ -1202,7 +1204,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn move_text_3() {
|
fn move_text_3() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
|
@ -1247,7 +1249,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn move_text_4() {
|
fn move_text_4() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
|
@ -1292,7 +1294,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn move_text_5() {
|
fn move_text_5() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
|
@ -1337,7 +1339,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_lines_1() {
|
fn remove_lines_1() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
|
@ -1368,7 +1370,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_lines_2() {
|
fn remove_lines_2() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
|
@ -1399,7 +1401,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn remove_lines_3() {
|
fn remove_lines_3() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
|
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
assert!(buf.grapheme_count() == 29);
|
assert!(buf.grapheme_count() == 29);
|
||||||
|
@ -1432,7 +1434,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn line_col_to_index_1() {
|
fn line_col_to_index_1() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
let pos = buf.line_col_to_index((2, 3));
|
let pos = buf.line_col_to_index((2, 3));
|
||||||
|
@ -1443,7 +1445,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn line_col_to_index_2() {
|
fn line_col_to_index_2() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
let pos = buf.line_col_to_index((2, 10));
|
let pos = buf.line_col_to_index((2, 10));
|
||||||
|
@ -1453,7 +1455,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn line_col_to_index_3() {
|
fn line_col_to_index_3() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
let pos = buf.line_col_to_index((10, 2));
|
let pos = buf.line_col_to_index((10, 2));
|
||||||
|
@ -1464,7 +1466,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn index_to_line_col_1() {
|
fn index_to_line_col_1() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
let pos = buf.index_to_line_col(5);
|
let pos = buf.index_to_line_col(5);
|
||||||
|
@ -1475,7 +1477,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn index_to_line_col_2() {
|
fn index_to_line_col_2() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
let pos = buf.index_to_line_col(50);
|
let pos = buf.index_to_line_col(50);
|
||||||
|
@ -1486,7 +1488,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_from_range_1() {
|
fn string_from_range_1() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
let s = buf.string_from_range(1, 12);
|
let s = buf.string_from_range(1, 12);
|
||||||
|
@ -1497,7 +1499,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_from_range_2() {
|
fn string_from_range_2() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
let s = buf.string_from_range(0, 29);
|
let s = buf.string_from_range(0, 29);
|
||||||
|
@ -1508,7 +1510,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn grapheme_iter_at_index_1() {
|
fn grapheme_iter_at_index_1() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter_at_index(16);
|
let mut iter = buf.grapheme_iter_at_index(16);
|
||||||
|
@ -1532,7 +1534,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn grapheme_iter_at_index_2() {
|
fn grapheme_iter_at_index_2() {
|
||||||
let mut buf = Buffer::new();
|
let mut buf = Buffer::new(TestLineFormatter::new());
|
||||||
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
buf.insert_text("Hi\nthere\npeople\nof\nthe\nworld!", 0);
|
||||||
|
|
||||||
let mut iter = buf.grapheme_iter_at_index(29);
|
let mut iter = buf.grapheme_iter_at_index(29);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::cmp::{min, max};
|
use std::cmp::{min, max};
|
||||||
|
|
||||||
use line_formatter::{LineFormatter, RoundingBehavior};
|
use super::line_formatter::{LineFormatter, RoundingBehavior};
|
||||||
use string_utils::is_line_ending;
|
use string_utils::is_line_ending;
|
||||||
use super::line::{Line, LineEnding, LineGraphemeIter, str_to_line_ending};
|
use super::line::{Line, LineEnding, LineGraphemeIter, str_to_line_ending};
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::ops::{Index, IndexMut};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use buffer::Buffer;
|
use buffer::Buffer;
|
||||||
use line_formatter::LineFormatter;
|
use buffer::line_formatter::LineFormatter;
|
||||||
|
|
||||||
/// A text cursor. Also represents selections when range.0 != range.1.
|
/// A text cursor. Also represents selections when range.0 != range.1.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use buffer::Buffer;
|
use buffer::Buffer;
|
||||||
use line_formatter::{LineFormatter, ConsoleLineFormatter};
|
use buffer::line_formatter::LineFormatter;
|
||||||
use line_formatter::RoundingBehavior::*;
|
use buffer::line_formatter::RoundingBehavior::*;
|
||||||
|
use term_ui::formatter::ConsoleLineFormatter;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use files::{load_file_to_buffer, save_buffer_to_file};
|
use files::{load_file_to_buffer, save_buffer_to_file};
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::io::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use buffer::line::{Line, LineEnding, line_ending_to_str};
|
use buffer::line::{Line, LineEnding, line_ending_to_str};
|
||||||
use line_formatter::LineFormatter;
|
use buffer::line_formatter::LineFormatter;
|
||||||
use buffer::Buffer as TextBuffer;
|
use buffer::Buffer as TextBuffer;
|
||||||
|
|
||||||
pub fn load_file_to_buffer<T: LineFormatter>(path: &Path, lf: T) -> IoResult<TextBuffer<T>> {
|
pub fn load_file_to_buffer<T: LineFormatter>(path: &Path, lf: T) -> IoResult<TextBuffer<T>> {
|
||||||
|
|
21
src/main.rs
21
src/main.rs
|
@ -14,7 +14,6 @@ use term_ui::TermUI;
|
||||||
|
|
||||||
mod string_utils;
|
mod string_utils;
|
||||||
mod buffer;
|
mod buffer;
|
||||||
mod line_formatter;
|
|
||||||
mod files;
|
mod files;
|
||||||
mod editor;
|
mod editor;
|
||||||
mod term_ui;
|
mod term_ui;
|
||||||
|
@ -59,18 +58,16 @@ fn main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize and start UI
|
// Initialize and start UI
|
||||||
// if args.flag_gui {
|
//if args.flag_gui {
|
||||||
// // GUI
|
// // GUI
|
||||||
// sdl2::init(sdl2::INIT_VIDEO);
|
// sdl2::init(sdl2::INIT_VIDEO);
|
||||||
// let mut ui = GUI::new_from_editor(editor);
|
// let mut ui = GUI::new_from_editor(editor);
|
||||||
// ui.main_ui_loop();
|
// ui.main_ui_loop();
|
||||||
// sdl2::quit();
|
// sdl2::quit();
|
||||||
// }
|
//}
|
||||||
// else {
|
//else {
|
||||||
// Console UI
|
// Console UI
|
||||||
let mut ui = TermUI::new_from_editor(editor);
|
let mut ui = TermUI::new_from_editor(editor);
|
||||||
ui.main_ui_loop();
|
ui.main_ui_loop();
|
||||||
// }
|
//}
|
||||||
|
|
||||||
//println!("{}", editor.buffer.root.tree_height);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +1,10 @@
|
||||||
use buffer::line::{Line, LineGraphemeIter};
|
|
||||||
use string_utils::{is_line_ending};
|
use string_utils::{is_line_ending};
|
||||||
|
use buffer::line::{Line, LineGraphemeIter};
|
||||||
|
use buffer::line_formatter::{LineFormatter, RoundingBehavior};
|
||||||
|
|
||||||
#[derive(Copy, PartialEq)]
|
//===================================================================
|
||||||
pub enum RoundingBehavior {
|
// LineFormatter implementation for terminals/consoles.
|
||||||
Round,
|
//===================================================================
|
||||||
Floor,
|
|
||||||
Ceiling,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait LineFormatter {
|
|
||||||
fn single_line_height(&self) -> usize;
|
|
||||||
|
|
||||||
fn dimensions(&self, line: &Line) -> (usize, usize);
|
|
||||||
|
|
||||||
fn index_to_v2d(&self, line: &Line, index: usize) -> (usize, usize);
|
|
||||||
|
|
||||||
fn v2d_to_index(&self, line: &Line, v2d: (usize, usize), rounding: (RoundingBehavior, RoundingBehavior)) -> usize;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
|
||||||
// An implementation of the LineFormatter stuff for consoles
|
|
||||||
|
|
||||||
pub struct ConsoleLineFormatterVisIter<'a> {
|
|
||||||
grapheme_iter: LineGraphemeIter<'a>,
|
|
||||||
f: &'a ConsoleLineFormatter,
|
|
||||||
pos: (usize, usize),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl<'a> Iterator for ConsoleLineFormatterVisIter<'a> {
|
|
||||||
type Item = (&'a str, (usize, usize), usize);
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<(&'a str, (usize, usize), usize)> {
|
|
||||||
if let Some(g) = self.grapheme_iter.next() {
|
|
||||||
let pos = self.pos;
|
|
||||||
|
|
||||||
let width = grapheme_vis_width_at_vis_pos(g, self.pos.1, self.f.tab_width as usize);
|
|
||||||
self.pos = (self.pos.0, self.pos.1 + width);
|
|
||||||
|
|
||||||
return Some((g, (pos.0, pos.1), width));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub struct ConsoleLineFormatter {
|
pub struct ConsoleLineFormatter {
|
||||||
pub tab_width: u8,
|
pub tab_width: u8,
|
||||||
|
@ -147,6 +101,41 @@ impl<'a> LineFormatter for ConsoleLineFormatter {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===================================================================
|
||||||
|
// An iterator that iterates over the graphemes in a line in a
|
||||||
|
// manner consistent with the ConsoleFormatter.
|
||||||
|
//===================================================================
|
||||||
|
pub struct ConsoleLineFormatterVisIter<'a> {
|
||||||
|
grapheme_iter: LineGraphemeIter<'a>,
|
||||||
|
f: &'a ConsoleLineFormatter,
|
||||||
|
pos: (usize, usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
impl<'a> Iterator for ConsoleLineFormatterVisIter<'a> {
|
||||||
|
type Item = (&'a str, (usize, usize), usize);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<(&'a str, (usize, usize), usize)> {
|
||||||
|
if let Some(g) = self.grapheme_iter.next() {
|
||||||
|
let pos = self.pos;
|
||||||
|
|
||||||
|
let width = grapheme_vis_width_at_vis_pos(g, self.pos.1, self.f.tab_width as usize);
|
||||||
|
self.pos = (self.pos.0, self.pos.1 + width);
|
||||||
|
|
||||||
|
return Some((g, (pos.0, pos.1), width));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================================================================
|
||||||
|
// Helper functions
|
||||||
|
//===================================================================
|
||||||
|
|
||||||
/// Returns the visual width of a grapheme given a starting
|
/// Returns the visual width of a grapheme given a starting
|
||||||
/// position on a line.
|
/// position on a line.
|
|
@ -7,7 +7,9 @@ use std::char;
|
||||||
use std::time::duration::Duration;
|
use std::time::duration::Duration;
|
||||||
use string_utils::{is_line_ending};
|
use string_utils::{is_line_ending};
|
||||||
use buffer::line::{line_ending_to_str, LineEnding};
|
use buffer::line::{line_ending_to_str, LineEnding};
|
||||||
use line_formatter::{LineFormatter, RoundingBehavior};
|
use buffer::line_formatter::{LineFormatter, RoundingBehavior};
|
||||||
|
|
||||||
|
pub mod formatter;
|
||||||
|
|
||||||
// Key codes
|
// Key codes
|
||||||
const K_ENTER: u16 = 13;
|
const K_ENTER: u16 = 13;
|
Loading…
Reference in New Issue
Block a user