ged/core/src/text_buffer/mod.rs

145 lines
4.3 KiB
Rust

use std::rc::Rc;
mod rope;
use rope::Rope;
pub struct TextBuffer {
contents: Rc<Rope>,
}
pub enum Point {
End,
}
impl TextBuffer {
pub fn new() -> Self {
Self {
contents: Rope::empty(),
}
}
pub fn num_bytes(&self) -> usize {
self.contents.total_bytes()
}
pub fn num_chars(&self) -> usize {
self.contents.total_chars()
}
pub fn num_lines(&self) -> usize {
let num_chars = self.num_chars();
if num_chars == 0 {
0
} else {
dbg!(self.contents.total_lines())
+ if self
.contents
.get_char_at_index(self.contents.total_chars() - 1)
== '\n'
{
0
} else {
1
}
}
}
pub fn insert_char(&mut self, c: char, point: Point) {
match point {
Point::End => {
self.contents = self
.contents
.insert_at_char_index(self.contents.total_chars(), c)
}
}
}
}
impl Default for TextBuffer {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_creates_empty_buffer() {
let target = TextBuffer::new();
assert_eq!(0, target.num_bytes());
assert_eq!(0, target.num_chars());
assert_eq!(0, target.num_lines());
}
#[test]
fn insert_char_at_end_increases_counts_as_expected() {
let mut target = TextBuffer::new();
target.insert_char('A', Point::End);
assert_eq!(1, target.num_bytes());
assert_eq!(1, target.num_chars());
assert_eq!(1, target.num_lines());
target.insert_char(' ', Point::End);
assert_eq!(2, target.num_bytes());
assert_eq!(2, target.num_chars());
assert_eq!(1, target.num_lines());
target.insert_char('c', Point::End);
assert_eq!(3, target.num_bytes());
assert_eq!(3, target.num_chars());
assert_eq!(1, target.num_lines());
target.insert_char('a', Point::End);
assert_eq!(4, target.num_bytes());
assert_eq!(4, target.num_chars());
assert_eq!(1, target.num_lines());
target.insert_char('t', Point::End);
assert_eq!(5, target.num_bytes());
assert_eq!(5, target.num_chars());
assert_eq!(1, target.num_lines());
target.insert_char('\n', Point::End);
assert_eq!(6, target.num_bytes());
assert_eq!(6, target.num_chars());
assert_eq!(1, target.num_lines());
target.insert_char('A', Point::End);
assert_eq!(7, target.num_bytes());
assert_eq!(7, target.num_chars());
assert_eq!(2, target.num_lines());
target.insert_char('\n', Point::End);
assert_eq!(8, target.num_bytes());
assert_eq!(8, target.num_chars());
assert_eq!(2, target.num_lines());
target.insert_char('\n', Point::End);
assert_eq!(9, target.num_bytes());
assert_eq!(9, target.num_chars());
assert_eq!(3, target.num_lines());
target.insert_char('*', Point::End);
assert_eq!(10, target.num_bytes());
assert_eq!(10, target.num_chars());
assert_eq!(4, target.num_lines());
target.insert_char('*', Point::End);
assert_eq!(11, target.num_bytes());
assert_eq!(11, target.num_chars());
assert_eq!(4, target.num_lines());
target.insert_char(' ', Point::End);
assert_eq!(12, target.num_bytes());
assert_eq!(12, target.num_chars());
assert_eq!(4, target.num_lines());
target.insert_char('猫', Point::End);
assert_eq!(15, target.num_bytes());
assert_eq!(13, target.num_chars());
assert_eq!(4, target.num_lines());
target.insert_char(' ', Point::End);
assert_eq!(16, target.num_bytes());
assert_eq!(14, target.num_chars());
assert_eq!(4, target.num_lines());
target.insert_char('\n', Point::End);
assert_eq!(17, target.num_bytes());
assert_eq!(15, target.num_chars());
assert_eq!(4, target.num_lines());
target.insert_char('_', Point::End);
assert_eq!(18, target.num_bytes());
assert_eq!(16, target.num_chars());
assert_eq!(5, target.num_lines());
}
}