1use {
2 crate::{
3 layout::Layout,
4 str::StrExt,
5 text::{Edit, Length, Position},
6 },
7 std::{ops, ops::Deref, slice::Iter},
8};
9
10#[derive(Clone, Copy, Debug, Default, PartialEq, Hash, Eq)]
11pub struct Selection {
12 pub cursor: Cursor,
13 pub anchor: Position,
14}
15
16impl Selection {
17 pub fn is_empty(self) -> bool {
18 self.anchor == self.cursor.position
19 }
20
21 pub fn overlaps_with(self, other: Self) -> bool {
22 if self.is_empty() || other.is_empty() {
23 self.end() >= other.start()
24 } else {
25 self.end() > other.start()
26 }
27 }
28
29 pub fn start(self) -> Position {
30 self.cursor.position.min(self.anchor)
31 }
32
33 pub fn start_affinity(self) -> Affinity {
34 if self.anchor < self.cursor.position {
35 Affinity::After
36 } else {
37 self.cursor.affinity
38 }
39 }
40
41 pub fn end(self) -> Position {
42 self.cursor.position.max(self.anchor)
43 }
44
45 pub fn end_affinity(self) -> Affinity {
46 if self.cursor.position < self.anchor {
47 Affinity::Before
48 } else {
49 self.cursor.affinity
50 }
51 }
52
53 pub fn length(self) -> Length {
54 self.end() - self.start()
55 }
56
57 pub fn line_range(self) -> ops::Range<usize> {
58 if self.anchor <= self.cursor.position {
59 self.anchor.line_index..self.cursor.position.line_index + 1
60 } else {
61 self.cursor.position.line_index..if self.anchor.byte_index == 0 {
62 self.anchor.line_index
63 } else {
64 self.anchor.line_index + 1
65 }
66 }
67 }
68
69 pub fn update_cursor(self, f: impl FnOnce(Cursor) -> Cursor) -> Self {
70 Self {
71 cursor: f(self.cursor),
72 ..self
73 }
74 }
75
76 pub fn reset_anchor(self) -> Self {
77 Self {
78 anchor: self.cursor.position,
79 ..self
80 }
81 }
82
83 pub fn merge_with(self, other: Self) -> Option<Self> {
84 if self.overlaps_with(other) {
85 Some(if self.anchor <= self.cursor.position {
86 Selection {
87 anchor: self.anchor,
88 cursor: other.cursor,
89 }
90 } else {
91 Selection {
92 anchor: other.anchor,
93 cursor: self.cursor,
94 }
95 })
96 } else {
97 None
98 }
99 }
100
101 pub fn apply_edit(self, edit: &Edit) -> Self {
102 Self {
103 anchor: self.anchor.apply_edit(edit),
104 cursor: self.cursor.apply_edit(edit),
105 ..self
106 }
107 }
108}
109
110impl From<Cursor> for Selection {
111 fn from(cursor: Cursor) -> Self {
112 Self {
113 cursor,
114 anchor: cursor.position,
115 }
116 }
117}
118
119#[derive(Clone, Debug, Eq, Hash, PartialEq)]
120pub struct SelectionSet {
121 selections: Vec<Selection>,
122}
123
124impl SelectionSet {
125 pub fn new() -> Self {
126 Self::default()
127 }
128
129 pub fn as_selections(&self) -> &[Selection] {
130 &self.selections
131 }
132
133 pub fn update_selection(
134 &mut self,
135 index: usize,
136 f: impl FnOnce(Selection) -> Selection,
137 ) -> usize {
138 self.selections[index] = f(self.selections[index]);
139 self.remove_overlapping_selections(index)
140 }
141
142 pub fn update_all_selections(
143 &mut self,
144 retained_index: Option<usize>,
145 mut f: impl FnMut(Selection) -> Selection,
146 ) -> Option<usize> {
147 for selection in &mut self.selections {
148 *selection = f(*selection);
149 }
150 let mut index = retained_index;
151 let mut current_index = 0;
152 while current_index + 1 < self.selections.len() {
153 let next_index = current_index + 1;
154 let current_selection = self.selections[current_index];
155 let next_selection = self.selections[next_index];
156 assert!(current_selection.start() <= next_selection.start());
157 if let Some(merged_selection) = current_selection.merge_with(next_selection) {
158 self.selections[current_index] = merged_selection;
159 self.selections.remove(next_index);
160 if let Some(index) = &mut index {
161 if next_index <= *index {
162 *index -= 1;
163 }
164 }
165 } else {
166 current_index += 1;
167 }
168 }
169 index
170 }
171
172 pub fn apply_edit(&mut self, edit: &Edit) {
173 for selection in &mut self.selections {
174 *selection = selection.apply_edit(edit);
175 }
176 }
177
178 pub fn add_selection(&mut self, selection: Selection) -> usize {
179 let index = match self
180 .selections
181 .binary_search_by_key(&selection.start(), |selection| selection.start())
182 {
183 Ok(index) => {
184 self.selections[index] = selection;
185 index
186 }
187 Err(index) => {
188 self.selections.insert(index, selection);
189 index
190 }
191 };
192 self.remove_overlapping_selections(index)
193 }
194
195 pub fn set_selection(&mut self, selection: Selection) {
196 self.selections.clear();
197 self.selections.push(selection);
198 }
199
200 fn remove_overlapping_selections(&mut self, index: usize) -> usize {
201 let mut index = index;
202 while index > 0 {
203 let prev_index = index - 1;
204 if !self.selections[prev_index].overlaps_with(self.selections[index]) {
205 break;
206 }
207 self.selections.remove(prev_index);
208 index -= 1;
209 }
210 while index + 1 < self.selections.len() {
211 let next_index = index + 1;
212 if !self.selections[index].overlaps_with(self.selections[next_index]) {
213 break;
214 }
215 self.selections.remove(next_index);
216 }
217 index
218 }
219}
220
221impl Default for SelectionSet {
222 fn default() -> Self {
223 Self {
224 selections: vec![Selection::default()],
225 }
226 }
227}
228
229impl Deref for SelectionSet {
230 type Target = [Selection];
231
232 fn deref(&self) -> &Self::Target {
233 &self.selections
234 }
235}
236
237impl<'a> IntoIterator for &'a SelectionSet {
238 type Item = &'a Selection;
239 type IntoIter = Iter<'a, Selection>;
240
241 fn into_iter(self) -> Self::IntoIter {
242 self.iter()
243 }
244}
245
246#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
247pub struct Cursor {
248 pub position: Position,
249 pub affinity: Affinity,
250 pub preferred_column_index: Option<usize>,
251}
252
253impl Cursor {
254 pub fn is_at_first_line(self) -> bool {
255 self.position.line_index == 0
256 }
257
258 pub fn is_at_last_line(self, line_count: usize) -> bool {
259 self.position.line_index == line_count - 1
260 }
261
262 pub fn is_at_start_of_line(self) -> bool {
263 self.position.byte_index == 0
264 }
265
266 pub fn is_at_end_of_line(self, lines: &[String]) -> bool {
267 self.position.byte_index == lines[self.position.line_index].len()
268 }
269
270 pub fn is_at_first_row_of_line(self, layout: &Layout<'_>) -> bool {
271 let (row, _) = layout
272 .line(self.position.line_index)
273 .logical_to_grid_position(self.position.byte_index, self.affinity);
274 row == 0
275 }
276
277 pub fn is_at_last_row_of_line(self, layout: &Layout<'_>) -> bool {
278 let line = layout.line(self.position.line_index);
279 let (row, _) = line.logical_to_grid_position(self.position.byte_index, self.affinity);
280 row == line.row_count() - 1
281 }
282
283 pub fn move_left(self, lines: &[String]) -> Self {
284 if !self.is_at_start_of_line() {
285 return self.move_to_prev_grapheme(lines);
286 }
287 if !self.is_at_first_line() {
288 return self.move_to_end_of_prev_line(lines);
289 }
290 self
291 }
292
293 pub fn move_right(self, lines: &[String]) -> Self {
294 if !self.is_at_end_of_line(lines) {
295 return self.move_to_next_grapheme(lines);
296 }
297 if !self.is_at_last_line(lines.len()) {
298 return self.move_to_start_of_next_line();
299 }
300 self
301 }
302
303 pub fn move_up(self, layout: &Layout<'_>) -> Self {
304 if !self.is_at_first_row_of_line(layout) {
305 return self.move_to_prev_row_of_line(layout);
306 }
307 if !self.is_at_first_line() {
308 return self.move_to_last_row_of_prev_line(layout);
309 }
310 self
311 }
312
313 pub fn move_down(self, layout: &Layout<'_>) -> Self {
314 if !self.is_at_last_row_of_line(layout) {
315 return self.move_to_next_row_of_line(layout);
316 }
317 if !self.is_at_last_line(layout.as_text().as_lines().len()) {
318 return self.move_to_first_row_of_next_line(layout);
319 }
320 self
321 }
322
323 pub fn move_to_prev_grapheme(self, lines: &[String]) -> Self {
324 Self {
325 position: Position {
326 line_index: self.position.line_index,
327 byte_index: lines[self.position.line_index][..self.position.byte_index]
328 .grapheme_indices()
329 .next_back()
330 .map(|(index, _)| index)
331 .unwrap(),
332 },
333 affinity: Affinity::After,
334 preferred_column_index: None,
335 }
336 }
337
338 pub fn move_to_next_grapheme(self, lines: &[String]) -> Self {
339 let line = &lines[self.position.line_index];
340 Self {
341 position: Position {
342 line_index: self.position.line_index,
343 byte_index: line[self.position.byte_index..]
344 .grapheme_indices()
345 .nth(1)
346 .map(|(index, _)| self.position.byte_index + index)
347 .unwrap_or(line.len()),
348 },
349 affinity: Affinity::Before,
350 preferred_column_index: None,
351 }
352 }
353
354 pub fn move_to_end_of_prev_line(self, lines: &[String]) -> Self {
355 let prev_line_index = self.position.line_index - 1;
356 Self {
357 position: Position {
358 line_index: prev_line_index,
359 byte_index: lines[prev_line_index].len(),
360 },
361 affinity: Affinity::After,
362 preferred_column_index: None,
363 }
364 }
365
366 pub fn move_to_start_of_next_line(self) -> Self {
367 Self {
368 position: Position {
369 line_index: self.position.line_index + 1,
370 byte_index: 0,
371 },
372 affinity: Affinity::Before,
373 preferred_column_index: None,
374 }
375 }
376
377 pub fn move_to_prev_row_of_line(self, layout: &Layout<'_>) -> Self {
378 let line = layout.line(self.position.line_index);
379 let (row_index, mut column_index) =
380 line.logical_to_grid_position(self.position.byte_index, self.affinity);
381 if let Some(preferred_column_index) = self.preferred_column_index {
382 column_index = preferred_column_index;
383 }
384 let (byte_index, affinity) = line.grid_to_logical_position(row_index - 1, column_index);
385 Self {
386 position: Position {
387 line_index: self.position.line_index,
388 byte_index,
389 },
390 affinity,
391 preferred_column_index: Some(column_index),
392 }
393 }
394
395 pub fn move_to_next_row_of_line(self, layout: &Layout<'_>) -> Self {
396 let line = layout.line(self.position.line_index);
397 let (row_index, mut column_index) =
398 line.logical_to_grid_position(self.position.byte_index, self.affinity);
399 if let Some(preferred_column_index) = self.preferred_column_index {
400 column_index = preferred_column_index;
401 }
402 let (byte, affinity) = line.grid_to_logical_position(row_index + 1, column_index);
403 Self {
404 position: Position {
405 line_index: self.position.line_index,
406 byte_index: byte,
407 },
408 affinity,
409 preferred_column_index: Some(column_index),
410 }
411 }
412
413 pub fn move_to_last_row_of_prev_line(self, layout: &Layout<'_>) -> Self {
414 let line = layout.line(self.position.line_index);
415 let (_, mut column_index) =
416 line.logical_to_grid_position(self.position.byte_index, self.affinity);
417 if let Some(preferred_column_index) = self.preferred_column_index {
418 column_index = preferred_column_index;
419 }
420 let prev_line = layout.line(self.position.line_index - 1);
421 let (byte_index, affinity) =
422 prev_line.grid_to_logical_position(prev_line.row_count() - 1, column_index);
423 Self {
424 position: Position {
425 line_index: self.position.line_index - 1,
426 byte_index,
427 },
428 affinity,
429 preferred_column_index: Some(column_index),
430 }
431 }
432
433 pub fn move_to_first_row_of_next_line(self, layout: &Layout<'_>) -> Self {
434 let line = layout.line(self.position.line_index);
435 let (_, mut column_index) =
436 line.logical_to_grid_position(self.position.byte_index, self.affinity);
437 if let Some(preferred_column_index) = self.preferred_column_index {
438 column_index = preferred_column_index;
439 }
440 let next_line = layout.line(self.position.line_index + 1);
441 let (byte_index, affinity) = next_line.grid_to_logical_position(0, column_index);
442 Self {
443 position: Position {
444 line_index: self.position.line_index + 1,
445 byte_index,
446 },
447 affinity,
448 preferred_column_index: Some(column_index),
449 }
450 }
451
452 pub fn apply_edit(self, edit: &Edit) -> Self {
453 Self {
454 position: self.position.apply_edit(edit),
455 ..self
456 }
457 }
458}
459
460impl From<Position> for Cursor {
461 fn from(position: Position) -> Self {
462 Self {
463 position,
464 affinity: Affinity::Before,
465 preferred_column_index: None,
466 }
467 }
468}
469
470#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
471pub enum Affinity {
472 Before,
473 After,
474}
475
476impl Default for Affinity {
477 fn default() -> Self {
478 Self::Before
479 }
480}