selection.rs

  1use super::{Anchor, MultiBufferSnapshot, ToOffset};
  2use std::{
  3    ops::{Range, Sub},
  4    sync::Arc,
  5};
  6use sum_tree::Bias;
  7use text::{rope::TextDimension, Selection, SelectionSetId};
  8
  9#[derive(Clone, Debug, Eq, PartialEq)]
 10pub struct SelectionSet {
 11    pub id: SelectionSetId,
 12    pub active: bool,
 13    pub selections: Arc<[Selection<Anchor>]>,
 14}
 15
 16impl SelectionSet {
 17    pub fn len(&self) -> usize {
 18        self.selections.len()
 19    }
 20
 21    pub fn selections<'a, D>(
 22        &'a self,
 23        snapshot: &'a MultiBufferSnapshot,
 24    ) -> impl 'a + Iterator<Item = Selection<D>>
 25    where
 26        D: TextDimension + Ord + Sub<D, Output = D>,
 27    {
 28        resolve_selections(&self.selections, snapshot)
 29    }
 30
 31    pub fn intersecting_selections<'a, D, I>(
 32        &'a self,
 33        range: Range<(I, Bias)>,
 34        snapshot: &'a MultiBufferSnapshot,
 35    ) -> impl 'a + Iterator<Item = Selection<D>>
 36    where
 37        D: TextDimension + Ord + Sub<D, Output = D>,
 38        I: 'a + ToOffset,
 39    {
 40        let start = snapshot.anchor_at(range.start.0, range.start.1);
 41        let end = snapshot.anchor_at(range.end.0, range.end.1);
 42        let start_ix = match self
 43            .selections
 44            .binary_search_by(|probe| probe.end.cmp(&start, snapshot).unwrap())
 45        {
 46            Ok(ix) | Err(ix) => ix,
 47        };
 48        let end_ix = match self
 49            .selections
 50            .binary_search_by(|probe| probe.start.cmp(&end, snapshot).unwrap())
 51        {
 52            Ok(ix) | Err(ix) => ix,
 53        };
 54        resolve_selections(&self.selections[start_ix..end_ix], snapshot)
 55    }
 56
 57    pub fn oldest_selection<'a, D>(
 58        &'a self,
 59        snapshot: &'a MultiBufferSnapshot,
 60    ) -> Option<Selection<D>>
 61    where
 62        D: TextDimension + Ord + Sub<D, Output = D>,
 63    {
 64        self.selections
 65            .iter()
 66            .min_by_key(|selection| selection.id)
 67            .map(|selection| resolve_selection(selection, snapshot))
 68    }
 69
 70    pub fn newest_selection<'a, D>(
 71        &'a self,
 72        snapshot: &'a MultiBufferSnapshot,
 73    ) -> Option<Selection<D>>
 74    where
 75        D: TextDimension + Ord + Sub<D, Output = D>,
 76    {
 77        self.selections
 78            .iter()
 79            .max_by_key(|selection| selection.id)
 80            .map(|selection| resolve_selection(selection, snapshot))
 81    }
 82}
 83
 84fn resolve_selection<'a, D>(
 85    selection: &'a Selection<Anchor>,
 86    snapshot: &'a MultiBufferSnapshot,
 87) -> Selection<D>
 88where
 89    D: TextDimension + Ord + Sub<D, Output = D>,
 90{
 91    Selection {
 92        id: selection.id,
 93        start: selection.start.summary::<D>(snapshot),
 94        end: selection.end.summary::<D>(snapshot),
 95        reversed: selection.reversed,
 96        goal: selection.goal,
 97    }
 98}
 99
100fn resolve_selections<'a, D>(
101    selections: &'a [Selection<Anchor>],
102    snapshot: &'a MultiBufferSnapshot,
103) -> impl 'a + Iterator<Item = Selection<D>>
104where
105    D: TextDimension + Ord + Sub<D, Output = D>,
106{
107    let mut summaries = snapshot
108        .summaries_for_anchors::<D, _>(
109            selections
110                .iter()
111                .flat_map(|selection| [&selection.start, &selection.end]),
112        )
113        .into_iter();
114    selections.iter().map(move |selection| Selection {
115        id: selection.id,
116        start: summaries.next().unwrap(),
117        end: summaries.next().unwrap(),
118        reversed: selection.reversed,
119        goal: selection.goal,
120    })
121}