1use std::cmp::{max, min, Ordering};
2
3use lapce_xi_rope::{RopeDelta, Transformer};
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7use crate::cursor::ColPosition;
8
9#[derive(Copy, Clone)]
12pub enum InsertDrift {
13 Inside,
15 Outside,
17 Default,
19}
20
21#[derive(Clone, Copy, PartialEq, Debug)]
22#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
23pub struct SelRegion {
24 pub start: usize,
26 pub end: usize,
28 pub horiz: Option<ColPosition>,
30}
31
32#[derive(Clone, PartialEq, Debug)]
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36pub struct Selection {
37 regions: Vec<SelRegion>,
38 last_inserted: usize,
39}
40
41impl AsRef<Selection> for Selection {
42 fn as_ref(&self) -> &Selection {
43 self
44 }
45}
46
47impl SelRegion {
48 pub fn new(start: usize, end: usize, horiz: Option<ColPosition>) -> SelRegion {
50 SelRegion { start, end, horiz }
51 }
52
53 pub fn caret(offset: usize) -> SelRegion {
56 SelRegion {
57 start: offset,
58 end: offset,
59 horiz: None,
60 }
61 }
62
63 pub fn min(self) -> usize {
75 min(self.start, self.end)
76 }
77
78 pub fn max(self) -> usize {
90 max(self.start, self.end)
91 }
92
93 pub fn is_caret(self) -> bool {
103 self.start == self.end
104 }
105
106 pub fn merge_with(self, other: SelRegion) -> SelRegion {
117 let is_forward = self.end >= self.start;
118 let new_min = min(self.min(), other.min());
119 let new_max = max(self.max(), other.max());
120 let (start, end) = if is_forward {
121 (new_min, new_max)
122 } else {
123 (new_max, new_min)
124 };
125 SelRegion::new(start, end, None)
126 }
127
128 fn should_merge(self, other: SelRegion) -> bool {
129 other.min() < self.max()
130 || ((self.is_caret() || other.is_caret()) && other.min() == self.max())
131 }
132
133 fn contains(&self, offset: usize) -> bool {
134 self.min() <= offset && offset <= self.max()
135 }
136}
137
138impl Selection {
139 pub fn new() -> Selection {
141 Selection {
142 regions: Vec::new(),
143 last_inserted: 0,
144 }
145 }
146
147 pub fn caret(offset: usize) -> Selection {
149 Selection {
150 regions: vec![SelRegion::caret(offset)],
151 last_inserted: 0,
152 }
153 }
154
155 pub fn region(start: usize, end: usize) -> Self {
158 Self::sel_region(SelRegion {
159 start,
160 end,
161 horiz: None,
162 })
163 }
164
165 pub fn sel_region(region: SelRegion) -> Self {
167 Self {
168 regions: vec![region],
169 last_inserted: 0,
170 }
171 }
172
173 pub fn contains(&self, offset: usize) -> bool {
186 for region in self.regions.iter() {
187 if region.contains(offset) {
188 return true;
189 }
190 }
191 false
192 }
193
194 pub fn regions(&self) -> &[SelRegion] {
196 &self.regions
197 }
198
199 pub fn regions_mut(&mut self) -> &mut [SelRegion] {
201 &mut self.regions
202 }
203
204 pub fn min(&self) -> Selection {
222 let mut selection = Self::new();
223 for region in &self.regions {
224 let new_region = SelRegion::new(region.min(), region.min(), None);
225 selection.add_region(new_region);
226 }
227 selection
228 }
229
230 pub fn first(&self) -> Option<&SelRegion> {
232 self.regions.first()
233 }
234
235 pub fn last(&self) -> Option<&SelRegion> {
237 self.regions.get(self.len() - 1)
238 }
239
240 pub fn last_inserted(&self) -> Option<&SelRegion> {
242 self.regions.get(self.last_inserted)
243 }
244
245 pub fn last_inserted_mut(&mut self) -> Option<&mut SelRegion> {
247 self.regions.get_mut(self.last_inserted)
248 }
249
250 pub fn len(&self) -> usize {
252 self.regions.len()
253 }
254
255 pub fn is_caret(&self) -> bool {
258 self.regions.iter().all(|region| region.is_caret())
259 }
260
261 pub fn current_caret(&self) -> Option<usize> {
262 if self.regions.len() == 1 {
263 if self.regions[0].is_caret() {
264 Some(self.regions[0].start)
265 } else {
266 None
267 }
268 } else {
269 None
270 }
271 }
272
273 pub fn is_empty(&self) -> bool {
275 self.len() == 0
276 }
277
278 pub fn min_offset(&self) -> usize {
293 let mut offset = self.regions()[0].min();
294 for region in &self.regions {
295 offset = offset.min(region.min());
296 }
297 offset
298 }
299
300 pub fn max_offset(&self) -> usize {
315 let mut offset = self.regions()[0].max();
316 for region in &self.regions {
317 offset = offset.max(region.max());
318 }
319 offset
320 }
321
322 pub fn regions_in_range(&self, start: usize, end: usize) -> &[SelRegion] {
342 let first = self.search(start);
343 let mut last = self.search(end);
344 if last < self.regions.len() && self.regions[last].min() <= end {
345 last += 1;
346 }
347 &self.regions[first..last]
348 }
349
350 pub fn full_regions_in_range(&self, start: usize, end: usize) -> &[SelRegion] {
368 let first = self.search_min(start);
369 let mut last = self.search_min(end);
370 if last < self.regions.len() && self.regions[last].min() <= end {
371 last += 1;
372 }
373 &self.regions[first..last]
374 }
375
376 pub fn delete_range(&mut self, start: usize, end: usize) {
391 let mut first = self.search(start);
392 let mut last = self.search(end);
393 if first >= self.regions.len() {
394 return;
395 }
396 if self.regions[first].max() == start {
397 first += 1;
398 }
399 if last < self.regions.len() && self.regions[last].min() < end {
400 last += 1;
401 }
402 remove_n_at(&mut self.regions, first, last - first);
403 }
404
405 pub fn add_region(&mut self, region: SelRegion) {
427 let mut ix = self.search(region.min());
428 if ix == self.regions.len() {
429 self.regions.push(region);
430 self.last_inserted = self.regions.len() - 1;
431 return;
432 }
433 let mut region = region;
434 let mut end_ix = ix;
435 if self.regions[ix].min() <= region.min() {
436 if self.regions[ix].should_merge(region) {
437 region = self.regions[ix].merge_with(region);
438 } else {
439 ix += 1;
440 }
441 end_ix += 1;
442 }
443 while end_ix < self.regions.len() && region.should_merge(self.regions[end_ix]) {
444 region = self.regions[end_ix].merge_with(region);
445 end_ix += 1;
446 }
447 if ix == end_ix {
448 self.regions.insert(ix, region);
449 self.last_inserted = ix;
450 } else {
451 self.regions[ix] = region;
452 remove_n_at(&mut self.regions, ix + 1, end_ix - ix - 1);
453 }
454 }
455
456 pub fn add_range_distinct(&mut self, region: SelRegion) -> (usize, usize) {
464 let mut ix = self.search(region.min());
465
466 if ix < self.regions.len() && self.regions[ix].max() == region.min() {
467 ix += 1;
468 }
469
470 if ix < self.regions.len() {
471 let occ = &self.regions[ix];
473 let is_eq = occ.min() == region.min() && occ.max() == region.max();
474 let is_intersect_before = region.min() >= occ.min() && occ.max() > region.min();
475 if is_eq || is_intersect_before {
476 return (occ.min(), occ.max());
477 }
478 }
479
480 let mut last = self.search(region.max());
482 if last < self.regions.len() && self.regions[last].min() < region.max() {
483 last += 1;
484 }
485 remove_n_at(&mut self.regions, ix, last - ix);
486
487 if ix == self.regions.len() {
488 self.regions.push(region);
489 } else {
490 self.regions.insert(ix, region);
491 }
492
493 (self.regions[ix].min(), self.regions[ix].max())
494 }
495
496 pub fn apply_delta(&self, delta: &RopeDelta, after: bool, drift: InsertDrift) -> Selection {
503 let mut result = Selection::new();
504 let mut transformer = Transformer::new(delta);
505 for region in self.regions() {
506 let is_region_forward = region.start < region.end;
507
508 let (start_after, end_after) = match (drift, region.is_caret()) {
509 (InsertDrift::Inside, false) => (!is_region_forward, is_region_forward),
510 (InsertDrift::Outside, false) => (is_region_forward, !is_region_forward),
511 _ => (after, after),
512 };
513
514 let new_region = SelRegion::new(
515 transformer.transform(region.start, start_after),
516 transformer.transform(region.end, end_after),
517 None,
518 );
519 result.add_region(new_region);
520 }
521 result
522 }
523
524 pub fn get_cursor_offset(&self) -> usize {
526 if self.is_empty() {
527 return 0;
528 }
529 self.regions[self.last_inserted].end
530 }
531
532 pub fn replace_last_inserted_region(&mut self, region: SelRegion) {
534 if self.is_empty() {
535 self.add_region(region);
536 return;
537 }
538
539 self.regions.remove(self.last_inserted);
540 self.add_region(region);
541 }
542
543 fn search(&self, offset: usize) -> usize {
544 if self.regions.is_empty() || offset > self.regions.last().unwrap().max() {
545 return self.regions.len();
546 }
547 match self.regions.binary_search_by(|r| r.max().cmp(&offset)) {
548 Ok(ix) => ix,
549 Err(ix) => ix,
550 }
551 }
552
553 fn search_min(&self, offset: usize) -> usize {
554 if self.regions.is_empty() || offset > self.regions.last().unwrap().max() {
555 return self.regions.len();
556 }
557 match self
558 .regions
559 .binary_search_by(|r| r.min().cmp(&(offset + 1)))
560 {
561 Ok(ix) => ix,
562 Err(ix) => ix,
563 }
564 }
565}
566
567impl Default for Selection {
568 fn default() -> Self {
569 Self::new()
570 }
571}
572
573fn remove_n_at<T>(v: &mut Vec<T>, index: usize, n: usize) {
574 match n.cmp(&1) {
575 Ordering::Equal => {
576 v.remove(index);
577 }
578 Ordering::Greater => {
579 v.drain(index..index + n);
580 }
581 _ => (),
582 };
583}
584
585#[cfg(test)]
586mod test {
587 use crate::{
588 buffer::Buffer,
589 editor::EditType,
590 selection::{InsertDrift, SelRegion, Selection},
591 };
592
593 #[test]
594 fn should_return_selection_region_min() {
595 let region = SelRegion::new(1, 10, None);
596 assert_eq!(region.min(), region.start);
597
598 let region = SelRegion::new(42, 1, None);
599 assert_eq!(region.min(), region.end);
600 }
601
602 #[test]
603 fn should_return_selection_region_max() {
604 let region = SelRegion::new(1, 10, None);
605 assert_eq!(region.max(), region.end);
606
607 let region = SelRegion::new(42, 1, None);
608 assert_eq!(region.max(), region.start);
609 }
610
611 #[test]
612 fn is_caret_should_return_true() {
613 let region = SelRegion::new(1, 10, None);
614 assert!(!region.is_caret());
615 }
616
617 #[test]
618 fn is_caret_should_return_false() {
619 let region = SelRegion::new(1, 1, None);
620 assert!(region.is_caret());
621 }
622
623 #[test]
624 fn should_merge_regions() {
625 let region = SelRegion::new(1, 2, None);
626 let other = SelRegion::new(3, 4, None);
627 assert_eq!(region.merge_with(other), SelRegion::new(1, 4, None));
628
629 let region = SelRegion::new(2, 1, None);
630 let other = SelRegion::new(4, 3, None);
631 assert_eq!(region.merge_with(other), SelRegion::new(4, 1, None));
632
633 let region = SelRegion::new(1, 1, None);
634 let other = SelRegion::new(6, 6, None);
635 assert_eq!(region.merge_with(other), SelRegion::new(1, 6, None));
636 }
637
638 #[test]
639 fn selection_should_be_caret() {
640 let mut selection = Selection::new();
641 selection.add_region(SelRegion::caret(1));
642 selection.add_region(SelRegion::caret(6));
643 assert!(selection.is_caret());
644 }
645
646 #[test]
647 fn selection_should_not_be_caret() {
648 let mut selection = Selection::new();
649 selection.add_region(SelRegion::caret(1));
650 selection.add_region(SelRegion::new(4, 6, None));
651 assert!(!selection.is_caret());
652 }
653
654 #[test]
655 fn should_return_min_selection() {
656 let mut selection = Selection::new();
657 selection.add_region(SelRegion::new(1, 3, None));
658 selection.add_region(SelRegion::new(4, 6, None));
659 assert_eq!(
660 selection.min().regions,
661 vec![SelRegion::caret(1), SelRegion::caret(4)]
662 );
663 }
664
665 #[test]
666 fn selection_should_contains_region() {
667 let selection = Selection::region(0, 2);
668 assert!(selection.contains(0));
669 assert!(selection.contains(1));
670 assert!(selection.contains(2));
671 assert!(!selection.contains(3));
672 }
673
674 #[test]
675 fn should_return_last_inserted_region() {
676 let mut selection = Selection::region(5, 6);
677 selection.add_region(SelRegion::caret(1));
678 assert_eq!(selection.last_inserted(), Some(&SelRegion::caret(1)));
679 }
680
681 #[test]
682 fn should_return_last_region() {
683 let mut selection = Selection::region(5, 6);
684 selection.add_region(SelRegion::caret(1));
685 assert_eq!(selection.last(), Some(&SelRegion::new(5, 6, None)));
686 }
687
688 #[test]
689 fn should_return_first_region() {
690 let mut selection = Selection::region(5, 6);
691 selection.add_region(SelRegion::caret(1));
692 assert_eq!(selection.first(), Some(&SelRegion::caret(1)));
693 }
694
695 #[test]
696 fn should_return_regions_in_range() {
697 let mut selection = Selection::new();
698 selection.add_region(SelRegion::new(0, 3, None));
699 selection.add_region(SelRegion::new(3, 6, None));
700 selection.add_region(SelRegion::new(7, 8, None));
701 selection.add_region(SelRegion::new(9, 11, None));
702
703 let regions = selection.regions_in_range(5, 10);
704
705 assert_eq!(
706 regions,
707 vec![
708 SelRegion::new(3, 6, None),
709 SelRegion::new(7, 8, None),
710 SelRegion::new(9, 11, None),
711 ]
712 );
713 }
714
715 #[test]
716 fn should_return_regions_in_full_range() {
717 let mut selection = Selection::new();
718 selection.add_region(SelRegion::new(0, 3, None));
719 selection.add_region(SelRegion::new(3, 6, None));
720 selection.add_region(SelRegion::new(7, 8, None));
721 selection.add_region(SelRegion::new(9, 11, None));
722
723 let regions = selection.full_regions_in_range(5, 10);
724
725 assert_eq!(
726 regions,
727 vec![SelRegion::new(7, 8, None), SelRegion::new(9, 11, None),]
728 );
729 }
730
731 #[test]
732 fn should_delete_regions() {
733 let mut selection = Selection::new();
734 selection.add_region(SelRegion::new(0, 3, None));
735 selection.add_region(SelRegion::new(3, 6, None));
736 selection.add_region(SelRegion::new(7, 8, None));
737 selection.add_region(SelRegion::new(9, 11, None));
738 selection.delete_range(5, 10);
739 assert_eq!(selection.regions(), vec![SelRegion::new(0, 3, None)]);
740 }
741
742 #[test]
743 fn should_add_regions() {
744 let mut selection = Selection::new();
745 selection.add_region(SelRegion::new(0, 3, None));
746 selection.add_region(SelRegion::new(3, 6, None));
747 assert_eq!(
748 selection.regions(),
749 vec![SelRegion::new(0, 3, None), SelRegion::new(3, 6, None),]
750 );
751 }
752
753 #[test]
754 fn should_add_and_merge_regions() {
755 let mut selection = Selection::new();
756
757 selection.add_region(SelRegion::new(0, 4, None));
758 selection.add_region(SelRegion::new(3, 6, None));
759 assert_eq!(selection.regions(), vec![SelRegion::new(0, 6, None)]);
760 }
761
762 #[test]
763 fn should_apply_delta_after_insertion() {
764 let selection = Selection::caret(0);
765
766 let (_, mock_delta, _) = {
767 let mut buffer = Buffer::new("");
768 buffer.edit(&[(selection.clone(), "Hello")], EditType::InsertChars)
769 };
770
771 assert_eq!(
772 selection.apply_delta(&mock_delta, true, InsertDrift::Inside),
773 Selection::caret(5)
774 );
775 }
776}