145 lines
4.3 KiB
Rust
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());
|
|
}
|
|
}
|