selections_collection.rs

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