From 0527e3b283af0153cf13fa64fe73862a5b7655c8 Mon Sep 17 00:00:00 2001 From: Bernardo Date: Tue, 11 Dec 2018 19:07:17 +0100 Subject: rename Edit to TextEdit and AtomEdit to AtomTextEdit --- crates/ra_text_edit/src/text_edit.rs | 84 ++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 crates/ra_text_edit/src/text_edit.rs (limited to 'crates/ra_text_edit/src/text_edit.rs') diff --git a/crates/ra_text_edit/src/text_edit.rs b/crates/ra_text_edit/src/text_edit.rs new file mode 100644 index 000000000..fb46f046d --- /dev/null +++ b/crates/ra_text_edit/src/text_edit.rs @@ -0,0 +1,84 @@ +use crate::AtomTextEdit; +use crate::text_utils::contains_offset_nonstrict; +use text_unit::{TextRange, TextUnit}; + +#[derive(Debug, Clone)] +pub struct TextEdit { + atoms: Vec, +} + +#[derive(Debug)] +pub struct TextEditBuilder { + atoms: Vec, +} + +impl TextEditBuilder { + pub fn new() -> TextEditBuilder { + TextEditBuilder { atoms: Vec::new() } + } + pub fn replace(&mut self, range: TextRange, replace_with: String) { + self.atoms.push(AtomTextEdit::replace(range, replace_with)) + } + pub fn delete(&mut self, range: TextRange) { + self.atoms.push(AtomTextEdit::delete(range)) + } + pub fn insert(&mut self, offset: TextUnit, text: String) { + self.atoms.push(AtomTextEdit::insert(offset, text)) + } + pub fn finish(self) -> TextEdit { + let mut atoms = self.atoms; + atoms.sort_by_key(|a| (a.delete.start(), a.delete.end())); + for (a1, a2) in atoms.iter().zip(atoms.iter().skip(1)) { + assert!(a1.delete.end() <= a2.delete.start()) + } + TextEdit { atoms } + } + pub fn invalidates_offset(&self, offset: TextUnit) -> bool { + self.atoms + .iter() + .any(|atom| contains_offset_nonstrict(atom.delete, offset)) + } +} + +impl TextEdit { + pub fn into_atoms(self) -> Vec { + self.atoms + } + + pub fn apply(&self, text: &str) -> String { + let mut total_len = text.len(); + for atom in self.atoms.iter() { + total_len += atom.insert.len(); + total_len -= u32::from(atom.delete.end() - atom.delete.start()) as usize; + } + let mut buf = String::with_capacity(total_len); + let mut prev = 0; + for atom in self.atoms.iter() { + let start = u32::from(atom.delete.start()) as usize; + let end = u32::from(atom.delete.end()) as usize; + if start > prev { + buf.push_str(&text[prev..start]); + } + buf.push_str(&atom.insert); + prev = end; + } + buf.push_str(&text[prev..text.len()]); + assert_eq!(buf.len(), total_len); + buf + } + + pub fn apply_to_offset(&self, offset: TextUnit) -> Option { + let mut res = offset; + for atom in self.atoms.iter() { + if atom.delete.start() >= offset { + break; + } + if offset < atom.delete.end() { + return None; + } + res += TextUnit::of_str(&atom.insert); + res -= atom.delete.len(); + } + Some(res) + } +} -- cgit v1.2.3