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
356        let line = display_map.layout_row(row, text_layout_details);
357
358        let start_col = line.closest_index_for_x(positions.start) as u32;
359        if start_col < line_len || (is_empty && positions.start == line.width) {
360            let start = DisplayPoint::new(row, start_col);
361            let end_col = line.closest_index_for_x(positions.end) as u32;
362            let end = DisplayPoint::new(row, end_col);
363
364            Some(Selection {
365                id: post_inc(&mut self.next_selection_id),
366                start: start.to_point(display_map),
367                end: end.to_point(display_map),
368                reversed,
369                goal: SelectionGoal::HorizontalRange {
370                    start: positions.start.into(),
371                    end: positions.end.into(),
372                },
373            })
374        } else {
375            None
376        }
377    }
378
379    pub fn change_with<R>(
380        &mut self,
381        cx: &mut App,
382        change: impl FnOnce(&mut MutableSelectionsCollection) -> R,
383    ) -> (bool, R) {
384        let mut mutable_collection = MutableSelectionsCollection {
385            collection: self,
386            selections_changed: false,
387            cx,
388        };
389
390        let result = change(&mut mutable_collection);
391        assert!(
392            !mutable_collection.disjoint.is_empty() || mutable_collection.pending.is_some(),
393            "There must be at least one selection"
394        );
395        (mutable_collection.selections_changed, result)
396    }
397}
398
399pub struct MutableSelectionsCollection<'a> {
400    collection: &'a mut SelectionsCollection,
401    selections_changed: bool,
402    cx: &'a mut App,
403}
404
405impl<'a> MutableSelectionsCollection<'a> {
406    pub fn display_map(&mut self) -> DisplaySnapshot {
407        self.collection.display_map(self.cx)
408    }
409
410    pub fn buffer(&self) -> Ref<MultiBufferSnapshot> {
411        self.collection.buffer(self.cx)
412    }
413
414    pub fn clear_disjoint(&mut self) {
415        self.collection.disjoint = Arc::default();
416    }
417
418    pub fn delete(&mut self, selection_id: usize) {
419        let mut changed = false;
420        self.collection.disjoint = self
421            .disjoint
422            .iter()
423            .filter(|selection| {
424                let found = selection.id == selection_id;
425                changed |= found;
426                !found
427            })
428            .cloned()
429            .collect();
430
431        self.selections_changed |= changed;
432    }
433
434    pub fn clear_pending(&mut self) {
435        if self.collection.pending.is_some() {
436            self.collection.pending = None;
437            self.selections_changed = true;
438        }
439    }
440
441    pub(crate) fn set_pending_anchor_range(&mut self, range: Range<Anchor>, mode: SelectMode) {
442        self.collection.pending = Some(PendingSelection {
443            selection: Selection {
444                id: post_inc(&mut self.collection.next_selection_id),
445                start: range.start,
446                end: range.end,
447                reversed: false,
448                goal: SelectionGoal::None,
449            },
450            mode,
451        });
452        self.selections_changed = true;
453    }
454
455    pub(crate) fn set_pending(&mut self, selection: Selection<Anchor>, mode: SelectMode) {
456        self.collection.pending = Some(PendingSelection { selection, mode });
457        self.selections_changed = true;
458    }
459
460    pub fn try_cancel(&mut self) -> bool {
461        if let Some(pending) = self.collection.pending.take() {
462            if self.disjoint.is_empty() {
463                self.collection.disjoint = Arc::from([pending.selection]);
464            }
465            self.selections_changed = true;
466            return true;
467        }
468
469        let mut oldest = self.oldest_anchor().clone();
470        if self.count() > 1 {
471            self.collection.disjoint = Arc::from([oldest]);
472            self.selections_changed = true;
473            return true;
474        }
475
476        if !oldest.start.cmp(&oldest.end, &self.buffer()).is_eq() {
477            let head = oldest.head();
478            oldest.start = head;
479            oldest.end = head;
480            self.collection.disjoint = Arc::from([oldest]);
481            self.selections_changed = true;
482            return true;
483        }
484
485        false
486    }
487
488    pub fn insert_range<T>(&mut self, range: Range<T>)
489    where
490        T: 'a + ToOffset + ToPoint + TextDimension + Ord + Sub<T, Output = T> + std::marker::Copy,
491    {
492        let mut selections = self.collection.all(self.cx);
493        let mut start = range.start.to_offset(&self.buffer());
494        let mut end = range.end.to_offset(&self.buffer());
495        let reversed = if start > end {
496            mem::swap(&mut start, &mut end);
497            true
498        } else {
499            false
500        };
501        selections.push(Selection {
502            id: post_inc(&mut self.collection.next_selection_id),
503            start,
504            end,
505            reversed,
506            goal: SelectionGoal::None,
507        });
508        self.select(selections);
509    }
510
511    pub fn select<T>(&mut self, mut selections: Vec<Selection<T>>)
512    where
513        T: ToOffset + ToPoint + Ord + std::marker::Copy + std::fmt::Debug,
514    {
515        let buffer = self.buffer.read(self.cx).snapshot(self.cx);
516        selections.sort_unstable_by_key(|s| s.start);
517        // Merge overlapping selections.
518        let mut i = 1;
519        while i < selections.len() {
520            if selections[i - 1].end >= selections[i].start {
521                let removed = selections.remove(i);
522                if removed.start < selections[i - 1].start {
523                    selections[i - 1].start = removed.start;
524                }
525                if removed.end > selections[i - 1].end {
526                    selections[i - 1].end = removed.end;
527                }
528            } else {
529                i += 1;
530            }
531        }
532
533        self.collection.disjoint = Arc::from_iter(selections.into_iter().map(|selection| {
534            let end_bias = if selection.end > selection.start {
535                Bias::Left
536            } else {
537                Bias::Right
538            };
539            Selection {
540                id: selection.id,
541                start: buffer.anchor_after(selection.start),
542                end: buffer.anchor_at(selection.end, end_bias),
543                reversed: selection.reversed,
544                goal: selection.goal,
545            }
546        }));
547
548        self.collection.pending = None;
549        self.selections_changed = true;
550    }
551
552    pub fn select_anchors(&mut self, selections: Vec<Selection<Anchor>>) {
553        let map = self.display_map();
554        let resolved_selections =
555            resolve_selections::<usize, _>(&selections, &map).collect::<Vec<_>>();
556        self.select(resolved_selections);
557    }
558
559    pub fn select_ranges<I, T>(&mut self, ranges: I)
560    where
561        I: IntoIterator<Item = Range<T>>,
562        T: ToOffset,
563    {
564        let buffer = self.buffer.read(self.cx).snapshot(self.cx);
565        let ranges = ranges
566            .into_iter()
567            .map(|range| range.start.to_offset(&buffer)..range.end.to_offset(&buffer));
568        self.select_offset_ranges(ranges);
569    }
570
571    fn select_offset_ranges<I>(&mut self, ranges: I)
572    where
573        I: IntoIterator<Item = Range<usize>>,
574    {
575        let selections = ranges
576            .into_iter()
577            .map(|range| {
578                let mut start = range.start;
579                let mut end = range.end;
580                let reversed = if start > end {
581                    mem::swap(&mut start, &mut end);
582                    true
583                } else {
584                    false
585                };
586                Selection {
587                    id: post_inc(&mut self.collection.next_selection_id),
588                    start,
589                    end,
590                    reversed,
591                    goal: SelectionGoal::None,
592                }
593            })
594            .collect::<Vec<_>>();
595
596        self.select(selections)
597    }
598
599    pub fn select_anchor_ranges<I>(&mut self, ranges: I)
600    where
601        I: IntoIterator<Item = Range<Anchor>>,
602    {
603        let buffer = self.buffer.read(self.cx).snapshot(self.cx);
604        let selections = ranges
605            .into_iter()
606            .map(|range| {
607                let mut start = range.start;
608                let mut end = range.end;
609                let reversed = if start.cmp(&end, &buffer).is_gt() {
610                    mem::swap(&mut start, &mut end);
611                    true
612                } else {
613                    false
614                };
615                Selection {
616                    id: post_inc(&mut self.collection.next_selection_id),
617                    start,
618                    end,
619                    reversed,
620                    goal: SelectionGoal::None,
621                }
622            })
623            .collect::<Vec<_>>();
624        self.select_anchors(selections)
625    }
626
627    pub fn new_selection_id(&mut self) -> usize {
628        post_inc(&mut self.next_selection_id)
629    }
630
631    pub fn select_display_ranges<T>(&mut self, ranges: T)
632    where
633        T: IntoIterator<Item = Range<DisplayPoint>>,
634    {
635        let display_map = self.display_map();
636        let selections = ranges
637            .into_iter()
638            .map(|range| {
639                let mut start = range.start;
640                let mut end = range.end;
641                let reversed = if start > end {
642                    mem::swap(&mut start, &mut end);
643                    true
644                } else {
645                    false
646                };
647                Selection {
648                    id: post_inc(&mut self.collection.next_selection_id),
649                    start: start.to_point(&display_map),
650                    end: end.to_point(&display_map),
651                    reversed,
652                    goal: SelectionGoal::None,
653                }
654            })
655            .collect();
656        self.select(selections);
657    }
658    pub fn reverse_selections(&mut self) {
659        let map = &self.display_map();
660        let mut new_selections: Vec<Selection<Point>> = Vec::new();
661        let disjoint = self.disjoint.clone();
662        for selection in disjoint
663            .iter()
664            .sorted_by(|first, second| Ord::cmp(&second.id, &first.id))
665            .collect::<Vec<&Selection<Anchor>>>()
666        {
667            new_selections.push(Selection {
668                id: self.new_selection_id(),
669                start: selection.start.to_display_point(map).to_point(map),
670                end: selection.end.to_display_point(map).to_point(map),
671                reversed: selection.reversed,
672                goal: selection.goal,
673            });
674        }
675        self.select(new_selections);
676    }
677
678    pub fn move_with(
679        &mut self,
680        mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
681    ) {
682        let mut changed = false;
683        let display_map = self.display_map();
684        let (_, selections) = self.collection.all_display(self.cx);
685        let selections = selections
686            .into_iter()
687            .map(|selection| {
688                let mut moved_selection = selection.clone();
689                move_selection(&display_map, &mut moved_selection);
690                if selection != moved_selection {
691                    changed = true;
692                }
693                moved_selection.map(|display_point| display_point.to_point(&display_map))
694            })
695            .collect();
696
697        if changed {
698            self.select(selections)
699        }
700    }
701
702    pub fn move_offsets_with(
703        &mut self,
704        mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection<usize>),
705    ) {
706        let mut changed = false;
707        let snapshot = self.buffer().clone();
708        let selections = self
709            .collection
710            .all::<usize>(self.cx)
711            .into_iter()
712            .map(|selection| {
713                let mut moved_selection = selection.clone();
714                move_selection(&snapshot, &mut moved_selection);
715                if selection != moved_selection {
716                    changed = true;
717                }
718                moved_selection
719            })
720            .collect();
721        drop(snapshot);
722
723        if changed {
724            self.select(selections)
725        }
726    }
727
728    pub fn move_heads_with(
729        &mut self,
730        mut update_head: impl FnMut(
731            &DisplaySnapshot,
732            DisplayPoint,
733            SelectionGoal,
734        ) -> (DisplayPoint, SelectionGoal),
735    ) {
736        self.move_with(|map, selection| {
737            let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
738            selection.set_head(new_head, new_goal);
739        });
740    }
741
742    pub fn move_cursors_with(
743        &mut self,
744        mut update_cursor_position: impl FnMut(
745            &DisplaySnapshot,
746            DisplayPoint,
747            SelectionGoal,
748        ) -> (DisplayPoint, SelectionGoal),
749    ) {
750        self.move_with(|map, selection| {
751            let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
752            selection.collapse_to(cursor, new_goal)
753        });
754    }
755
756    pub fn maybe_move_cursors_with(
757        &mut self,
758        mut update_cursor_position: impl FnMut(
759            &DisplaySnapshot,
760            DisplayPoint,
761            SelectionGoal,
762        ) -> Option<(DisplayPoint, SelectionGoal)>,
763    ) {
764        self.move_cursors_with(|map, point, goal| {
765            update_cursor_position(map, point, goal).unwrap_or((point, goal))
766        })
767    }
768
769    pub fn replace_cursors_with(
770        &mut self,
771        find_replacement_cursors: impl FnOnce(&DisplaySnapshot) -> Vec<DisplayPoint>,
772    ) {
773        let display_map = self.display_map();
774        let new_selections = find_replacement_cursors(&display_map)
775            .into_iter()
776            .map(|cursor| {
777                let cursor_point = cursor.to_point(&display_map);
778                Selection {
779                    id: post_inc(&mut self.collection.next_selection_id),
780                    start: cursor_point,
781                    end: cursor_point,
782                    reversed: false,
783                    goal: SelectionGoal::None,
784                }
785            })
786            .collect();
787        self.select(new_selections);
788    }
789
790    /// Compute new ranges for any selections that were located in excerpts that have
791    /// since been removed.
792    ///
793    /// Returns a `HashMap` indicating which selections whose former head position
794    /// was no longer present. The keys of the map are selection ids. The values are
795    /// the id of the new excerpt where the head of the selection has been moved.
796    pub fn refresh(&mut self) -> HashMap<usize, ExcerptId> {
797        let mut pending = self.collection.pending.take();
798        let mut selections_with_lost_position = HashMap::default();
799
800        let anchors_with_status = {
801            let buffer = self.buffer();
802            let disjoint_anchors = self
803                .disjoint
804                .iter()
805                .flat_map(|selection| [&selection.start, &selection.end]);
806            buffer.refresh_anchors(disjoint_anchors)
807        };
808        let adjusted_disjoint: Vec<_> = anchors_with_status
809            .chunks(2)
810            .map(|selection_anchors| {
811                let (anchor_ix, start, kept_start) = selection_anchors[0];
812                let (_, end, kept_end) = selection_anchors[1];
813                let selection = &self.disjoint[anchor_ix / 2];
814                let kept_head = if selection.reversed {
815                    kept_start
816                } else {
817                    kept_end
818                };
819                if !kept_head {
820                    selections_with_lost_position.insert(selection.id, selection.head().excerpt_id);
821                }
822
823                Selection {
824                    id: selection.id,
825                    start,
826                    end,
827                    reversed: selection.reversed,
828                    goal: selection.goal,
829                }
830            })
831            .collect();
832
833        if !adjusted_disjoint.is_empty() {
834            let map = self.display_map();
835            let resolved_selections = resolve_selections(adjusted_disjoint.iter(), &map).collect();
836            self.select::<usize>(resolved_selections);
837        }
838
839        if let Some(pending) = pending.as_mut() {
840            let buffer = self.buffer();
841            let anchors =
842                buffer.refresh_anchors([&pending.selection.start, &pending.selection.end]);
843            let (_, start, kept_start) = anchors[0];
844            let (_, end, kept_end) = anchors[1];
845            let kept_head = if pending.selection.reversed {
846                kept_start
847            } else {
848                kept_end
849            };
850            if !kept_head {
851                selections_with_lost_position
852                    .insert(pending.selection.id, pending.selection.head().excerpt_id);
853            }
854
855            pending.selection.start = start;
856            pending.selection.end = end;
857        }
858        self.collection.pending = pending;
859        self.selections_changed = true;
860
861        selections_with_lost_position
862    }
863}
864
865impl Deref for MutableSelectionsCollection<'_> {
866    type Target = SelectionsCollection;
867    fn deref(&self) -> &Self::Target {
868        self.collection
869    }
870}
871
872impl DerefMut for MutableSelectionsCollection<'_> {
873    fn deref_mut(&mut self) -> &mut Self::Target {
874        self.collection
875    }
876}
877
878// Panics if passed selections are not in order
879fn resolve_selections_display<'a>(
880    selections: impl 'a + IntoIterator<Item = &'a Selection<Anchor>>,
881    map: &'a DisplaySnapshot,
882) -> impl 'a + Iterator<Item = Selection<DisplayPoint>> {
883    let (to_summarize, selections) = selections.into_iter().tee();
884    let mut summaries = map
885        .buffer_snapshot
886        .summaries_for_anchors::<Point, _>(to_summarize.flat_map(|s| [&s.start, &s.end]))
887        .into_iter();
888    let mut selections = selections
889        .map(move |s| {
890            let start = summaries.next().unwrap();
891            let end = summaries.next().unwrap();
892
893            let display_start = map.point_to_display_point(start, Bias::Left);
894            let display_end = if start == end {
895                map.point_to_display_point(end, Bias::Right)
896            } else {
897                map.point_to_display_point(end, Bias::Left)
898            };
899
900            Selection {
901                id: s.id,
902                start: display_start,
903                end: display_end,
904                reversed: s.reversed,
905                goal: s.goal,
906            }
907        })
908        .peekable();
909    iter::from_fn(move || {
910        let mut selection = selections.next()?;
911        while let Some(next_selection) = selections.peek() {
912            if selection.end >= next_selection.start {
913                selection.end = cmp::max(selection.end, next_selection.end);
914                selections.next();
915            } else {
916                break;
917            }
918        }
919        Some(selection)
920    })
921}
922
923// Panics if passed selections are not in order
924pub(crate) fn resolve_selections<'a, D, I>(
925    selections: I,
926    map: &'a DisplaySnapshot,
927) -> impl 'a + Iterator<Item = Selection<D>>
928where
929    D: TextDimension + Ord + Sub<D, Output = D>,
930    I: 'a + IntoIterator<Item = &'a Selection<Anchor>>,
931{
932    let (to_convert, selections) = resolve_selections_display(selections, map).tee();
933    let mut converted_endpoints =
934        map.buffer_snapshot
935            .dimensions_from_points::<D>(to_convert.flat_map(|s| {
936                let start = map.display_point_to_point(s.start, Bias::Left);
937                let end = map.display_point_to_point(s.end, Bias::Right);
938                [start, end]
939            }));
940    selections.map(move |s| {
941        let start = converted_endpoints.next().unwrap();
942        let end = converted_endpoints.next().unwrap();
943        Selection {
944            id: s.id,
945            start,
946            end,
947            reversed: s.reversed,
948            goal: s.goal,
949        }
950    })
951}