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
663    pub fn reverse_selections(&mut self) {
664        let map = &self.display_map();
665        let mut new_selections: Vec<Selection<Point>> = Vec::new();
666        let disjoint = self.disjoint.clone();
667        for selection in disjoint
668            .iter()
669            .sorted_by(|first, second| Ord::cmp(&second.id, &first.id))
670            .collect::<Vec<&Selection<Anchor>>>()
671        {
672            new_selections.push(Selection {
673                id: self.new_selection_id(),
674                start: selection.start.to_display_point(map).to_point(map),
675                end: selection.end.to_display_point(map).to_point(map),
676                reversed: selection.reversed,
677                goal: selection.goal,
678            });
679        }
680        self.select(new_selections);
681    }
682
683    pub fn move_with(
684        &mut self,
685        mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
686    ) {
687        let mut changed = false;
688        let display_map = self.display_map();
689        let (_, selections) = self.collection.all_display(self.cx);
690        let selections = selections
691            .into_iter()
692            .map(|selection| {
693                let mut moved_selection = selection.clone();
694                move_selection(&display_map, &mut moved_selection);
695                if selection != moved_selection {
696                    changed = true;
697                }
698                moved_selection.map(|display_point| display_point.to_point(&display_map))
699            })
700            .collect();
701
702        if changed {
703            self.select(selections)
704        }
705    }
706
707    pub fn move_offsets_with(
708        &mut self,
709        mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection<usize>),
710    ) {
711        let mut changed = false;
712        let snapshot = self.buffer().clone();
713        let selections = self
714            .collection
715            .all::<usize>(self.cx)
716            .into_iter()
717            .map(|selection| {
718                let mut moved_selection = selection.clone();
719                move_selection(&snapshot, &mut moved_selection);
720                if selection != moved_selection {
721                    changed = true;
722                }
723                moved_selection
724            })
725            .collect();
726        drop(snapshot);
727
728        if changed {
729            self.select(selections)
730        }
731    }
732
733    pub fn move_heads_with(
734        &mut self,
735        mut update_head: impl FnMut(
736            &DisplaySnapshot,
737            DisplayPoint,
738            SelectionGoal,
739        ) -> (DisplayPoint, SelectionGoal),
740    ) {
741        self.move_with(|map, selection| {
742            let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
743            selection.set_head(new_head, new_goal);
744        });
745    }
746
747    pub fn move_cursors_with(
748        &mut self,
749        mut update_cursor_position: impl FnMut(
750            &DisplaySnapshot,
751            DisplayPoint,
752            SelectionGoal,
753        ) -> (DisplayPoint, SelectionGoal),
754    ) {
755        self.move_with(|map, selection| {
756            let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
757            selection.collapse_to(cursor, new_goal)
758        });
759    }
760
761    pub fn maybe_move_cursors_with(
762        &mut self,
763        mut update_cursor_position: impl FnMut(
764            &DisplaySnapshot,
765            DisplayPoint,
766            SelectionGoal,
767        ) -> Option<(DisplayPoint, SelectionGoal)>,
768    ) {
769        self.move_cursors_with(|map, point, goal| {
770            update_cursor_position(map, point, goal).unwrap_or((point, goal))
771        })
772    }
773
774    pub fn replace_cursors_with(
775        &mut self,
776        find_replacement_cursors: impl FnOnce(&DisplaySnapshot) -> Vec<DisplayPoint>,
777    ) {
778        let display_map = self.display_map();
779        let new_selections = find_replacement_cursors(&display_map)
780            .into_iter()
781            .map(|cursor| {
782                let cursor_point = cursor.to_point(&display_map);
783                Selection {
784                    id: post_inc(&mut self.collection.next_selection_id),
785                    start: cursor_point,
786                    end: cursor_point,
787                    reversed: false,
788                    goal: SelectionGoal::None,
789                }
790            })
791            .collect();
792        self.select(new_selections);
793    }
794
795    /// Compute new ranges for any selections that were located in excerpts that have
796    /// since been removed.
797    ///
798    /// Returns a `HashMap` indicating which selections whose former head position
799    /// was no longer present. The keys of the map are selection ids. The values are
800    /// the id of the new excerpt where the head of the selection has been moved.
801    pub fn refresh(&mut self) -> HashMap<usize, ExcerptId> {
802        let mut pending = self.collection.pending.take();
803        let mut selections_with_lost_position = HashMap::default();
804
805        let anchors_with_status = {
806            let buffer = self.buffer();
807            let disjoint_anchors = self
808                .disjoint
809                .iter()
810                .flat_map(|selection| [&selection.start, &selection.end]);
811            buffer.refresh_anchors(disjoint_anchors)
812        };
813        let adjusted_disjoint: Vec<_> = anchors_with_status
814            .chunks(2)
815            .map(|selection_anchors| {
816                let (anchor_ix, start, kept_start) = selection_anchors[0];
817                let (_, end, kept_end) = selection_anchors[1];
818                let selection = &self.disjoint[anchor_ix / 2];
819                let kept_head = if selection.reversed {
820                    kept_start
821                } else {
822                    kept_end
823                };
824                if !kept_head {
825                    selections_with_lost_position.insert(selection.id, selection.head().excerpt_id);
826                }
827
828                Selection {
829                    id: selection.id,
830                    start,
831                    end,
832                    reversed: selection.reversed,
833                    goal: selection.goal,
834                }
835            })
836            .collect();
837
838        if !adjusted_disjoint.is_empty() {
839            let map = self.display_map();
840            let resolved_selections = resolve_selections(adjusted_disjoint.iter(), &map).collect();
841            self.select::<usize>(resolved_selections);
842        }
843
844        if let Some(pending) = pending.as_mut() {
845            let buffer = self.buffer();
846            let anchors =
847                buffer.refresh_anchors([&pending.selection.start, &pending.selection.end]);
848            let (_, start, kept_start) = anchors[0];
849            let (_, end, kept_end) = anchors[1];
850            let kept_head = if pending.selection.reversed {
851                kept_start
852            } else {
853                kept_end
854            };
855            if !kept_head {
856                selections_with_lost_position
857                    .insert(pending.selection.id, pending.selection.head().excerpt_id);
858            }
859
860            pending.selection.start = start;
861            pending.selection.end = end;
862        }
863        self.collection.pending = pending;
864        self.selections_changed = true;
865
866        selections_with_lost_position
867    }
868}
869
870impl Deref for MutableSelectionsCollection<'_> {
871    type Target = SelectionsCollection;
872    fn deref(&self) -> &Self::Target {
873        self.collection
874    }
875}
876
877impl DerefMut for MutableSelectionsCollection<'_> {
878    fn deref_mut(&mut self) -> &mut Self::Target {
879        self.collection
880    }
881}
882
883// Panics if passed selections are not in order
884fn resolve_selections_display<'a>(
885    selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
886    map: &'a DisplaySnapshot,
887) -> impl 'a + Iterator<Item = Selection<DisplayPoint>> {
888    let (to_summarize, selections) = selections.into_iter().tee();
889    let mut summaries = map
890        .buffer_snapshot
891        .summaries_for_anchors::<Point, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
892        .into_iter();
893    let mut selections = selections
894        .map(move |s| {
895            let start = summaries.next().unwrap();
896            let end = summaries.next().unwrap();
897
898            let display_start = map.point_to_display_point(start, Bias::Left);
899            let display_end = if start == end {
900                map.point_to_display_point(end, Bias::Right)
901            } else {
902                map.point_to_display_point(end, Bias::Left)
903            };
904
905            Selection {
906                id: s.id,
907                start: display_start,
908                end: display_end,
909                reversed: s.reversed,
910                goal: s.goal,
911            }
912        })
913        .peekable();
914    iter::from_fn(move || {
915        let mut selection = selections.next()?;
916        while let Some(next_selection) = selections.peek() {
917            if selection.end >= next_selection.start {
918                selection.end = cmp::max(selection.end, next_selection.end);
919                selections.next();
920            } else {
921                break;
922            }
923        }
924        Some(selection)
925    })
926}
927
928// Panics if passed selections are not in order
929pub(crate) fn resolve_selections<'a, D, I>(
930    selections: I,
931    map: &'a DisplaySnapshot,
932) -> impl 'a + Iterator<Item = Selection<D>>
933where
934    D: TextDimension + Ord + Sub<D, Output = D>,
935    I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
936{
937    let (to_convert, selections) = resolve_selections_display(selections, map).tee();
938    let mut converted_endpoints =
939        map.buffer_snapshot
940            .dimensions_from_points::<D>(to_convert.flat_map(|s| {
941                let start = map.display_point_to_point(s.start, Bias::Left);
942                let end = map.display_point_to_point(s.end, Bias::Right);
943                [start, end]
944            }));
945    selections.map(move |s| {
946        let start = converted_endpoints.next().unwrap();
947        let end = converted_endpoints.next().unwrap();
948        Selection {
949            id: s.id,
950            start,
951            end,
952            reversed: s.reversed,
953            goal: s.goal,
954        }
955    })
956}