1use std::cmp::{max, min};
18use std::fmt;
19use std::ops::Deref;
20
21use crate::annotations::{AnnotationRange, AnnotationSlice, AnnotationType, ToAnnotation};
22use crate::index_set::remove_n_at;
23use crate::view::View;
24use xi_rope::{Interval, Rope, RopeDelta, Transformer};
25
26pub type HorizPos = usize;
30
31#[derive(Copy, Clone)]
35pub enum InsertDrift {
36 Inside,
38 Outside,
40 Default,
42}
43
44#[derive(Default, Debug, Clone)]
46pub struct Selection {
47 regions: Vec<SelRegion>,
50}
51
52impl Selection {
53 pub fn new() -> Selection {
55 Selection::default()
56 }
57
58 pub fn new_simple(region: SelRegion) -> Selection {
60 Selection { regions: vec![region] }
61 }
62
63 pub fn clear(&mut self) {
65 self.regions.clear();
66 }
67
68 pub fn collapse(&mut self) {
70 self.regions.truncate(1);
71 self.regions[0].start = self.regions[0].end;
72 }
73
74 pub fn search(&self, offset: usize) -> usize {
77 if self.regions.is_empty() || offset > self.regions.last().unwrap().max() {
78 return self.regions.len();
79 }
80 match self.regions.binary_search_by(|r| r.max().cmp(&offset)) {
81 Ok(ix) => ix,
82 Err(ix) => ix,
83 }
84 }
85
86 pub fn add_region(&mut self, region: SelRegion) {
96 let mut ix = self.search(region.min());
97 if ix == self.regions.len() {
98 self.regions.push(region);
99 return;
100 }
101 let mut region = region;
102 let mut end_ix = ix;
103 if self.regions[ix].min() <= region.min() {
104 if self.regions[ix].should_merge(region) {
105 region = self.regions[ix].merge_with(region);
106 } else {
107 ix += 1;
108 }
109 end_ix += 1;
110 }
111 while end_ix < self.regions.len() && region.should_merge(self.regions[end_ix]) {
112 region = region.merge_with(self.regions[end_ix]);
113 end_ix += 1;
114 }
115 if ix == end_ix {
116 self.regions.insert(ix, region);
117 } else {
118 self.regions[ix] = region;
119 remove_n_at(&mut self.regions, ix + 1, end_ix - ix - 1);
120 }
121 }
122
123 pub fn regions_in_range(&self, start: usize, end: usize) -> &[SelRegion] {
130 let first = self.search(start);
131 let mut last = self.search(end);
132 if last < self.regions.len() && self.regions[last].min() <= end {
133 last += 1;
134 }
135 &self.regions[first..last]
136 }
137
138 pub fn delete_range(&mut self, start: usize, end: usize, delete_adjacent: bool) {
140 let mut first = self.search(start);
141 let mut last = self.search(end);
142 if first >= self.regions.len() {
143 return;
144 }
145 if !delete_adjacent && self.regions[first].max() == start {
146 first += 1;
147 }
148 if last < self.regions.len()
149 && ((delete_adjacent && self.regions[last].min() <= end)
150 || (!delete_adjacent && self.regions[last].min() < end))
151 {
152 last += 1;
153 }
154 remove_n_at(&mut self.regions, first, last - first);
155 }
156
157 pub fn add_range_distinct(&mut self, region: SelRegion) -> (usize, usize) {
165 let mut ix = self.search(region.min());
166
167 if ix < self.regions.len() && self.regions[ix].max() == region.min() {
168 ix += 1;
169 }
170
171 if ix < self.regions.len() {
172 let occ = &self.regions[ix];
174 let is_eq = occ.min() == region.min() && occ.max() == region.max();
175 let is_intersect_before = region.min() >= occ.min() && occ.max() > region.min();
176 if is_eq || is_intersect_before {
177 return (occ.min(), occ.max());
178 }
179 }
180
181 let mut last = self.search(region.max());
183 if last < self.regions.len() && self.regions[last].min() < region.max() {
184 last += 1;
185 }
186 remove_n_at(&mut self.regions, ix, last - ix);
187
188 if ix == self.regions.len() {
189 self.regions.push(region);
190 } else {
191 self.regions.insert(ix, region);
192 }
193
194 (self.regions[ix].min(), self.regions[ix].max())
195 }
196
197 pub fn apply_delta(&self, delta: &RopeDelta, after: bool, drift: InsertDrift) -> Selection {
205 let mut result = Selection::new();
206 let mut transformer = Transformer::new(delta);
207 for region in self.iter() {
208 let is_caret = region.start == region.end;
209 let is_region_forward = region.start < region.end;
210
211 let (start_after, end_after) = match (drift, is_caret) {
212 (InsertDrift::Inside, false) => (!is_region_forward, is_region_forward),
213 (InsertDrift::Outside, false) => (is_region_forward, !is_region_forward),
214 _ => (after, after),
215 };
216
217 let new_region = SelRegion::new(
218 transformer.transform(region.start, start_after),
219 transformer.transform(region.end, end_after),
220 )
221 .with_affinity(region.affinity);
222 result.add_region(new_region);
223 }
224 result
225 }
226}
227
228impl ToAnnotation for Selection {
230 fn get_annotations(&self, interval: Interval, view: &View, text: &Rope) -> AnnotationSlice {
231 let regions = self.regions_in_range(interval.start(), interval.end());
232 let ranges = regions
233 .iter()
234 .map(|region| {
235 let (start_line, start_col) = view.offset_to_line_col(text, region.min());
236 let (end_line, end_col) = view.offset_to_line_col(text, region.max());
237
238 AnnotationRange { start_line, start_col, end_line, end_col }
239 })
240 .collect::<Vec<AnnotationRange>>();
241 AnnotationSlice::new(AnnotationType::Selection, ranges, None)
242 }
243}
244
245impl Deref for Selection {
248 type Target = [SelRegion];
249
250 fn deref(&self) -> &[SelRegion] {
251 &self.regions
252 }
253}
254
255#[derive(Clone, Copy, PartialEq, Eq, Debug)]
260pub enum Affinity {
261 Downstream,
265 Upstream,
269}
270
271impl Default for Affinity {
272 fn default() -> Affinity {
273 Affinity::Downstream
274 }
275}
276
277#[derive(Clone, Copy, PartialEq, Eq, Debug)]
282pub struct SelRegion {
283 pub start: usize,
286
287 pub end: usize,
289
290 pub horiz: Option<HorizPos>,
292
293 pub affinity: Affinity,
295}
296
297impl SelRegion {
298 pub fn new(start: usize, end: usize) -> Self {
300 Self { start, end, horiz: None, affinity: Affinity::default() }
301 }
302
303 pub fn caret(pos: usize) -> Self {
305 Self { start: pos, end: pos, horiz: None, affinity: Affinity::default() }
306 }
307
308 pub fn with_horiz(self, horiz: Option<HorizPos>) -> Self {
310 Self { horiz, ..self }
311 }
312
313 pub fn with_affinity(self, affinity: Affinity) -> Self {
315 Self { affinity, ..self }
316 }
317
318 pub fn min(self) -> usize {
320 min(self.start, self.end)
321 }
322
323 pub fn max(self) -> usize {
325 max(self.start, self.end)
326 }
327
328 pub fn is_caret(self) -> bool {
330 self.start == self.end
331 }
332
333 pub fn is_upstream(self) -> bool {
335 self.affinity == Affinity::Upstream
336 }
337
338 fn should_merge(self, other: SelRegion) -> bool {
341 other.min() < self.max()
342 || ((self.is_caret() || other.is_caret()) && other.min() == self.max())
343 }
344
345 fn merge_with(self, other: SelRegion) -> SelRegion {
346 let is_forward = self.end > self.start || other.end > other.start;
347 let new_min = min(self.min(), other.min());
348 let new_max = max(self.max(), other.max());
349 let (start, end) = if is_forward { (new_min, new_max) } else { (new_max, new_min) };
350 SelRegion::new(start, end)
353 }
354}
355
356impl<'a> From<&'a SelRegion> for Interval {
357 fn from(src: &'a SelRegion) -> Interval {
358 Interval::new(src.min(), src.max())
359 }
360}
361
362impl From<Interval> for SelRegion {
363 fn from(src: Interval) -> SelRegion {
364 SelRegion::new(src.start, src.end)
365 }
366}
367
368impl From<SelRegion> for Selection {
369 fn from(region: SelRegion) -> Self {
370 Self::new_simple(region)
371 }
372}
373
374impl fmt::Display for Selection {
375 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
376 if self.regions.len() == 1 {
377 self.regions[0].fmt(f)?;
378 } else {
379 write!(f, "[ {}", &self.regions[0])?;
380 for region in &self.regions[1..] {
381 write!(f, ", {}", region)?;
382 }
383 write!(f, " ]")?;
384 }
385 Ok(())
386 }
387}
388
389impl fmt::Display for SelRegion {
390 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
391 if self.is_caret() {
392 write!(f, "{}|", self.start)?;
393 } else if self.start < self.end {
394 write!(f, "{}..{}|", self.start, self.end)?;
395 } else {
396 write!(f, "|{}..{}", self.end, self.start)?;
397 }
398 Ok(())
399 }
400}
401
402#[cfg(test)]
403mod tests {
404 use super::{InsertDrift, SelRegion, Selection};
405 use std::ops::Deref;
406 use xi_rope::{DeltaBuilder, Interval};
407
408 fn r(start: usize, end: usize) -> SelRegion {
409 SelRegion::new(start, end)
410 }
411
412 #[test]
413 fn empty() {
414 let s = Selection::new();
415 assert!(s.is_empty());
416 assert_eq!(s.deref(), &[]);
417 }
418
419 #[test]
420 fn simple_region() {
421 let s = Selection::new_simple(r(3, 5));
422 assert!(!s.is_empty());
423 assert_eq!(s.deref(), &[r(3, 5)]);
424 }
425
426 #[test]
427 fn from_selregion() {
428 let s: Selection = r(3, 5).into();
429 assert!(!s.is_empty());
430 assert_eq!(s.deref(), &[r(3, 5)]);
431 }
432
433 #[test]
434 fn delete_range() {
435 let mut s = Selection::new_simple(r(3, 5));
436 s.delete_range(1, 2, true);
437 assert_eq!(s.deref(), &[r(3, 5)]);
438 s.delete_range(1, 3, false);
439 assert_eq!(s.deref(), &[r(3, 5)]);
440 s.delete_range(1, 3, true);
441 assert_eq!(s.deref(), &[]);
442
443 let mut s = Selection::new_simple(r(3, 5));
444 s.delete_range(5, 6, false);
445 assert_eq!(s.deref(), &[r(3, 5)]);
446 s.delete_range(5, 6, true);
447 assert_eq!(s.deref(), &[]);
448
449 let mut s = Selection::new_simple(r(3, 5));
450 s.delete_range(2, 4, false);
451 assert_eq!(s.deref(), &[]);
452 assert_eq!(s.deref(), &[]);
453
454 let mut s = Selection::new();
455 s.add_region(r(3, 5));
456 s.add_region(r(7, 8));
457 s.delete_range(2, 10, false);
458 assert_eq!(s.deref(), &[]);
459 }
460
461 #[test]
462 fn simple_regions_in_range() {
463 let s = Selection::new_simple(r(3, 5));
464 assert_eq!(s.regions_in_range(0, 1), &[]);
465 assert_eq!(s.regions_in_range(0, 2), &[]);
466 assert_eq!(s.regions_in_range(0, 3), &[r(3, 5)]);
467 assert_eq!(s.regions_in_range(0, 4), &[r(3, 5)]);
468 assert_eq!(s.regions_in_range(5, 6), &[r(3, 5)]);
469 assert_eq!(s.regions_in_range(6, 7), &[]);
470 }
471
472 #[test]
473 fn caret_regions_in_range() {
474 let s = Selection::new_simple(r(4, 4));
475 assert_eq!(s.regions_in_range(0, 1), &[]);
476 assert_eq!(s.regions_in_range(0, 2), &[]);
477 assert_eq!(s.regions_in_range(0, 3), &[]);
478 assert_eq!(s.regions_in_range(0, 4), &[r(4, 4)]);
479 assert_eq!(s.regions_in_range(4, 4), &[r(4, 4)]);
480 assert_eq!(s.regions_in_range(4, 5), &[r(4, 4)]);
481 assert_eq!(s.regions_in_range(5, 6), &[]);
482 }
483
484 #[test]
485 fn merge_regions() {
486 let mut s = Selection::new();
487 s.add_region(r(3, 5));
488 assert_eq!(s.deref(), &[r(3, 5)]);
489 s.add_region(r(7, 9));
490 assert_eq!(s.deref(), &[r(3, 5), r(7, 9)]);
491 s.add_region(r(1, 3));
492 assert_eq!(s.deref(), &[r(1, 3), r(3, 5), r(7, 9)]);
493 s.add_region(r(4, 6));
494 assert_eq!(s.deref(), &[r(1, 3), r(3, 6), r(7, 9)]);
495 s.add_region(r(2, 8));
496 assert_eq!(s.deref(), &[r(1, 9)]);
497
498 s.clear();
499 assert_eq!(s.deref(), &[]);
500 s.add_region(r(1, 4));
501 s.add_region(r(4, 5));
502 s.add_region(r(5, 6));
503 s.add_region(r(6, 9));
504 assert_eq!(s.deref(), &[r(1, 4), r(4, 5), r(5, 6), r(6, 9)]);
505 s.add_region(r(2, 8));
506 assert_eq!(s.deref(), &[r(1, 9)]);
507 }
508
509 #[test]
510 fn merge_carets() {
511 let mut s = Selection::new();
512 s.add_region(r(1, 1));
513 assert_eq!(s.deref(), &[r(1, 1)]);
514 s.add_region(r(3, 3));
515 assert_eq!(s.deref(), &[r(1, 1), r(3, 3)]);
516 s.add_region(r(2, 2));
517 assert_eq!(s.deref(), &[r(1, 1), r(2, 2), r(3, 3)]);
518 s.add_region(r(1, 1));
519 assert_eq!(s.deref(), &[r(1, 1), r(2, 2), r(3, 3)]);
520 }
521
522 #[test]
523 fn merge_region_caret() {
524 let mut s = Selection::new();
525 s.add_region(r(3, 5));
526 assert_eq!(s.deref(), &[r(3, 5)]);
527 s.add_region(r(3, 3));
528 assert_eq!(s.deref(), &[r(3, 5)]);
529 s.add_region(r(4, 4));
530 assert_eq!(s.deref(), &[r(3, 5)]);
531 s.add_region(r(5, 5));
532 assert_eq!(s.deref(), &[r(3, 5)]);
533 s.add_region(r(6, 6));
534 assert_eq!(s.deref(), &[r(3, 5), r(6, 6)]);
535 }
536
537 #[test]
538 fn merge_reverse() {
539 let mut s = Selection::new();
540 s.add_region(r(5, 3));
541 assert_eq!(s.deref(), &[r(5, 3)]);
542 s.add_region(r(9, 7));
543 assert_eq!(s.deref(), &[r(5, 3), r(9, 7)]);
544 s.add_region(r(3, 1));
545 assert_eq!(s.deref(), &[r(3, 1), r(5, 3), r(9, 7)]);
546 s.add_region(r(6, 4));
547 assert_eq!(s.deref(), &[r(3, 1), r(6, 3), r(9, 7)]);
548 s.add_region(r(8, 2));
549 assert_eq!(s.deref(), &[r(9, 1)]);
550 }
551
552 #[test]
553 fn apply_delta_outside_drift() {
554 let mut s = Selection::new();
555 s.add_region(r(0, 4));
556 s.add_region(r(4, 8));
557 assert_eq!(s.deref(), &[r(0, 4), r(4, 8)]);
558
559 let mut builder = DeltaBuilder::new("texthere!".len());
563 builder.replace(Interval::new(4, 4), " ".into());
564 let s2 = s.apply_delta(&builder.build(), true, InsertDrift::Outside);
565
566 assert_eq!(s2.deref(), &[r(0, 4), r(5, 9)]);
567 }
568
569 #[test]
570 fn apply_delta_inside_drift() {
571 let mut s = Selection::new();
572 s.add_region(r(1, 2));
573 assert_eq!(s.deref(), &[r(1, 2)]);
574
575 let mut builder = DeltaBuilder::new("abc".len());
579 builder.replace(Interval::new(1, 1), "b".into());
580 builder.replace(Interval::new(2, 2), "b".into());
581 let s2 = s.apply_delta(&builder.build(), true, InsertDrift::Inside);
582
583 assert_eq!(s2.deref(), &[r(1, 4)]);
584 }
585
586 #[test]
587 fn apply_delta_drift_ignored_for_carets() {
588 let mut s = Selection::new();
589 s.add_region(r(1, 1));
590 assert_eq!(s.deref(), &[r(1, 1)]);
591
592 let mut builder = DeltaBuilder::new("ab".len());
593 builder.replace(Interval::new(1, 1), "b".into());
594 let s2 = s.apply_delta(&builder.build(), true, InsertDrift::Inside);
595 assert_eq!(s2.deref(), &[r(2, 2)]);
596
597 let mut builder = DeltaBuilder::new("ab".len());
598 builder.replace(Interval::new(1, 1), "b".into());
599 let s3 = s.apply_delta(&builder.build(), false, InsertDrift::Inside);
600 assert_eq!(s3.deref(), &[r(1, 1)]);
601 }
602
603 #[test]
604 fn display() {
605 let mut s = Selection::new();
606 s.add_region(r(1, 1));
607 assert_eq!(s.to_string(), "1|");
608 s.add_region(r(3, 5));
609 s.add_region(r(8, 6));
610 assert_eq!(s.to_string(), "[ 1|, 3..5|, |6..8 ]");
611 }
612}