selections_collection.rs

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