1use crate::{
2 editor::{
3 buffer::{Anchor, Buffer, Point, ToPoint},
4 display_map::{Bias, DisplayMap},
5 DisplayPoint,
6 },
7 time,
8};
9use gpui::AppContext;
10use std::{cmp::Ordering, mem, ops::Range};
11
12pub type SelectionSetId = time::Lamport;
13pub type SelectionsVersion = usize;
14
15#[derive(Clone, Debug, Eq, PartialEq)]
16pub struct Selection {
17 pub start: Anchor,
18 pub end: Anchor,
19 pub reversed: bool,
20 pub goal_column: Option<u32>,
21}
22
23impl Selection {
24 pub fn head(&self) -> &Anchor {
25 if self.reversed {
26 &self.start
27 } else {
28 &self.end
29 }
30 }
31
32 pub fn set_head(&mut self, buffer: &Buffer, cursor: Anchor) {
33 if cursor.cmp(self.tail(), buffer).unwrap() < Ordering::Equal {
34 if !self.reversed {
35 mem::swap(&mut self.start, &mut self.end);
36 self.reversed = true;
37 }
38 self.start = cursor;
39 } else {
40 if self.reversed {
41 mem::swap(&mut self.start, &mut self.end);
42 self.reversed = false;
43 }
44 self.end = cursor;
45 }
46 }
47
48 pub fn tail(&self) -> &Anchor {
49 if self.reversed {
50 &self.end
51 } else {
52 &self.start
53 }
54 }
55
56 pub fn range(&self, buffer: &Buffer) -> Range<Point> {
57 let start = self.start.to_point(buffer).unwrap();
58 let end = self.end.to_point(buffer).unwrap();
59 if self.reversed {
60 end..start
61 } else {
62 start..end
63 }
64 }
65
66 pub fn display_range(&self, map: &DisplayMap, app: &AppContext) -> Range<DisplayPoint> {
67 let start = self.start.to_display_point(map, app).unwrap();
68 let end = self.end.to_display_point(map, app).unwrap();
69 if self.reversed {
70 end..start
71 } else {
72 start..end
73 }
74 }
75
76 pub fn buffer_rows_for_display_rows(
77 &self,
78 map: &DisplayMap,
79 ctx: &AppContext,
80 ) -> (Range<u32>, Range<u32>) {
81 let display_start = self.start.to_display_point(map, ctx).unwrap();
82 let buffer_start = DisplayPoint::new(display_start.row(), 0)
83 .to_buffer_point(map, Bias::Left, ctx)
84 .unwrap();
85
86 let mut display_end = self.end.to_display_point(map, ctx).unwrap();
87 if display_end.row() != map.max_point(ctx).row()
88 && display_start.row() != display_end.row()
89 && display_end.column() == 0
90 {
91 *display_end.row_mut() -= 1;
92 }
93 let buffer_end = DisplayPoint::new(
94 display_end.row(),
95 map.line_len(display_end.row(), ctx).unwrap(),
96 )
97 .to_buffer_point(map, Bias::Left, ctx)
98 .unwrap();
99
100 (
101 buffer_start.row..buffer_end.row + 1,
102 display_start.row()..display_end.row() + 1,
103 )
104 }
105}