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