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