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