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