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}