From 1b67f19edca3903d497f4565192b383d7a09adef Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 14 Dec 2021 12:13:19 +0100 Subject: [PATCH] Implement `MultiBuffer::set_active_selections` --- crates/editor/src/multi_buffer.rs | 80 +++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index a2d8558f905e46a2a95ea44f3ee3aa2de1994a6c..57b6bcc0969e298230967305a4ffb701a24c38b2 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -12,7 +12,7 @@ use language::{ use std::{ cell::{Ref, RefCell}, cmp, io, - iter::{FromIterator, Peekable}, + iter::{self, FromIterator, Peekable}, ops::{Range, Sub}, sync::Arc, time::{Duration, Instant, SystemTime}, @@ -346,19 +346,71 @@ impl MultiBuffer { selections: &[Selection], cx: &mut ModelContext, ) { - // TODO - let this = self.read(cx); - self.as_singleton().unwrap().update(cx, |buffer, cx| { - let buffer_snapshot = buffer.snapshot(); - let selections = selections.iter().map(|selection| Selection { - id: selection.id, - start: buffer_snapshot.anchor_before(selection.start.to_offset(&this)), - end: buffer_snapshot.anchor_before(selection.end.to_offset(&this)), - reversed: selection.reversed, - goal: selection.goal, + let mut selections_by_buffer: HashMap>> = + Default::default(); + let snapshot = self.read(cx); + let mut cursor = snapshot.excerpts.cursor::>(); + for selection in selections { + cursor.seek(&Some(&selection.start.excerpt_id), Bias::Left, &()); + while let Some(excerpt) = cursor.item() { + if excerpt.id > selection.end.excerpt_id { + break; + } + + let mut start = excerpt.range.start.clone(); + let mut end = excerpt.range.end.clone(); + if excerpt.id == selection.start.excerpt_id { + start = selection.start.text_anchor.clone(); + } + if excerpt.id == selection.end.excerpt_id { + end = selection.end.text_anchor.clone(); + } + selections_by_buffer + .entry(excerpt.buffer_id) + .or_default() + .push(Selection { + id: selection.id, + start, + end, + reversed: selection.reversed, + goal: selection.goal, + }); + + cursor.next(&()); + } + } + + for (buffer_id, mut selections) in selections_by_buffer { + self.buffers[&buffer_id].buffer.update(cx, |buffer, cx| { + selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer).unwrap()); + let mut selections = selections.into_iter().peekable(); + let merged_selections = Arc::from_iter(iter::from_fn(|| { + let mut selection = selections.next()?; + while let Some(next_selection) = selections.peek() { + if selection + .end + .cmp(&next_selection.start, buffer) + .unwrap() + .is_ge() + { + let next_selection = selections.next().unwrap(); + if next_selection + .end + .cmp(&selection.end, buffer) + .unwrap() + .is_ge() + { + selection.end = next_selection.end; + } + } else { + break; + } + } + Some(selection) + })); + buffer.set_active_selections(merged_selections, cx); }); - buffer.set_active_selections(Arc::from_iter(selections), cx); - }); + } } pub fn remove_active_selections(&mut self, cx: &mut ModelContext) { @@ -976,7 +1028,7 @@ impl MultiBufferSnapshot { let mut summaries = Vec::new(); while let Some(anchor) = anchors.peek() { let excerpt_id = &anchor.excerpt_id; - let excerpt_anchors = std::iter::from_fn(|| { + let excerpt_anchors = iter::from_fn(|| { let anchor = anchors.peek()?; if anchor.excerpt_id == *excerpt_id { Some(&anchors.next().unwrap().text_anchor)