From fee6fc21a3667d215a963ca1d326e645c13f88be Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Sun, 22 Feb 2015 12:30:02 -0800 Subject: [PATCH] Removed line and node source files since they are no longer used. --- src/buffer/line.rs | 818 ------------------------------ src/buffer/node.rs | 1201 -------------------------------------------- 2 files changed, 2019 deletions(-) delete mode 100644 src/buffer/line.rs delete mode 100644 src/buffer/node.rs diff --git a/src/buffer/line.rs b/src/buffer/line.rs deleted file mode 100644 index 9443733..0000000 --- a/src/buffer/line.rs +++ /dev/null @@ -1,818 +0,0 @@ -#![allow(dead_code)] - -use std::mem; -use super::rope::{Rope, RopeGraphemeIter}; -use string_utils::{is_line_ending, grapheme_count}; - - -/// A single line of text -pub struct Line { - text: Rope, // The text data, stored as UTF8 - pub ending: LineEnding, // The type of line ending, if any -} - - -impl Line { - /// Creates a new empty Line - pub fn new() -> Line { - Line { - text: Rope::new(), - ending: LineEnding::None, - } - } - - - /// Creates a new Line from a str. - pub fn new_from_str(text: &str) -> Line { - let mut ending = LineEnding::None; - let mut end_pos = 0; - - // Find the slice before the line ending, if any - for g in text.graphemes(true) { - match g { - //============== - // Line endings - //============== - - // CRLF - "\u{000D}\u{000A}" => { - ending = LineEnding::CRLF; - break; - }, - - // LF - "\u{000A}" => { - ending = LineEnding::LF; - break; - }, - - // VT - "\u{000B}" => { - ending = LineEnding::VT; - break; - }, - - // FF - "\u{000C}" => { - ending = LineEnding::FF; - break; - }, - - // CR - "\u{000D}" => { - ending = LineEnding::CR; - break; - }, - - // NEL - "\u{0085}" => { - ending = LineEnding::NEL; - break; - }, - - // LS - "\u{2028}" => { - ending = LineEnding::LS; - break; - }, - - // PS - "\u{2029}" => { - ending = LineEnding::PS; - break; - }, - - //================== - // Other characters - //================== - - _ => { - end_pos += g.len(); - } - } - } - - // Create and return Line - return Line { - text: Rope::new_from_str(&text[..end_pos]), - ending: ending, - }; - } - - - pub fn new_from_str_with_count_unchecked(text: &str, count: usize) -> Line { - let mut ending = LineEnding::None; - - let bytes = text.as_bytes(); - - // Check for line ending - let mut le_size: usize = 0; - let text_size = text.len(); - if text.len() >= 3 { - match &text[(text_size-3)..] { - // LS - "\u{2028}" => { - ending = LineEnding::LS; - le_size = 3; - }, - - // PS - "\u{2029}" => { - ending = LineEnding::PS; - le_size = 3; - }, - - _ => {} - } - } - - if le_size == 0 && text.len() >= 2 { - match &text[(text_size-2)..] { - // CRLF - "\u{000D}\u{000A}" => { - ending = LineEnding::CRLF; - le_size = 2; - }, - - _ => {} - } - } - - if le_size == 0 && text.len() >= 1 { - match &text[(text_size-1)..] { - // LF - "\u{000A}" => { - ending = LineEnding::LF; - le_size = 1; - }, - - // VT - "\u{000B}" => { - ending = LineEnding::VT; - le_size = 1; - }, - - // FF - "\u{000C}" => { - ending = LineEnding::FF; - le_size = 1; - }, - - // CR - "\u{000D}" => { - ending = LineEnding::CR; - le_size = 1; - }, - - // NEL - "\u{0085}" => { - ending = LineEnding::NEL; - le_size = 1; - }, - - _ => {} - } - } - - // Create and return Line - let cnt = if ending == LineEnding::None { count } else { count - 1 }; - return Line { - text: Rope::new_from_str_with_count(&text[..(bytes.len()-le_size)], cnt, 0), - ending: ending, - }; - } - - - /// Creates a new Line from a string. - /// Does not check to see if the string has internal newlines. - /// This is primarily used for efficient loading of files. - pub fn new_from_string_unchecked(text: String) -> Line { - // TODO: this can be smarter, and can pass the string - // directly to the Rope after taking off any line - // endings. - return Line::new_from_str_with_count_unchecked(text.as_slice(), grapheme_count(text.as_slice())); - } - - - /// Returns the total number of unicode graphemes in the line - pub fn grapheme_count(&self) -> usize { - let mut count = self.text.grapheme_count(); - match self.ending { - LineEnding::None => {}, - _ => {count += 1;} - } - return count; - } - - - /// Returns the total number of unicode graphemes in the line, - /// not counting the line ending grapheme, if any. - pub fn grapheme_count_sans_line_ending(&self) -> usize { - self.text.grapheme_count() - } - - - pub fn grapheme_at_index<'a>(&'a self, index: usize) -> &'a str { - // TODO: we don't have to iterate over the entire line - // anymore because we're using a rope now. Update. - let mut i = 0; - - for g in self.grapheme_iter() { - if i == index { - return g; - } - else { - i += 1; - } - } - - // Should never get here - panic!("Line::grapheme_at_index(): index past end of line."); - } - - - /// Returns a string containing the line's text - pub fn to_string(&self) -> String { - let s = self.text.to_string(); - return s; - } - - - /// Inserts `text` at grapheme index `pos`. - /// NOTE: panics if it encounters a line ending in the text. - pub fn insert_text(&mut self, text: &str, pos: usize) { - // Check for line endings - for g in text.graphemes(true) { - if is_line_ending(g) { - panic!("Line::insert_text(): line ending in inserted text."); - } - } - - // Insert text - self.text.insert_text_at_grapheme_index(text, pos); - } - - - /// Appends `text` to the end of line, just before the line ending (if - /// any). - /// NOTE: panics if it encounters a line ending in the text. - pub fn append_text(&mut self, text: &str) { - // Check for line endings - for g in text.graphemes(true) { - if is_line_ending(g) { - panic!("Line::append_text(): line ending in inserted text."); - } - } - - // Append text - let gc = self.text.grapheme_count(); - self.text.insert_text_at_grapheme_index(text, gc); - } - - - /// Remove the text between grapheme positions 'pos_a' and 'pos_b'. - pub fn remove_text(&mut self, pos_a: usize, pos_b: usize) { - self.text.remove_text_between_grapheme_indices(pos_a, pos_b); - } - - - /// Insert a line break into the line, splitting it into two. - /// This line stays as the first part of the split. The second - /// part is returned. - pub fn split(&mut self, ending: LineEnding, pos: usize) -> Line { - // TODO: change code to use Rope - let mut other = Line::new(); - - // Inserting at very beginning: special cased for efficiency - if pos == 0 { - mem::swap(self, &mut other); - self.ending = ending; - } - // Otherwise, general case - else { - // Split the text - other.text = self.text.split(pos); - - // Set the line endings appropriately - other.ending = self.ending; - self.ending = ending; - } - - return other; - } - - - /// Appends another line to the end of this one, consuming the other - /// line. - /// Note that the resulting line ending is the ending of the other - /// line, if any. - pub fn append(&mut self, other: Line) { - self.ending = other.ending; - self.text.append(other.text); - } - - - /// Returns an iterator over the graphemes of the line - pub fn grapheme_iter<'a>(&'a self) -> LineGraphemeIter<'a> { - LineGraphemeIter { - graphemes: self.text.grapheme_iter(), - grapheme_count: None, - ending: self.ending, - done: false, - } - } - - - /// Returns an iterator over the graphemes of the line - pub fn grapheme_iter_at_index<'a>(&'a self, index: usize) -> LineGraphemeIter<'a> { - LineGraphemeIter { - graphemes: self.text.grapheme_iter_at_index(index), - grapheme_count: None, - ending: self.ending, - done: false, - } - } - - - /// Returns an iterator over the graphemes of the line - pub fn grapheme_iter_at_index_with_max_length<'a>(&'a self, index: usize, length: usize) -> LineGraphemeIter<'a> { - LineGraphemeIter { - graphemes: self.text.grapheme_iter_at_index(index), - grapheme_count: Some(length), - ending: self.ending, - done: false, - } - } -} - - -/// Represents one of the valid Unicode line endings. -/// Also acts as an index into `LINE_ENDINGS`. -#[derive(PartialEq, Copy)] -pub enum LineEnding { - None = 0, // No line ending - CRLF = 1, // CarriageReturn followed by LineFeed - LF = 2, // U+000A -- LineFeed - VT = 3, // U+000B -- VerticalTab - FF = 4, // U+000C -- FormFeed - CR = 5, // U+000D -- CarriageReturn - NEL = 6, // U+0085 -- NextLine - LS = 7, // U+2028 -- Line Separator - PS = 8, // U+2029 -- ParagraphSeparator -} - -pub fn str_to_line_ending(g: &str) -> LineEnding { - match g { - //============== - // Line endings - //============== - - // CRLF - "\u{000D}\u{000A}" => { - return LineEnding::CRLF; - }, - - // LF - "\u{000A}" => { - return LineEnding::LF; - }, - - // VT - "\u{000B}" => { - return LineEnding::VT; - }, - - // FF - "\u{000C}" => { - return LineEnding::FF; - }, - - // CR - "\u{000D}" => { - return LineEnding::CR; - }, - - // NEL - "\u{0085}" => { - return LineEnding::NEL; - }, - - // LS - "\u{2028}" => { - return LineEnding::LS; - }, - - // PS - "\u{2029}" => { - return LineEnding::PS; - }, - - // Not a line ending - _ => { - return LineEnding::None; - } - } -} - -pub fn line_ending_to_str(ending: LineEnding) -> &'static str { - LINE_ENDINGS[ending as usize] -} - -/// An array of string literals corresponding to the possible -/// unicode line endings. -pub const LINE_ENDINGS: [&'static str; 9] = ["", - "\u{000D}\u{000A}", - "\u{000A}", - "\u{000B}", - "\u{000C}", - "\u{000D}", - "\u{0085}", - "\u{2028}", - "\u{2029}" -]; - - -/// An iterator over the graphemes of a Line -pub struct LineGraphemeIter<'a> { - graphemes: RopeGraphemeIter<'a>, - grapheme_count: Option, - ending: LineEnding, - done: bool, -} - -impl<'a> LineGraphemeIter<'a> { - pub fn skip_graphemes(&mut self, n: usize) { - for _ in range(0, n) { - if let None = self.next() { - break; - } - } - } -} - -impl<'a> Iterator for LineGraphemeIter<'a> { - type Item = &'a str; - - fn next(&mut self) -> Option<&'a str> { - if self.done { - return None; - } - else if let Some(0) = self.grapheme_count { - return None; - } - else { - if let Some(ref mut i) = self.grapheme_count { - *i -= 1; - } - - let g = self.graphemes.next(); - if let Some(_) = g { - return g; - } - else { - self.done = true; - - if self.ending == LineEnding::None { - return None; - } - else { - return Some(LINE_ENDINGS[self.ending as usize]); - } - } - } - } -} - - - - -//========================================================================= -// Line tests -//========================================================================= - -#[cfg(test)] -mod tests { - #![allow(unused_imports)] - use super::{Line, LineEnding, LineGraphemeIter}; - const TAB_WIDTH: usize = 4; - - - #[test] - fn new_text_line() { - let tl = Line::new(); - - assert_eq!(tl.text.grapheme_count(), 0); - assert!(tl.ending == LineEnding::None); - } - - #[test] - fn new_text_line_from_str() { - let tl = Line::new_from_str("Hello!"); - - assert_eq!(tl.text.grapheme_count(), 6); - assert!(&tl.text[0] == "H"); - assert!(&tl.text[1] == "e"); - assert!(&tl.text[2] == "l"); - assert!(&tl.text[3] == "l"); - assert!(&tl.text[4] == "o"); - assert!(&tl.text[5] == "!"); - assert!(tl.ending == LineEnding::None); - } - - #[test] - fn new_text_line_from_empty_str() { - let tl = Line::new_from_str(""); - - assert_eq!(tl.text.grapheme_count(), 0); - assert!(tl.ending == LineEnding::None); - } - - #[test] - fn new_text_line_from_str_with_lf() { - let tl = Line::new_from_str("Hello!\n"); - - assert_eq!(tl.text.grapheme_count(), 6); - assert!(&tl.text[0] == "H"); - assert!(&tl.text[1] == "e"); - assert!(&tl.text[2] == "l"); - assert!(&tl.text[3] == "l"); - assert!(&tl.text[4] == "o"); - assert!(&tl.text[5] == "!"); - assert!(tl.ending == LineEnding::LF); - } - - #[test] - fn new_text_line_from_str_with_crlf() { - let tl = Line::new_from_str("Hello!\r\n"); - - assert_eq!(tl.text.grapheme_count(), 6); - assert!(&tl.text[0] == "H"); - assert!(&tl.text[1] == "e"); - assert!(&tl.text[2] == "l"); - assert!(&tl.text[3] == "l"); - assert!(&tl.text[4] == "o"); - assert!(&tl.text[5] == "!"); - assert!(tl.ending == LineEnding::CRLF); - } - - #[test] - fn new_text_line_from_str_with_crlf_and_too_long() { - let tl = Line::new_from_str("Hello!\r\nLa la la la"); - - assert_eq!(tl.text.grapheme_count(), 6); - assert!(&tl.text[0] == "H"); - assert!(&tl.text[1] == "e"); - assert!(&tl.text[2] == "l"); - assert!(&tl.text[3] == "l"); - assert!(&tl.text[4] == "o"); - assert!(&tl.text[5] == "!"); - assert!(tl.ending == LineEnding::CRLF); - } - - #[test] - fn new_text_line_from_string_unchecked() { - let s = String::from_str("Hello!"); - - let tl = Line::new_from_string_unchecked(s); - - assert_eq!(tl.text.grapheme_count(), 6); - assert!(&tl.text[0] == "H"); - assert!(&tl.text[1] == "e"); - assert!(&tl.text[2] == "l"); - assert!(&tl.text[3] == "l"); - assert!(&tl.text[4] == "o"); - assert!(&tl.text[5] == "!"); - assert!(tl.ending == LineEnding::None); - } - - #[test] - fn new_text_line_from_string_unchecked_with_lf() { - let s = String::from_str("Hello!\u{000A}"); - - let tl = Line::new_from_string_unchecked(s); - - assert_eq!(tl.text.grapheme_count(), 6); - assert!(&tl.text[0] == "H"); - assert!(&tl.text[1] == "e"); - assert!(&tl.text[2] == "l"); - assert!(&tl.text[3] == "l"); - assert!(&tl.text[4] == "o"); - assert!(&tl.text[5] == "!"); - assert!(tl.ending == LineEnding::LF); - } - - #[test] - fn new_text_line_from_string_unchecked_with_crlf() { - let s = String::from_str("Hello!\u{000D}\u{000A}"); - - let tl = Line::new_from_string_unchecked(s); - - assert_eq!(tl.text.grapheme_count(), 6); - assert!(&tl.text[0] == "H"); - assert!(&tl.text[1] == "e"); - assert!(&tl.text[2] == "l"); - assert!(&tl.text[3] == "l"); - assert!(&tl.text[4] == "o"); - assert!(&tl.text[5] == "!"); - assert!(tl.ending == LineEnding::CRLF); - } - - #[test] - fn new_text_line_from_string_unchecked_with_ls() { - let s = String::from_str("Hello!\u{2028}"); - - let tl = Line::new_from_string_unchecked(s); - - assert_eq!(tl.text.grapheme_count(), 6); - assert!(&tl.text[0] == "H"); - assert!(&tl.text[1] == "e"); - assert!(&tl.text[2] == "l"); - assert!(&tl.text[3] == "l"); - assert!(&tl.text[4] == "o"); - assert!(&tl.text[5] == "!"); - assert!(tl.ending == LineEnding::LS); - } - - #[test] - fn text_line_insert_text() { - let mut tl = Line::new_from_str("Hello!\r\n"); - - tl.insert_text(" world", 5); - - assert_eq!(tl.text.grapheme_count(), 12); - assert!(&tl.text[0] == "H"); - assert!(&tl.text[1] == "e"); - assert!(&tl.text[2] == "l"); - assert!(&tl.text[3] == "l"); - assert!(&tl.text[4] == "o"); - assert!(&tl.text[5] == " "); - assert!(&tl.text[6] == "w"); - assert!(&tl.text[7] == "o"); - assert!(&tl.text[8] == "r"); - assert!(&tl.text[9] == "l"); - assert!(&tl.text[10] == "d"); - assert!(&tl.text[11] == "!"); - assert!(tl.ending == LineEnding::CRLF); - } - - #[test] - fn text_line_append_text() { - let mut tl = Line::new_from_str("Hello\r\n"); - - tl.append_text(" world!"); - - assert_eq!(tl.text.grapheme_count(), 12); - assert!(&tl.text[0] == "H"); - assert!(&tl.text[1] == "e"); - assert!(&tl.text[2] == "l"); - assert!(&tl.text[3] == "l"); - assert!(&tl.text[4] == "o"); - assert!(&tl.text[5] == " "); - assert!(&tl.text[6] == "w"); - assert!(&tl.text[7] == "o"); - assert!(&tl.text[8] == "r"); - assert!(&tl.text[9] == "l"); - assert!(&tl.text[10] == "d"); - assert!(&tl.text[11] == "!"); - assert!(tl.ending == LineEnding::CRLF); - } - - #[test] - fn text_line_remove_text() { - let mut tl = Line::new_from_str("Hello world!\r\n"); - - tl.remove_text(5, 11); - - assert_eq!(tl.text.grapheme_count(), 6); - assert!(&tl.text[0] == "H"); - assert!(&tl.text[1] == "e"); - assert!(&tl.text[2] == "l"); - assert!(&tl.text[3] == "l"); - assert!(&tl.text[4] == "o"); - assert!(&tl.text[5] == "!"); - assert!(tl.ending == LineEnding::CRLF); - } - - #[test] - fn text_line_split() { - let mut tl1 = Line::new_from_str("Hello world!\r\n"); - - let tl2 = tl1.split(LineEnding::LF, 5); - - assert_eq!(tl1.text.grapheme_count(), 5); - assert!(&tl1.text[0] == "H"); - assert!(&tl1.text[1] == "e"); - assert!(&tl1.text[2] == "l"); - assert!(&tl1.text[3] == "l"); - assert!(&tl1.text[4] == "o"); - assert!(tl1.ending == LineEnding::LF); - - assert_eq!(tl2.text.grapheme_count(), 7); - assert!(&tl2.text[0] == " "); - assert!(&tl2.text[1] == "w"); - assert!(&tl2.text[2] == "o"); - assert!(&tl2.text[3] == "r"); - assert!(&tl2.text[4] == "l"); - assert!(&tl2.text[5] == "d"); - assert!(&tl2.text[6] == "!"); - assert!(tl2.ending == LineEnding::CRLF); - } - - #[test] - fn text_line_split_beginning() { - let mut tl1 = Line::new_from_str("Hello!\r\n"); - - let tl2 = tl1.split(LineEnding::LF, 0); - - assert_eq!(tl1.text.grapheme_count(), 0); - assert!(tl1.ending == LineEnding::LF); - - assert_eq!(tl2.text.grapheme_count(), 6); - assert!(&tl2.text[0] == "H"); - assert!(&tl2.text[1] == "e"); - assert!(&tl2.text[2] == "l"); - assert!(&tl2.text[3] == "l"); - assert!(&tl2.text[4] == "o"); - assert!(&tl2.text[5] == "!"); - assert!(tl2.ending == LineEnding::CRLF); - } - - - //========================================================================= - // LineGraphemeIter tests - //========================================================================= - - #[test] - fn text_line_grapheme_iter() { - let tl = Line::new_from_str("Hello!"); - let mut iter = tl.grapheme_iter(); - - assert!(iter.next() == Some("H")); - assert!(iter.next() == Some("e")); - assert!(iter.next() == Some("l")); - assert!(iter.next() == Some("l")); - assert!(iter.next() == Some("o")); - assert!(iter.next() == Some("!")); - assert!(iter.next() == None); - } - - #[test] - fn text_line_grapheme_iter_with_lf() { - let tl = Line::new_from_str("Hello!\n"); - let mut iter = tl.grapheme_iter(); - - assert!(iter.next() == Some("H")); - assert!(iter.next() == Some("e")); - assert!(iter.next() == Some("l")); - assert!(iter.next() == Some("l")); - assert!(iter.next() == Some("o")); - assert!(iter.next() == Some("!")); - assert!(iter.next() == Some("\n")); - assert!(iter.next() == None); - } - - #[test] - fn text_line_grapheme_iter_with_crlf() { - let tl = Line::new_from_str("Hello!\r\n"); - let mut iter = tl.grapheme_iter(); - - assert!(iter.next() == Some("H")); - assert!(iter.next() == Some("e")); - assert!(iter.next() == Some("l")); - assert!(iter.next() == Some("l")); - assert!(iter.next() == Some("o")); - assert!(iter.next() == Some("!")); - assert!(iter.next() == Some("\r\n")); - assert!(iter.next() == None); - } - - #[test] - fn text_line_grapheme_iter_at_index() { - let tl = Line::new_from_str("Hello!"); - let mut iter = tl.grapheme_iter_at_index(2); - - assert!(iter.next() == Some("l")); - assert!(iter.next() == Some("l")); - assert!(iter.next() == Some("o")); - assert!(iter.next() == Some("!")); - assert!(iter.next() == None); - } - - #[test] - fn text_line_grapheme_iter_at_index_past_end() { - let tl = Line::new_from_str("Hello!"); - let mut iter = tl.grapheme_iter_at_index(10); - - assert!(iter.next() == None); - } - - #[test] - fn text_line_grapheme_iter_at_index_at_lf() { - let tl = Line::new_from_str("Hello!\n"); - let mut iter = tl.grapheme_iter_at_index(6); - - assert!(iter.next() == Some("\n")); - assert!(iter.next() == None); - } - -} \ No newline at end of file diff --git a/src/buffer/node.rs b/src/buffer/node.rs deleted file mode 100644 index 1e3590d..0000000 --- a/src/buffer/node.rs +++ /dev/null @@ -1,1201 +0,0 @@ -use std::mem; -use std::cmp::{min, max}; - -use string_utils::is_line_ending; -use super::line::{Line, LineEnding, LineGraphemeIter, str_to_line_ending}; - -pub enum BufferNodeData { - Leaf(Line), - Branch(Box, Box), -} - -pub struct BufferNode { - pub data: BufferNodeData, - pub tree_height: usize, - - pub grapheme_count: usize, - pub line_count: usize, -} - -impl BufferNode { - pub fn new() -> BufferNode { - let line = Line::new(); - - BufferNode { - data: BufferNodeData::Leaf(line), - tree_height: 1, - grapheme_count: 0, - line_count: 1, - } - } - - - pub fn new_from_line(line: Line) -> BufferNode { - let gc = line.grapheme_count(); - - BufferNode { - data: BufferNodeData::Leaf(line), - tree_height: 1, - grapheme_count: gc, - line_count: 1, - } - } - - - pub fn new_from_line_with_count_unchecked(line: Line, grapheme_count: usize) -> BufferNode { - BufferNode { - data: BufferNodeData::Leaf(line), - tree_height: 1, - grapheme_count: grapheme_count, - line_count: 1, - } - } - - - fn update_height(&mut self) { - match self.data { - BufferNodeData::Leaf(_) => { - self.tree_height = 1; - }, - - BufferNodeData::Branch(ref left, ref right) => { - self.tree_height = max(left.tree_height, right.tree_height) + 1; - } - } - } - - - fn update_stats(&mut self) { - self.update_height(); - - match self.data { - BufferNodeData::Leaf(ref line) => { - self.grapheme_count = line.grapheme_count(); - self.line_count = 1; - }, - - BufferNodeData::Branch(ref left, ref right) => { - self.grapheme_count = left.grapheme_count + right.grapheme_count; - self.line_count = left.line_count + right.line_count; - } - } - } - - - /// Rotates the tree under the node left - fn rotate_left(&mut self) { - let mut temp = BufferNode::new(); - - if let BufferNodeData::Branch(_, ref mut right) = self.data { - mem::swap(&mut temp, &mut (**right)); - - if let BufferNodeData::Branch(ref mut left, _) = temp.data { - mem::swap(&mut (**left), &mut (**right)); - } - else { - panic!("rotate_left(): attempting to rotate node without branching right child."); - } - } - else { - panic!("rotate_left(): attempting to rotate leaf node."); - } - - if let BufferNodeData::Branch(ref mut left, _) = temp.data { - mem::swap(&mut (**left), self); - left.update_stats(); - } - - mem::swap(&mut temp, self); - self.update_stats(); - } - - - /// Rotates the tree under the node right - fn rotate_right(&mut self) { - let mut temp = BufferNode::new(); - - if let BufferNodeData::Branch(ref mut left, _) = self.data { - mem::swap(&mut temp, &mut (**left)); - - if let BufferNodeData::Branch(_, ref mut right) = temp.data { - mem::swap(&mut (**right), &mut (**left)); - } - else { - panic!("rotate_right(): attempting to rotate node without branching left child."); - } - } - else { - panic!("rotate_right(): attempting to rotate leaf node."); - } - - if let BufferNodeData::Branch(_, ref mut right) = temp.data { - mem::swap(&mut (**right), self); - right.update_stats(); - } - - mem::swap(&mut temp, self); - self.update_stats(); - } - - - /// Rebalances the tree under the node - fn rebalance(&mut self) { - loop { - let mut rot: isize; - - if let BufferNodeData::Branch(ref mut left, ref mut right) = self.data { - let height_diff = (left.tree_height as isize) - (right.tree_height as isize); - - // Left side higher than right side - if height_diff > 1 { - let mut child_rot = false; - if let BufferNodeData::Branch(ref lc, ref rc) = left.data { - if lc.tree_height < rc.tree_height { - child_rot = true; - } - } - - if child_rot { - left.rotate_left(); - } - - rot = 1; - } - // Right side higher then left side - else if height_diff < -1 { - let mut child_rot = false; - if let BufferNodeData::Branch(ref lc, ref rc) = right.data { - if lc.tree_height > rc.tree_height { - child_rot = true; - } - } - - if child_rot { - right.rotate_right(); - } - - rot = -1; - } - // Balanced, stop - else { - break; - } - } - else { - // Leaf node, stop - break; - } - - if rot == 1 { - self.rotate_right(); - } - else if rot == -1 { - self.rotate_left(); - } - } - } - - - pub fn get_grapheme_recursive<'a>(&'a self, index: usize) -> &'a str { - match self.data { - BufferNodeData::Leaf(ref line) => { - return line.grapheme_at_index(index); - }, - - BufferNodeData::Branch(ref left, ref right) => { - if index < left.grapheme_count { - return left.get_grapheme_recursive(index); - } - else { - return right.get_grapheme_recursive(index - left.grapheme_count); - } - } - } - } - - - pub fn get_line_recursive<'a>(&'a self, index: usize) -> &'a Line { - match self.data { - BufferNodeData::Leaf(ref line) => { - if index != 0 { - panic!("get_line_recursive(): at leaf, but index is not zero. This should never happen!"); - } - return line; - }, - - BufferNodeData::Branch(ref left, ref right) => { - if index < left.line_count { - return left.get_line_recursive(index); - } - else { - return right.get_line_recursive(index - left.line_count); - } - } - } - } - - - pub fn index_to_line_col_recursive(&self, index: usize) -> (usize, usize) { - match self.data { - BufferNodeData::Leaf(_) => { - return (0, min(index, self.grapheme_count)); - }, - - BufferNodeData::Branch(ref left, ref right) => { - if index < left.grapheme_count { - return left.index_to_line_col_recursive(index); - } - else { - let (v, h) = right.index_to_line_col_recursive((index - left.grapheme_count)); - return (v + left.line_count, h); - } - } - } - } - - - pub fn line_col_to_index_recursive(&self, pos: (usize, usize)) -> usize { - match self.data { - BufferNodeData::Leaf(ref line) => { - if pos.0 != 0 { - return self.grapheme_count; - } - - if pos.1 >= self.grapheme_count { - if line.ending != LineEnding::None { - return self.grapheme_count - 1; - } - else { - return self.grapheme_count; - } - } - else { - return pos.1; - } - }, - - BufferNodeData::Branch(ref left, ref right) => { - if pos.0 < left.line_count { - return left.line_col_to_index_recursive(pos); - } - else { - return left.grapheme_count + right.line_col_to_index_recursive((pos.0 - left.line_count, pos.1)); - } - } - } - } - - - /// Insert 'text' at grapheme position 'pos'. - pub fn insert_text(&mut self, text: &str, pos: usize) { - // Byte indices - let mut b1: usize = 0; - let mut b2: usize = 0; - - // Grapheme indices - let mut g1: usize = 0; - let mut g2: usize = 0; - - // Iterate through graphemes - for grapheme in text.grapheme_indices(true) { - if is_line_ending(grapheme.1) { - if g1 < g2 { - self.insert_text_recursive(&text[b1..b2], pos + g1); - } - - g1 = g2; - b2 += grapheme.1.len(); - g2 += 1; - - self.insert_line_break_recursive(str_to_line_ending(grapheme.1), pos + g1); - - b1 = b2; - g1 = g2; - } - else { - b2 += grapheme.1.len(); - g2 += 1; - } - } - - if g1 < g2 { - self.insert_text_recursive(&text[b1..b2], pos + g1); - } - } - - - /// Inserts the given text string at the given grapheme position. - /// Note: this assumes the given text has no newline graphemes. - pub fn insert_text_recursive(&mut self, text: &str, pos: usize) { - match self.data { - // Find node for text to be inserted into - BufferNodeData::Branch(ref mut left, ref mut right) => { - if pos < left.grapheme_count { - left.insert_text_recursive(text, pos); - } - else { - right.insert_text_recursive(text, pos - left.grapheme_count); - } - - }, - - // Insert the text - BufferNodeData::Leaf(ref mut line) => { - line.insert_text(text, pos); - }, - } - - self.update_stats(); - } - - - /// Inserts a line break at the given grapheme position - pub fn insert_line_break_recursive(&mut self, ending: LineEnding, pos: usize) { - if ending == LineEnding::None { - return; - } - - let mut old_line = Line::new(); - let mut do_split: bool; - - match self.data { - // Find node for the line break to be inserted into - BufferNodeData::Branch(ref mut left, ref mut right) => { - if pos < left.grapheme_count { - left.insert_line_break_recursive(ending, pos); - } - else { - right.insert_line_break_recursive(ending, pos - left.grapheme_count); - } - do_split = false; - }, - - // We need to insert the line break, so get the data we - // need for that (can't do it here because of borrow checker). - BufferNodeData::Leaf(ref mut line) => { - mem::swap(&mut old_line, line); - do_split = true; - }, - } - - if do_split { - // Insert line break - let new_line = old_line.split(ending, pos); - let new_node_a = Box::new(BufferNode::new_from_line(old_line)); - let new_node_b = Box::new(BufferNode::new_from_line(new_line)); - - self.data = BufferNodeData::Branch(new_node_a, new_node_b); - - self.update_stats(); - } - else { - self.update_stats(); - self.rebalance(); - } - } - - - /// Removes text between grapheme positions pos_a and pos_b. - /// Returns true if a dangling left side remains from the removal. - /// Returns false otherwise. - pub fn remove_text_recursive(&mut self, pos_a: usize, pos_b: usize, is_last: bool) -> bool { - let mut temp_node = BufferNode::new(); - let mut total_side_removal = false; - let mut dangling_line = false; - let mut do_merge_fix = false; - let mut merge_line_number: usize = 0; - - match self.data { - BufferNodeData::Branch(ref mut left, ref mut right) => { - // Check for complete removal of both sides, which - // should never happen here - if pos_a == 0 && pos_b == self.grapheme_count { - panic!("remove_text_recursive(): attempting to remove entirety of self, which cannot be done from inside self."); - } - // Complete removal of left side - else if pos_a == 0 && pos_b >= left.grapheme_count { - if pos_b > left.grapheme_count { - let a = 0; - let b = pos_b - left.grapheme_count; - right.remove_text_recursive(a, b, is_last); - } - - total_side_removal = true; - mem::swap(&mut temp_node, &mut (**right)); - } - // Complete removal of right side - else if pos_a <= left.grapheme_count && pos_b == self.grapheme_count { - if pos_a < left.grapheme_count { - let a = pos_a; - let b = left.grapheme_count; - dangling_line = left.remove_text_recursive(a, b, false); - } - - if is_last && !dangling_line { - mem::swap(&mut temp_node, &mut (**right)); - } - else { - if is_last { - dangling_line = false; - } - - total_side_removal = true; - mem::swap(&mut temp_node, &mut (**left)); - } - } - // Partial removal of one or both sides - else { - // Right side - if pos_b > left.grapheme_count { - let a = if pos_a > left.grapheme_count {pos_a - left.grapheme_count} else {0}; - let b = pos_b - left.grapheme_count; - dangling_line = right.remove_text_recursive(a, b, is_last) && !is_last; - } - - // Left side - if pos_a < left.grapheme_count { - let a = pos_a; - let b = min(pos_b, left.grapheme_count); - do_merge_fix = left.remove_text_recursive(a, b, false); - merge_line_number = left.line_count - 1; - } - } - }, - - - BufferNodeData::Leaf(ref mut line) => { - let mut pos_b2 = pos_b; - if pos_b == self.grapheme_count && line.ending != LineEnding::None { - line.ending = LineEnding::None; - pos_b2 -= 1; - } - line.remove_text(pos_a, pos_b2); - - dangling_line = line.ending == LineEnding::None && !is_last; - }, - } - - // Do the merge fix if necessary - if do_merge_fix { - self.merge_line_with_next_recursive(merge_line_number, None); - } - // If one of the sides was completely removed, replace self with the - // remaining side. - else if total_side_removal { - mem::swap(&mut temp_node, self); - } - - self.update_stats(); - self.rebalance(); - - return dangling_line; - } - - - pub fn append_line_unchecked_recursive(&mut self, line: Line) { - let mut other_line = Line::new(); - - if let BufferNodeData::Branch(_, ref mut right) = self.data { - right.append_line_unchecked_recursive(line); - } - else { - if let BufferNodeData::Leaf(ref mut this_line) = self.data { - mem::swap(this_line, &mut other_line); - } - - let new_node_a = Box::new(BufferNode::new_from_line(other_line)); - let new_node_b = Box::new(BufferNode::new_from_line(line)); - self.data = BufferNodeData::Branch(new_node_a, new_node_b); - } - - self.update_stats(); - self.rebalance(); - } - - - pub fn append_leaf_node_unchecked_recursive(&mut self, node: BufferNode) { - if let BufferNodeData::Branch(_, ref mut right) = self.data { - right.append_leaf_node_unchecked_recursive(node); - } - else { - let mut new_left_node = BufferNode::new(); - mem::swap(self, &mut new_left_node); - self.data = BufferNodeData::Branch(Box::new(new_left_node), Box::new(node)); - } - - self.update_stats(); - self.rebalance(); - } - - - /// Removes lines in line number range [line_a, line_b) - pub fn remove_lines_recursive(&mut self, line_a: usize, line_b: usize) { - let mut remove_left = false; - let mut remove_right = false; - let mut temp_node = BufferNode::new(); - - if let BufferNodeData::Branch(ref mut left, ref mut right) = self.data { - // Right node completely removed - if line_a <= left.line_count && line_b >= (left.line_count + right.line_count) { - remove_right = true; - } - // Right node partially removed - else if line_b > left.line_count { - let a = if line_a > left.line_count {line_a - left.line_count} else {0}; - let b = line_b - left.line_count; - right.remove_lines_recursive(a, b); - } - - // Left node completely removed - if line_a == 0 && line_b >= left.line_count { - remove_left = true; - } - // Left node partially removed - else if line_a < left.line_count { - let a = line_a; - let b = min(left.line_count, line_b); - left.remove_lines_recursive(a, b); - } - - // Set up for node removal - if remove_left && remove_right { - panic!("remove_lines_recursive(): attempting to completely remove both left and right nodes. This should never happen!"); - } - else if remove_left { - mem::swap(&mut temp_node, &mut (**right)); - } - else if remove_right { - mem::swap(&mut temp_node, &mut (**left)); - } - } - else { - panic!("remove_lines_recursive(): processing a leaf node directly. This should never happen!"); - } - - // Swap out node for non-removed node - if remove_left || remove_right { - mem::swap(&mut temp_node, self); - } - - self.update_stats(); - self.rebalance(); - } - - - pub fn merge_line_with_next_recursive(&mut self, line_number: usize, fetched_line: Option) { - match fetched_line { - None => { - let line: Option = self.pull_out_line_recursive(line_number + 1); - if let Some(l) = line { - self.merge_line_with_next_recursive(line_number, Some(l)); - } - }, - - Some(line) => { - match self.data { - BufferNodeData::Branch(ref mut left, ref mut right) => { - if line_number < left.line_count { - left.merge_line_with_next_recursive(line_number, Some(line)); - } - else { - right.merge_line_with_next_recursive(line_number - left.line_count, Some(line)); - } - }, - - BufferNodeData::Leaf(ref mut line2) => { - line2.append(line); - } - } - } - } - - self.update_stats(); - self.rebalance(); - } - - - /// Removes a single line out of the text and returns it. - pub fn pull_out_line_recursive(&mut self, line_number: usize) -> Option { - let mut pulled_line = Line::new(); - let mut temp_node = BufferNode::new(); - let mut side_removal = false; - - match self.data { - BufferNodeData::Branch(ref mut left, ref mut right) => { - if line_number < left.line_count { - if let BufferNodeData::Leaf(ref mut line) = left.data { - mem::swap(&mut pulled_line, line); - mem::swap(&mut temp_node, &mut (**right)); - side_removal = true; - } - else { - pulled_line = left.pull_out_line_recursive(line_number).unwrap(); - } - } - else if line_number < self.line_count { - if let BufferNodeData::Leaf(ref mut line) = right.data { - mem::swap(&mut pulled_line, line); - mem::swap(&mut temp_node, &mut (**left)); - side_removal = true; - } - else { - pulled_line = right.pull_out_line_recursive(line_number - left.line_count).unwrap(); - } - } - else { - return None; - } - }, - - - BufferNodeData::Leaf(_) => { - panic!("pull_out_line_recursive(): inside leaf node. This should never happen!"); - }, - } - - if side_removal { - mem::swap(&mut temp_node, self); - } - - self.update_stats(); - self.rebalance(); - - return Some(pulled_line); - } - - - /// Ensures that the last line in the node tree has no - /// ending line break. - pub fn set_last_line_ending_recursive(&mut self) { - match self.data { - BufferNodeData::Branch(_, ref mut right) => { - right.set_last_line_ending_recursive(); - }, - - BufferNodeData::Leaf(ref mut line) => { - line.ending = LineEnding::None; - }, - } - - self.update_stats(); - } - - - /// Creates an iterator at the first grapheme - pub fn grapheme_iter<'a>(&'a self) -> BufferNodeGraphemeIter<'a> { - let mut node_stack: Vec<&'a BufferNode> = Vec::new(); - let mut cur_node = self; - - loop { - match cur_node.data { - BufferNodeData::Leaf(_) => { - break; - }, - - BufferNodeData::Branch(ref left, ref right) => { - node_stack.push(&(**right)); - cur_node = &(**left); - } - } - } - - BufferNodeGraphemeIter { - node_stack: node_stack, - cur_line: match cur_node.data { - BufferNodeData::Leaf(ref line) => line.grapheme_iter(), - _ => panic!("This should never happen.") - } - } - } - - - /// Creates an iterator at the given grapheme index - pub fn grapheme_iter_at_index<'a>(&'a self, index: usize) -> BufferNodeGraphemeIter<'a> { - let mut node_stack: Vec<&'a BufferNode> = Vec::new(); - let mut cur_node = self; - let mut grapheme_i = index; - - loop { - match cur_node.data { - BufferNodeData::Leaf(_) => { - break; - }, - - BufferNodeData::Branch(ref left, ref right) => { - if grapheme_i < left.grapheme_count { - node_stack.push(&(**right)); - cur_node = &(**left); - } - else { - cur_node = &(**right); - grapheme_i -= left.grapheme_count; - } - } - } - } - - BufferNodeGraphemeIter { - node_stack: node_stack, - cur_line: match cur_node.data { - BufferNodeData::Leaf(ref line) => line.grapheme_iter_at_index(grapheme_i), - _ => panic!("This should never happen.") - } - } - } - - - /// Creates a line iterator starting at the first line - pub fn line_iter<'a>(&'a self) -> BufferNodeLineIter<'a> { - let mut node_stack: Vec<&'a BufferNode> = Vec::new(); - let mut cur_node = self; - - loop { - match cur_node.data { - BufferNodeData::Leaf(_) => { - break; - }, - - BufferNodeData::Branch(ref left, ref right) => { - node_stack.push(&(**right)); - cur_node = &(**left); - } - } - } - - node_stack.push(cur_node); - - BufferNodeLineIter { - node_stack: node_stack, - } - } - - - /// Creates a line iterator starting at the given line index - pub fn line_iter_at_index<'a>(&'a self, index: usize) -> BufferNodeLineIter<'a> { - let mut node_stack: Vec<&'a BufferNode> = Vec::new(); - let mut cur_node = self; - let mut line_i = index; - - loop { - match cur_node.data { - BufferNodeData::Leaf(_) => { - break; - }, - - BufferNodeData::Branch(ref left, ref right) => { - if line_i < left.line_count { - node_stack.push(&(**right)); - cur_node = &(**left); - } - else { - line_i -= left.line_count; - cur_node = &(**right); - } - } - } - } - - node_stack.push(cur_node); - - BufferNodeLineIter { - node_stack: node_stack, - } - } - - -} - - - - -//============================================================= -// Node iterators -//============================================================= - -/// An iterator over a text buffer's graphemes -pub struct BufferNodeGraphemeIter<'a> { - node_stack: Vec<&'a BufferNode>, - cur_line: LineGraphemeIter<'a>, -} - - -impl<'a> BufferNodeGraphemeIter<'a> { - // Puts the iterator on the next line. - // Returns true if there was a next line, - // false if there wasn't. - pub fn next_line(&mut self) -> bool { - loop { - if let Option::Some(node) = self.node_stack.pop() { - match node.data { - BufferNodeData::Leaf(ref line) => { - self.cur_line = line.grapheme_iter(); - return true; - }, - - BufferNodeData::Branch(ref left, ref right) => { - self.node_stack.push(&(**right)); - self.node_stack.push(&(**left)); - continue; - } - } - } - else { - return false; - } - } - } - - - // Skips the iterator n graphemes ahead. - // If it runs out of graphemes before reaching the desired skip count, - // returns false. Otherwise returns true. - pub fn skip_graphemes(&mut self, n: usize) -> bool { - // TODO: more efficient implementation - for _ in range(0, n) { - if let Option::None = self.next() { - return false; - } - } - - return true; - } - - -} - - -impl<'a> Iterator for BufferNodeGraphemeIter<'a> { - type Item = &'a str; - - fn next(&mut self) -> Option<&'a str> { - loop { - if let Option::Some(g) = self.cur_line.next() { - return Option::Some(g); - } - - if self.next_line() { - continue; - } - else { - return Option::None; - } - } - } - - -} - - - - -/// An iterator over a text buffer's lines -pub struct BufferNodeLineIter<'a> { - node_stack: Vec<&'a BufferNode>, -} - - -impl<'a> Iterator for BufferNodeLineIter<'a> { - type Item = &'a Line; - - fn next(&mut self) -> Option<&'a Line> { - loop { - if let Option::Some(node) = self.node_stack.pop() { - match node.data { - BufferNodeData::Leaf(ref line) => { - return Some(line); - }, - - BufferNodeData::Branch(ref left, ref right) => { - self.node_stack.push(&(**right)); - self.node_stack.push(&(**left)); - continue; - } - } - } - else { - return None; - } - } - } - - -} - - - -//==================================================================== -// TESTS -//==================================================================== - -#[cfg(test)] -mod tests { - use super::BufferNode; - use super::super::line::LineEnding; - - #[test] - fn merge_line_with_next_recursive_1() { - let mut node = BufferNode::new(); - node.insert_text("Hi\n there!", 0); - - assert!(node.grapheme_count == 10); - assert!(node.line_count == 2); - - node.merge_line_with_next_recursive(0, None); - - let mut iter = node.grapheme_iter(); - - assert!(node.grapheme_count == 9); - assert!(node.line_count == 1); - assert!(Some("H") == iter.next()); - assert!(Some("i") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("t") == iter.next()); - assert!(Some("h") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("r") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("!") == iter.next()); - assert!(None == iter.next()); - } - - - #[test] - fn merge_line_with_next_recursive_2() { - let mut node = BufferNode::new(); - node.insert_text("Hi\n there\n people \nof the\n world!", 0); - - assert!(node.grapheme_count == 33); - assert!(node.line_count == 5); - - node.merge_line_with_next_recursive(2, None); - - let mut iter = node.grapheme_iter(); - - assert!(node.grapheme_count == 32); - assert!(node.line_count == 4); - assert!(Some("H") == iter.next()); - assert!(Some("i") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("t") == iter.next()); - assert!(Some("h") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("r") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("p") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("p") == iter.next()); - assert!(Some("l") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("f") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("t") == iter.next()); - assert!(Some("h") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("w") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("r") == iter.next()); - assert!(Some("l") == iter.next()); - assert!(Some("d") == iter.next()); - assert!(Some("!") == iter.next()); - assert!(None == iter.next()); - } - - - #[test] - fn merge_line_with_next_recursive_3() { - let mut node = BufferNode::new(); - node.insert_text("Hi\n there\n people \nof the\n world!", 0); - - assert!(node.grapheme_count == 33); - assert!(node.line_count == 5); - - node.merge_line_with_next_recursive(0, None); - - let mut iter = node.grapheme_iter(); - - assert!(node.grapheme_count == 32); - assert!(node.line_count == 4); - assert!(Some("H") == iter.next()); - assert!(Some("i") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("t") == iter.next()); - assert!(Some("h") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("r") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("p") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("p") == iter.next()); - assert!(Some("l") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("f") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("t") == iter.next()); - assert!(Some("h") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("w") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("r") == iter.next()); - assert!(Some("l") == iter.next()); - assert!(Some("d") == iter.next()); - assert!(Some("!") == iter.next()); - assert!(None == iter.next()); - } - - - #[test] - fn pull_out_line_recursive_1() { - let mut node = BufferNode::new(); - node.insert_text("Hi\n there\n people \nof the\n world!", 0); - - assert!(node.grapheme_count == 33); - assert!(node.line_count == 5); - - let line = node.pull_out_line_recursive(0).unwrap(); - assert!(line.to_string().as_slice() == "Hi"); - assert!(line.ending == LineEnding::LF); - - let mut iter = node.grapheme_iter(); - - assert!(node.grapheme_count == 30); - assert!(node.line_count == 4); - assert!(Some(" ") == iter.next()); - assert!(Some("t") == iter.next()); - assert!(Some("h") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("r") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("p") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("p") == iter.next()); - assert!(Some("l") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("f") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("t") == iter.next()); - assert!(Some("h") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("w") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("r") == iter.next()); - assert!(Some("l") == iter.next()); - assert!(Some("d") == iter.next()); - assert!(Some("!") == iter.next()); - assert!(None == iter.next()); - } - - - #[test] - fn pull_out_line_recursive_2() { - let mut node = BufferNode::new(); - node.insert_text("Hi\n there\n people \nof the\n world!", 0); - - assert!(node.grapheme_count == 33); - assert!(node.line_count == 5); - - let line = node.pull_out_line_recursive(2).unwrap(); - assert!(line.to_string().as_slice() == " people "); - assert!(line.ending == LineEnding::LF); - - let mut iter = node.grapheme_iter(); - - assert!(node.grapheme_count == 24); - assert!(node.line_count == 4); - assert!(Some("H") == iter.next()); - assert!(Some("i") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("t") == iter.next()); - assert!(Some("h") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("r") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("f") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("t") == iter.next()); - assert!(Some("h") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("w") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("r") == iter.next()); - assert!(Some("l") == iter.next()); - assert!(Some("d") == iter.next()); - assert!(Some("!") == iter.next()); - assert!(None == iter.next()); - } - - - #[test] - fn pull_out_line_recursive_3() { - let mut node = BufferNode::new(); - node.insert_text("Hi\n there\n people \nof the\n world!", 0); - - assert!(node.grapheme_count == 33); - assert!(node.line_count == 5); - - let line = node.pull_out_line_recursive(4).unwrap(); - assert!(line.to_string().as_slice() == " world!"); - assert!(line.ending == LineEnding::None); - - let mut iter = node.grapheme_iter(); - - assert!(node.grapheme_count == 26); - assert!(node.line_count == 4); - assert!(Some("H") == iter.next()); - assert!(Some("i") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("t") == iter.next()); - assert!(Some("h") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("r") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("p") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("p") == iter.next()); - assert!(Some("l") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(Some("o") == iter.next()); - assert!(Some("f") == iter.next()); - assert!(Some(" ") == iter.next()); - assert!(Some("t") == iter.next()); - assert!(Some("h") == iter.next()); - assert!(Some("e") == iter.next()); - assert!(Some("\n") == iter.next()); - assert!(None == iter.next()); - } - -} \ No newline at end of file