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