selections_collection.rs

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