1use std::{
2 cell::Ref,
3 iter, mem,
4 ops::{Deref, DerefMut, Range, Sub},
5 sync::Arc,
6};
7
8use collections::HashMap;
9use gpui::{AppContext, Model, Pixels};
10use itertools::Itertools;
11use language::{Bias, Point, Selection, SelectionGoal, TextDimension, ToPoint};
12use util::post_inc;
13
14use crate::{
15 display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint},
16 movement::TextLayoutDetails,
17 Anchor, DisplayPoint, DisplayRow, ExcerptId, MultiBuffer, MultiBufferSnapshot, SelectMode,
18 ToOffset,
19};
20
21#[derive(Debug, Clone)]
22pub struct PendingSelection {
23 pub selection: Selection<Anchor>,
24 pub mode: SelectMode,
25}
26
27#[derive(Debug, Clone)]
28pub struct SelectionsCollection {
29 display_map: Model<DisplayMap>,
30 buffer: Model<MultiBuffer>,
31 pub next_selection_id: usize,
32 pub line_mode: bool,
33 /// The non-pending, non-overlapping selections.
34 /// The [SelectionsCollection::pending] selection could possibly overlap these
35 pub disjoint: Arc<[Selection<Anchor>]>,
36 /// A pending selection, such as when the mouse is being dragged
37 pub pending: Option<PendingSelection>,
38}
39
40impl SelectionsCollection {
41 pub fn new(display_map: Model<DisplayMap>, buffer: Model<MultiBuffer>) -> Self {
42 Self {
43 display_map,
44 buffer,
45 next_selection_id: 1,
46 line_mode: false,
47 disjoint: Arc::from([]),
48 pending: Some(PendingSelection {
49 selection: Selection {
50 id: 0,
51 start: Anchor::min(),
52 end: Anchor::min(),
53 reversed: false,
54 goal: SelectionGoal::None,
55 },
56 mode: SelectMode::Character,
57 }),
58 }
59 }
60
61 pub fn display_map(&self, cx: &mut AppContext) -> DisplaySnapshot {
62 self.display_map.update(cx, |map, cx| map.snapshot(cx))
63 }
64
65 fn buffer<'a>(&self, cx: &'a AppContext) -> Ref<'a, MultiBufferSnapshot> {
66 self.buffer.read(cx).read(cx)
67 }
68
69 pub fn clone_state(&mut self, other: &SelectionsCollection) {
70 self.next_selection_id = other.next_selection_id;
71 self.line_mode = other.line_mode;
72 self.disjoint = other.disjoint.clone();
73 self.pending.clone_from(&other.pending);
74 }
75
76 pub fn count(&self) -> usize {
77 let mut count = self.disjoint.len();
78 if self.pending.is_some() {
79 count += 1;
80 }
81 count
82 }
83
84 /// The non-pending, non-overlapping selections. There could still be a pending
85 /// selection that overlaps these if the mouse is being dragged, etc. Returned as
86 /// selections over Anchors.
87 pub fn disjoint_anchors(&self) -> Arc<[Selection<Anchor>]> {
88 self.disjoint.clone()
89 }
90
91 pub fn pending_anchor(&self) -> Option<Selection<Anchor>> {
92 self.pending
93 .as_ref()
94 .map(|pending| pending.selection.clone())
95 }
96
97 pub fn pending<D: TextDimension + Ord + Sub<D, Output = D>>(
98 &self,
99 cx: &AppContext,
100 ) -> Option<Selection<D>> {
101 self.pending_anchor()
102 .as_ref()
103 .map(|pending| pending.map(|p| p.summary::<D>(&self.buffer(cx))))
104 }
105
106 pub(crate) fn pending_mode(&self) -> Option<SelectMode> {
107 self.pending.as_ref().map(|pending| pending.mode.clone())
108 }
109
110 pub fn all<'a, D>(&self, cx: &AppContext) -> Vec<Selection<D>>
111 where
112 D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
113 {
114 let disjoint_anchors = &self.disjoint;
115 let mut disjoint =
116 resolve_multiple::<D, _>(disjoint_anchors.iter(), &self.buffer(cx)).peekable();
117
118 let mut pending_opt = self.pending::<D>(cx);
119
120 iter::from_fn(move || {
121 if let Some(pending) = pending_opt.as_mut() {
122 while let Some(next_selection) = disjoint.peek() {
123 if pending.start <= next_selection.end && pending.end >= next_selection.start {
124 let next_selection = disjoint.next().unwrap();
125 if next_selection.start < pending.start {
126 pending.start = next_selection.start;
127 }
128 if next_selection.end > pending.end {
129 pending.end = next_selection.end;
130 }
131 } else if next_selection.end < pending.start {
132 return disjoint.next();
133 } else {
134 break;
135 }
136 }
137
138 pending_opt.take()
139 } else {
140 disjoint.next()
141 }
142 })
143 .collect()
144 }
145
146 /// Returns all of the selections, adjusted to take into account the selection line_mode
147 pub fn all_adjusted(&self, cx: &mut AppContext) -> Vec<Selection<Point>> {
148 let mut selections = self.all::<Point>(cx);
149 if self.line_mode {
150 let map = self.display_map(cx);
151 for selection in &mut selections {
152 let new_range = map.expand_to_line(selection.range());
153 selection.start = new_range.start;
154 selection.end = new_range.end;
155 }
156 }
157 selections
158 }
159
160 pub fn all_adjusted_display(
161 &self,
162 cx: &mut AppContext,
163 ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
164 if self.line_mode {
165 let selections = self.all::<Point>(cx);
166 let map = self.display_map(cx);
167 let result = selections
168 .into_iter()
169 .map(|mut selection| {
170 let new_range = map.expand_to_line(selection.range());
171 selection.start = new_range.start;
172 selection.end = new_range.end;
173 selection.map(|point| point.to_display_point(&map))
174 })
175 .collect();
176 (map, result)
177 } else {
178 self.all_display(cx)
179 }
180 }
181
182 pub fn disjoint_in_range<'a, D>(
183 &self,
184 range: Range<Anchor>,
185 cx: &AppContext,
186 ) -> Vec<Selection<D>>
187 where
188 D: 'a + TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
189 {
190 let buffer = self.buffer(cx);
191 let start_ix = match self
192 .disjoint
193 .binary_search_by(|probe| probe.end.cmp(&range.start, &buffer))
194 {
195 Ok(ix) | Err(ix) => ix,
196 };
197 let end_ix = match self
198 .disjoint
199 .binary_search_by(|probe| probe.start.cmp(&range.end, &buffer))
200 {
201 Ok(ix) => ix + 1,
202 Err(ix) => ix,
203 };
204 resolve_multiple(&self.disjoint[start_ix..end_ix], &buffer).collect()
205 }
206
207 pub fn all_display(
208 &self,
209 cx: &mut AppContext,
210 ) -> (DisplaySnapshot, Vec<Selection<DisplayPoint>>) {
211 let display_map = self.display_map(cx);
212 let selections = self
213 .all::<Point>(cx)
214 .into_iter()
215 .map(|selection| selection.map(|point| point.to_display_point(&display_map)))
216 .collect();
217 (display_map, selections)
218 }
219
220 pub fn newest_anchor(&self) -> &Selection<Anchor> {
221 self.pending
222 .as_ref()
223 .map(|s| &s.selection)
224 .or_else(|| self.disjoint.iter().max_by_key(|s| s.id))
225 .unwrap()
226 }
227
228 pub fn newest<D: TextDimension + Ord + Sub<D, Output = D>>(
229 &self,
230 cx: &AppContext,
231 ) -> Selection<D> {
232 resolve(self.newest_anchor(), &self.buffer(cx))
233 }
234
235 pub fn newest_display(&self, cx: &mut AppContext) -> Selection<DisplayPoint> {
236 let display_map = self.display_map(cx);
237 let selection = self
238 .newest_anchor()
239 .map(|point| point.to_display_point(&display_map));
240 selection
241 }
242
243 pub fn oldest_anchor(&self) -> &Selection<Anchor> {
244 self.disjoint
245 .iter()
246 .min_by_key(|s| s.id)
247 .or_else(|| self.pending.as_ref().map(|p| &p.selection))
248 .unwrap()
249 }
250
251 pub fn oldest<D: TextDimension + Ord + Sub<D, Output = D>>(
252 &self,
253 cx: &AppContext,
254 ) -> Selection<D> {
255 resolve(self.oldest_anchor(), &self.buffer(cx))
256 }
257
258 pub fn first_anchor(&self) -> Selection<Anchor> {
259 self.disjoint[0].clone()
260 }
261
262 pub fn first<D: TextDimension + Ord + Sub<D, Output = D>>(
263 &self,
264 cx: &AppContext,
265 ) -> Selection<D> {
266 self.all(cx).first().unwrap().clone()
267 }
268
269 pub fn last<D: TextDimension + Ord + Sub<D, Output = D>>(
270 &self,
271 cx: &AppContext,
272 ) -> Selection<D> {
273 self.all(cx).last().unwrap().clone()
274 }
275
276 pub fn disjoint_anchor_ranges(&self) -> Vec<Range<Anchor>> {
277 self.disjoint_anchors()
278 .iter()
279 .map(|s| s.start..s.end)
280 .collect()
281 }
282
283 #[cfg(any(test, feature = "test-support"))]
284 pub fn ranges<D: TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug>(
285 &self,
286 cx: &AppContext,
287 ) -> Vec<Range<D>> {
288 self.all::<D>(cx)
289 .iter()
290 .map(|s| {
291 if s.reversed {
292 s.end.clone()..s.start.clone()
293 } else {
294 s.start.clone()..s.end.clone()
295 }
296 })
297 .collect()
298 }
299
300 #[cfg(any(test, feature = "test-support"))]
301 pub fn display_ranges(&self, cx: &mut AppContext) -> Vec<Range<DisplayPoint>> {
302 let display_map = self.display_map(cx);
303 self.disjoint_anchors()
304 .iter()
305 .chain(self.pending_anchor().as_ref())
306 .map(|s| {
307 if s.reversed {
308 s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map)
309 } else {
310 s.start.to_display_point(&display_map)..s.end.to_display_point(&display_map)
311 }
312 })
313 .collect()
314 }
315
316 pub fn build_columnar_selection(
317 &mut self,
318 display_map: &DisplaySnapshot,
319 row: DisplayRow,
320 positions: &Range<Pixels>,
321 reversed: bool,
322 text_layout_details: &TextLayoutDetails,
323 ) -> Option<Selection<Point>> {
324 let is_empty = positions.start == positions.end;
325 let line_len = display_map.line_len(row);
326
327 let line = display_map.layout_row(row, &text_layout_details);
328
329 let start_col = line.closest_index_for_x(positions.start) as u32;
330 if start_col < line_len || (is_empty && positions.start == line.width) {
331 let start = DisplayPoint::new(row, start_col);
332 let end_col = line.closest_index_for_x(positions.end) as u32;
333 let end = DisplayPoint::new(row, end_col);
334
335 Some(Selection {
336 id: post_inc(&mut self.next_selection_id),
337 start: start.to_point(display_map),
338 end: end.to_point(display_map),
339 reversed,
340 goal: SelectionGoal::HorizontalRange {
341 start: positions.start.into(),
342 end: positions.end.into(),
343 },
344 })
345 } else {
346 None
347 }
348 }
349
350 pub(crate) fn change_with<R>(
351 &mut self,
352 cx: &mut AppContext,
353 change: impl FnOnce(&mut MutableSelectionsCollection) -> R,
354 ) -> (bool, R) {
355 let mut mutable_collection = MutableSelectionsCollection {
356 collection: self,
357 selections_changed: false,
358 cx,
359 };
360
361 let result = change(&mut mutable_collection);
362 assert!(
363 !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(),
364 "There must be at least one selection"
365 );
366 (mutable_collection.selections_changed, result)
367 }
368}
369
370pub struct MutableSelectionsCollection<'a> {
371 collection: &'a mut SelectionsCollection,
372 selections_changed: bool,
373 cx: &'a mut AppContext,
374}
375
376impl<'a> MutableSelectionsCollection<'a> {
377 pub fn display_map(&mut self) -> DisplaySnapshot {
378 self.collection.display_map(self.cx)
379 }
380
381 fn buffer(&self) -> Ref<MultiBufferSnapshot> {
382 self.collection.buffer(self.cx)
383 }
384
385 pub fn clear_disjoint(&mut self) {
386 self.collection.disjoint = Arc::from([]);
387 }
388
389 pub fn delete(&mut self, selection_id: usize) {
390 let mut changed = false;
391 self.collection.disjoint = self
392 .disjoint
393 .iter()
394 .filter(|selection| {
395 let found = selection.id == selection_id;
396 changed |= found;
397 !found
398 })
399 .cloned()
400 .collect();
401
402 self.selections_changed |= changed;
403 }
404
405 pub fn clear_pending(&mut self) {
406 if self.collection.pending.is_some() {
407 self.collection.pending = None;
408 self.selections_changed = true;
409 }
410 }
411
412 pub(crate) fn set_pending_anchor_range(&mut self, range: Range<Anchor>, mode: SelectMode) {
413 self.collection.pending = Some(PendingSelection {
414 selection: Selection {
415 id: post_inc(&mut self.collection.next_selection_id),
416 start: range.start,
417 end: range.end,
418 reversed: false,
419 goal: SelectionGoal::None,
420 },
421 mode,
422 });
423 self.selections_changed = true;
424 }
425
426 pub(crate) fn set_pending_display_range(
427 &mut self,
428 range: Range<DisplayPoint>,
429 mode: SelectMode,
430 ) {
431 let (start, end, reversed) = {
432 let display_map = self.display_map();
433 let buffer = self.buffer();
434 let mut start = range.start;
435 let mut end = range.end;
436 let reversed = if start > end {
437 mem::swap(&mut start, &mut end);
438 true
439 } else {
440 false
441 };
442
443 let end_bias = if end > start { Bias::Left } else { Bias::Right };
444 (
445 buffer.anchor_before(start.to_point(&display_map)),
446 buffer.anchor_at(end.to_point(&display_map), end_bias),
447 reversed,
448 )
449 };
450
451 let new_pending = PendingSelection {
452 selection: Selection {
453 id: post_inc(&mut self.collection.next_selection_id),
454 start,
455 end,
456 reversed,
457 goal: SelectionGoal::None,
458 },
459 mode,
460 };
461
462 self.collection.pending = Some(new_pending);
463 self.selections_changed = true;
464 }
465
466 pub(crate) fn set_pending(&mut self, selection: Selection<Anchor>, mode: SelectMode) {
467 self.collection.pending = Some(PendingSelection { selection, mode });
468 self.selections_changed = true;
469 }
470
471 pub fn try_cancel(&mut self) -> bool {
472 if let Some(pending) = self.collection.pending.take() {
473 if self.disjoint.is_empty() {
474 self.collection.disjoint = Arc::from([pending.selection]);
475 }
476 self.selections_changed = true;
477 return true;
478 }
479
480 let mut oldest = self.oldest_anchor().clone();
481 if self.count() > 1 {
482 self.collection.disjoint = Arc::from([oldest]);
483 self.selections_changed = true;
484 return true;
485 }
486
487 if !oldest.start.cmp(&oldest.end, &self.buffer()).is_eq() {
488 let head = oldest.head();
489 oldest.start = head;
490 oldest.end = head;
491 self.collection.disjoint = Arc::from([oldest]);
492 self.selections_changed = true;
493 return true;
494 }
495
496 false
497 }
498
499 pub fn insert_range<T>(&mut self, range: Range<T>)
500 where
501 T: 'a + ToOffset + ToPoint + TextDimension + Ord + Sub<T, Output = T> + std::marker::Copy,
502 {
503 let mut selections = self.all(self.cx);
504 let mut start = range.start.to_offset(&self.buffer());
505 let mut end = range.end.to_offset(&self.buffer());
506 let reversed = if start > end {
507 mem::swap(&mut start, &mut end);
508 true
509 } else {
510 false
511 };
512 selections.push(Selection {
513 id: post_inc(&mut self.collection.next_selection_id),
514 start,
515 end,
516 reversed,
517 goal: SelectionGoal::None,
518 });
519 self.select(selections);
520 }
521
522 pub fn select<T>(&mut self, mut selections: Vec<Selection<T>>)
523 where
524 T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
525 {
526 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
527 selections.sort_unstable_by_key(|s| s.start);
528 // Merge overlapping selections.
529 let mut i = 1;
530 while i < selections.len() {
531 if selections[i - 1].end >= selections[i].start {
532 let removed = selections.remove(i);
533 if removed.start < selections[i - 1].start {
534 selections[i - 1].start = removed.start;
535 }
536 if removed.end > selections[i - 1].end {
537 selections[i - 1].end = removed.end;
538 }
539 } else {
540 i += 1;
541 }
542 }
543
544 self.collection.disjoint = Arc::from_iter(selections.into_iter().map(|selection| {
545 let end_bias = if selection.end > selection.start {
546 Bias::Left
547 } else {
548 Bias::Right
549 };
550 Selection {
551 id: selection.id,
552 start: buffer.anchor_after(selection.start),
553 end: buffer.anchor_at(selection.end, end_bias),
554 reversed: selection.reversed,
555 goal: selection.goal,
556 }
557 }));
558
559 self.collection.pending = None;
560 self.selections_changed = true;
561 }
562
563 pub fn select_anchors(&mut self, selections: Vec<Selection<Anchor>>) {
564 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
565 let resolved_selections =
566 resolve_multiple::<usize, _>(&selections, &buffer).collect::<Vec<_>>();
567 self.select(resolved_selections);
568 }
569
570 pub fn select_ranges<I, T>(&mut self, ranges: I)
571 where
572 I: IntoIterator<Item = Range<T>>,
573 T: ToOffset,
574 {
575 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
576 let ranges = ranges
577 .into_iter()
578 .map(|range| range.start.to_offset(&buffer)..range.end.to_offset(&buffer));
579 self.select_offset_ranges(ranges);
580 }
581
582 fn select_offset_ranges<I>(&mut self, ranges: I)
583 where
584 I: IntoIterator<Item = Range<usize>>,
585 {
586 let selections = ranges
587 .into_iter()
588 .map(|range| {
589 let mut start = range.start;
590 let mut end = range.end;
591 let reversed = if start > end {
592 mem::swap(&mut start, &mut end);
593 true
594 } else {
595 false
596 };
597 Selection {
598 id: post_inc(&mut self.collection.next_selection_id),
599 start,
600 end,
601 reversed,
602 goal: SelectionGoal::None,
603 }
604 })
605 .collect::<Vec<_>>();
606
607 self.select(selections)
608 }
609
610 pub fn select_anchor_ranges<I>(&mut self, ranges: I)
611 where
612 I: IntoIterator<Item = Range<Anchor>>,
613 {
614 let buffer = self.buffer.read(self.cx).snapshot(self.cx);
615 let selections = ranges
616 .into_iter()
617 .map(|range| {
618 let mut start = range.start;
619 let mut end = range.end;
620 let reversed = if start.cmp(&end, &buffer).is_gt() {
621 mem::swap(&mut start, &mut end);
622 true
623 } else {
624 false
625 };
626 Selection {
627 id: post_inc(&mut self.collection.next_selection_id),
628 start,
629 end,
630 reversed,
631 goal: SelectionGoal::None,
632 }
633 })
634 .collect::<Vec<_>>();
635 self.select_anchors(selections)
636 }
637
638 pub fn new_selection_id(&mut self) -> usize {
639 post_inc(&mut self.next_selection_id)
640 }
641
642 pub fn select_display_ranges<T>(&mut self, ranges: T)
643 where
644 T: IntoIterator<Item = Range<DisplayPoint>>,
645 {
646 let display_map = self.display_map();
647 let selections = ranges
648 .into_iter()
649 .map(|range| {
650 let mut start = range.start;
651 let mut end = range.end;
652 let reversed = if start > end {
653 mem::swap(&mut start, &mut end);
654 true
655 } else {
656 false
657 };
658 Selection {
659 id: post_inc(&mut self.collection.next_selection_id),
660 start: start.to_point(&display_map),
661 end: end.to_point(&display_map),
662 reversed,
663 goal: SelectionGoal::None,
664 }
665 })
666 .collect();
667 self.select(selections);
668 }
669
670 pub fn move_with(
671 &mut self,
672 mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
673 ) {
674 let mut changed = false;
675 let display_map = self.display_map();
676 let selections = self
677 .all::<Point>(self.cx)
678 .into_iter()
679 .map(|selection| {
680 let mut moved_selection =
681 selection.map(|point| point.to_display_point(&display_map));
682 move_selection(&display_map, &mut moved_selection);
683 let moved_selection =
684 moved_selection.map(|display_point| display_point.to_point(&display_map));
685 if selection != moved_selection {
686 changed = true;
687 }
688 moved_selection
689 })
690 .collect();
691
692 if changed {
693 self.select(selections)
694 }
695 }
696
697 pub fn move_offsets_with(
698 &mut self,
699 mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection<usize>),
700 ) {
701 let mut changed = false;
702 let snapshot = self.buffer().clone();
703 let selections = self
704 .all::<usize>(self.cx)
705 .into_iter()
706 .map(|selection| {
707 let mut moved_selection = selection.clone();
708 move_selection(&snapshot, &mut moved_selection);
709 if selection != moved_selection {
710 changed = true;
711 }
712 moved_selection
713 })
714 .collect();
715 drop(snapshot);
716
717 if changed {
718 self.select(selections)
719 }
720 }
721
722 pub fn move_heads_with(
723 &mut self,
724 mut update_head: impl FnMut(
725 &DisplaySnapshot,
726 DisplayPoint,
727 SelectionGoal,
728 ) -> (DisplayPoint, SelectionGoal),
729 ) {
730 self.move_with(|map, selection| {
731 let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
732 selection.set_head(new_head, new_goal);
733 });
734 }
735
736 pub fn move_cursors_with(
737 &mut self,
738 mut update_cursor_position: impl FnMut(
739 &DisplaySnapshot,
740 DisplayPoint,
741 SelectionGoal,
742 ) -> (DisplayPoint, SelectionGoal),
743 ) {
744 self.move_with(|map, selection| {
745 let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
746 selection.collapse_to(cursor, new_goal)
747 });
748 }
749
750 pub fn maybe_move_cursors_with(
751 &mut self,
752 mut update_cursor_position: impl FnMut(
753 &DisplaySnapshot,
754 DisplayPoint,
755 SelectionGoal,
756 ) -> Option<(DisplayPoint, SelectionGoal)>,
757 ) {
758 self.move_cursors_with(|map, point, goal| {
759 update_cursor_position(map, point, goal).unwrap_or((point, goal))
760 })
761 }
762
763 pub fn replace_cursors_with(
764 &mut self,
765 mut find_replacement_cursors: impl FnMut(&DisplaySnapshot) -> Vec<DisplayPoint>,
766 ) {
767 let display_map = self.display_map();
768 let new_selections = find_replacement_cursors(&display_map)
769 .into_iter()
770 .map(|cursor| {
771 let cursor_point = cursor.to_point(&display_map);
772 Selection {
773 id: post_inc(&mut self.collection.next_selection_id),
774 start: cursor_point,
775 end: cursor_point,
776 reversed: false,
777 goal: SelectionGoal::None,
778 }
779 })
780 .collect();
781 self.select(new_selections);
782 }
783
784 /// Compute new ranges for any selections that were located in excerpts that have
785 /// since been removed.
786 ///
787 /// Returns a `HashMap` indicating which selections whose former head position
788 /// was no longer present. The keys of the map are selection ids. The values are
789 /// the id of the new excerpt where the head of the selection has been moved.
790 pub fn refresh(&mut self) -> HashMap<usize, ExcerptId> {
791 let mut pending = self.collection.pending.take();
792 let mut selections_with_lost_position = HashMap::default();
793
794 let anchors_with_status = {
795 let buffer = self.buffer();
796 let disjoint_anchors = self
797 .disjoint
798 .iter()
799 .flat_map(|selection| [&selection.start, &selection.end]);
800 buffer.refresh_anchors(disjoint_anchors)
801 };
802 let adjusted_disjoint: Vec<_> = anchors_with_status
803 .chunks(2)
804 .map(|selection_anchors| {
805 let (anchor_ix, start, kept_start) = selection_anchors[0];
806 let (_, end, kept_end) = selection_anchors[1];
807 let selection = &self.disjoint[anchor_ix / 2];
808 let kept_head = if selection.reversed {
809 kept_start
810 } else {
811 kept_end
812 };
813 if !kept_head {
814 selections_with_lost_position.insert(selection.id, selection.head().excerpt_id);
815 }
816
817 Selection {
818 id: selection.id,
819 start,
820 end,
821 reversed: selection.reversed,
822 goal: selection.goal,
823 }
824 })
825 .collect();
826
827 if !adjusted_disjoint.is_empty() {
828 let resolved_selections =
829 resolve_multiple(adjusted_disjoint.iter(), &self.buffer()).collect();
830 self.select::<usize>(resolved_selections);
831 }
832
833 if let Some(pending) = pending.as_mut() {
834 let buffer = self.buffer();
835 let anchors =
836 buffer.refresh_anchors([&pending.selection.start, &pending.selection.end]);
837 let (_, start, kept_start) = anchors[0];
838 let (_, end, kept_end) = anchors[1];
839 let kept_head = if pending.selection.reversed {
840 kept_start
841 } else {
842 kept_end
843 };
844 if !kept_head {
845 selections_with_lost_position
846 .insert(pending.selection.id, pending.selection.head().excerpt_id);
847 }
848
849 pending.selection.start = start;
850 pending.selection.end = end;
851 }
852 self.collection.pending = pending;
853 self.selections_changed = true;
854
855 selections_with_lost_position
856 }
857}
858
859impl<'a> Deref for MutableSelectionsCollection<'a> {
860 type Target = SelectionsCollection;
861 fn deref(&self) -> &Self::Target {
862 self.collection
863 }
864}
865
866impl<'a> DerefMut for MutableSelectionsCollection<'a> {
867 fn deref_mut(&mut self) -> &mut Self::Target {
868 self.collection
869 }
870}
871
872// Panics if passed selections are not in order
873pub(crate) fn resolve_multiple<'a, D, I>(
874 selections: I,
875 snapshot: &MultiBufferSnapshot,
876) -> impl 'a + Iterator<Item = Selection<D>>
877where
878 D: TextDimension + Ord + Sub<D, Output = D> + std::fmt::Debug,
879 I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
880{
881 let (to_summarize, selections) = selections.into_iter().tee();
882 let mut summaries = snapshot
883 .summaries_for_anchors::<D, _>(
884 to_summarize
885 .flat_map(|s| [&s.start, &s.end])
886 .collect::<Vec<_>>(),
887 )
888 .into_iter();
889 selections.map(move |s| Selection {
890 id: s.id,
891 start: summaries.next().unwrap(),
892 end: summaries.next().unwrap(),
893 reversed: s.reversed,
894 goal: s.goal,
895 })
896}
897
898fn resolve<D: TextDimension + Ord + Sub<D, Output = D>>(
899 selection: &Selection<Anchor>,
900 buffer: &MultiBufferSnapshot,
901) -> Selection<D> {
902 selection.map(|p| p.summary::<D>(buffer))
903}