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