diff --git a/crates/editor/src/display_map/suggestion_map.rs b/crates/editor/src/display_map/suggestion_map.rs index b02a5e8866110a30fbffa11fb2038e167e872ea9..95eca9f9e97af1291bdb6409f3d3b2f2cd0155ae 100644 --- a/crates/editor/src/display_map/suggestion_map.rs +++ b/crates/editor/src/display_map/suggestion_map.rs @@ -1,6 +1,10 @@ +use std::ops::{Add, AddAssign, Sub}; + +use crate::{ToOffset, ToPoint}; + use super::fold_map::{FoldEdit, FoldOffset, FoldSnapshot}; use gpui::fonts::HighlightStyle; -use language::{Edit, Rope}; +use language::{Bias, Edit, Patch, Rope}; use parking_lot::Mutex; pub type SuggestionEdit = Edit; @@ -8,16 +12,71 @@ pub type SuggestionEdit = Edit; #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] pub struct SuggestionOffset(pub usize); +impl Add for SuggestionOffset { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) + } +} + +impl Sub for SuggestionOffset { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self(self.0 - rhs.0) + } +} + +impl AddAssign for SuggestionOffset { + fn add_assign(&mut self, rhs: Self) { + self.0 += rhs.0; + } +} + #[derive(Clone)] pub struct Suggestion { - position: FoldOffset, + offset: FoldOffset, text: Rope, - highlight_style: HighlightStyle, } pub struct SuggestionMap(Mutex); impl SuggestionMap { + pub fn replace( + &mut self, + position: P, + text: T, + fold_snapshot: FoldSnapshot, + fold_edits: Vec, + ) -> (SuggestionSnapshot, Vec) + where + P: ToPoint, + T: Into, + { + let buffer_point = position.to_point(fold_snapshot.buffer_snapshot()); + let fold_point = fold_snapshot.to_fold_point(buffer_point, Bias::Left); + let fold_offset = fold_point.to_offset(&fold_snapshot); + let new_suggestion = Suggestion { + offset: fold_offset, + text: text.into(), + }; + + let (_, edits) = self.sync(fold_snapshot, fold_edits); + let mut snapshot = self.0.lock(); + let old = if let Some(suggestion) = snapshot.suggestion.take() { + SuggestionOffset(suggestion.offset.0) + ..SuggestionOffset(suggestion.offset.0 + suggestion.text.len()) + } else { + SuggestionOffset(new_suggestion.offset.0)..SuggestionOffset(new_suggestion.offset.0) + }; + let new = SuggestionOffset(new_suggestion.offset.0) + ..SuggestionOffset(new_suggestion.offset.0 + new_suggestion.text.len()); + let patch = Patch::new(edits).compose([SuggestionEdit { old, new }]); + snapshot.suggestion = Some(new_suggestion); + (snapshot.clone(), patch.into_inner()) + } + pub fn sync( &self, fold_snapshot: FoldSnapshot, @@ -32,10 +91,10 @@ impl SuggestionMap { let start = fold_edit.new.start; let end = FoldOffset(start.0 + fold_edit.old_len().0); if let Some(suggestion) = snapshot.suggestion.as_mut() { - if end < suggestion.position { - suggestion.position.0 += fold_edit.new_len().0; - suggestion.position.0 -= fold_edit.old_len().0; - } else if start > suggestion.position { + if end < suggestion.offset { + suggestion.offset.0 += fold_edit.new_len().0; + suggestion.offset.0 -= fold_edit.old_len().0; + } else if start > suggestion.offset { suggestion_old_len = suggestion.text.len(); suggestion_new_len = suggestion_old_len; } else {