1use std::ops::Range;
12
13#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
15pub struct Selection {
16 ranges: Vec<(usize, usize)>,
18 anchor: Option<usize>,
19 cursor: Option<usize>,
20}
21
22impl Selection {
23 pub fn new() -> Self {
24 Self::default()
25 }
26
27 pub fn contains(&self, row: usize) -> bool {
29 let i = self.ranges.partition_point(|r| r.1 <= row);
30 self.ranges.get(i).is_some_and(|r| r.0 <= row)
31 }
32 pub fn len(&self) -> usize {
34 self.ranges.iter().fold(0usize, |n, r| n.saturating_add(r.1.saturating_sub(r.0)))
35 }
36 pub fn is_empty(&self) -> bool {
37 self.ranges.is_empty()
38 }
39 pub fn cursor(&self) -> Option<usize> {
41 self.cursor
42 }
43 pub fn anchor(&self) -> Option<usize> {
45 self.anchor
46 }
47 pub fn ranges(&self) -> impl Iterator<Item = Range<usize>> + '_ {
49 self.ranges.iter().map(|r| r.0..r.1)
50 }
51 pub fn iter(&self) -> impl Iterator<Item = usize> + '_ {
53 self.ranges().flatten()
54 }
55
56 pub fn select_only(&mut self, row: usize) {
58 self.ranges.clear();
59 self.ranges.push((row, row.saturating_add(1)));
60 self.anchor = Some(row);
61 self.cursor = Some(row);
62 }
63 pub fn toggle(&mut self, row: usize) {
65 if self.contains(row) {
66 self.remove(row..row.saturating_add(1));
67 } else {
68 self.insert(row..row.saturating_add(1));
69 }
70 self.anchor = Some(row);
71 self.cursor = Some(row);
72 }
73 pub fn extend_to(&mut self, row: usize) {
76 let anchor = self.anchor.unwrap_or(row);
77 let (lo, hi) = if anchor <= row { (anchor, row) } else { (row, anchor) };
78 self.ranges.clear();
79 self.ranges.push((lo, hi.saturating_add(1)));
80 self.anchor = Some(anchor);
81 self.cursor = Some(row);
82 }
83 pub fn select_all(&mut self, rows: usize) {
85 self.ranges.clear();
86 if rows > 0 {
87 self.ranges.push((0, rows));
88 }
89 }
90 pub fn clear(&mut self) {
92 *self = Self::default();
93 }
94 pub fn clamp(&mut self, rows: usize) {
96 self.remove(rows..usize::MAX);
97 self.anchor = self.anchor.filter(|a| *a < rows);
98 self.cursor = self.cursor.filter(|c| *c < rows);
99 }
100
101 pub fn insert(&mut self, rows: Range<usize>) {
103 if rows.is_empty() {
104 return;
105 }
106 let (mut lo, mut hi) = (rows.start, rows.end);
107 let first = self.ranges.partition_point(|r| r.1 < lo);
109 let last = self.ranges.partition_point(|r| r.0 <= hi);
110 if let Some(r) = self.ranges.get(first..last) {
111 if let (Some(a), Some(b)) = (r.first(), r.last()) {
112 lo = lo.min(a.0);
113 hi = hi.max(b.1);
114 }
115 self.ranges.splice(first..last, [(lo, hi)]);
116 }
117 }
118 pub fn remove(&mut self, rows: Range<usize>) {
120 if rows.is_empty() {
121 return;
122 }
123 let (lo, hi) = (rows.start, rows.end);
124 let first = self.ranges.partition_point(|r| r.1 <= lo);
125 let last = self.ranges.partition_point(|r| r.0 < hi);
126 let Some(hit) = self.ranges.get(first..last) else { return };
127 let mut keep = Vec::with_capacity(2);
128 if let Some(a) = hit.first().filter(|a| a.0 < lo) {
129 keep.push((a.0, lo));
130 }
131 if let Some(b) = hit.last().filter(|b| b.1 > hi) {
132 keep.push((hi, b.1));
133 }
134 self.ranges.splice(first..last, keep);
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn ranges_merge_split_and_count() {
144 let mut s = Selection::new();
145 s.insert(5..8);
146 s.insert(1..3);
147 s.insert(3..5);
148 assert_eq!(s.ranges().collect::<Vec<_>>(), vec![1..8]);
149 s.remove(4..6);
150 assert_eq!(s.ranges().collect::<Vec<_>>(), vec![1..4, 6..8]);
151 assert!(s.contains(3) && !s.contains(4) && s.contains(7) && !s.contains(8));
152 assert_eq!(s.len(), 5);
153 s.toggle(5);
154 assert_eq!(s.ranges().collect::<Vec<_>>(), vec![1..4, 5..8]);
155 s.toggle(5);
156 assert_eq!(s.iter().collect::<Vec<_>>(), vec![1, 2, 3, 6, 7]);
157 s.remove(0..usize::MAX);
158 assert!(s.is_empty());
159 }
160
161 #[test]
162 fn extend_keeps_anchor_and_select_all_is_one_range() {
163 let mut s = Selection::new();
164 s.select_only(10);
165 s.extend_to(7);
166 assert_eq!((s.anchor(), s.cursor(), s.len()), (Some(10), Some(7), 4));
167 s.extend_to(12);
168 assert_eq!(s.ranges().collect::<Vec<_>>(), vec![10..13]);
169 s.select_all(10_000_000);
170 assert_eq!((s.len(), s.ranges().count()), (10_000_000, 1));
171 s.clamp(5);
172 assert_eq!((s.len(), s.anchor(), s.cursor()), (5, None, None));
173 s.insert(usize::MAX - 1..usize::MAX);
174 s.toggle(usize::MAX);
175 let json = serde_json::to_string(&s).unwrap();
176 assert_eq!(serde_json::from_str::<Selection>(&json).unwrap(), s);
177 }
178}