use ropey::Rope; pub struct TextBuffer { rope: Rope, } impl Default for TextBuffer { fn default() -> Self { Self::new() } } impl TextBuffer { #[must_use] pub fn new() -> Self { Self { rope: Rope::new() } } #[must_use] pub fn char_count(&self) -> usize { self.rope.len_chars() } #[must_use] pub fn line_count(&self) -> usize { self.rope.len_lines() } pub fn insert(&mut self, char_index: usize, text: &str) { self.rope.insert(char_index, text); } pub fn delete(&mut self, range: std::ops::Range) { self.rope.remove(range); } #[must_use] pub fn slice(&self, range: std::ops::Range) -> String { self.rope.slice(range).to_string() } #[must_use] pub fn line(&self, line_index: usize) -> String { let mut s = self.rope.line(line_index).to_string(); if s.ends_with('\n') { s.pop(); } s } } impl std::fmt::Display for TextBuffer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for chunk in self.rope.chunks() { write!(f, "{chunk}")?; } Ok(()) } }