1use crate::model::event::CursorId;
2use std::collections::HashMap;
3use std::ops::Range;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
7pub enum SelectionMode {
8 #[default]
10 Normal,
11 Block,
13}
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub struct Position2D {
18 pub line: usize,
19 pub column: usize,
20}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub struct Cursor {
25 pub position: usize,
27
28 pub anchor: Option<usize>,
30
31 pub sticky_column: usize,
34
35 pub selection_mode: SelectionMode,
37
38 pub block_anchor: Option<Position2D>,
41
42 pub deselect_on_move: bool,
45}
46
47impl Cursor {
48 pub fn new(position: usize) -> Self {
50 Self {
51 position,
52 anchor: None,
53 sticky_column: 0,
54 selection_mode: SelectionMode::Normal,
55 block_anchor: None,
56 deselect_on_move: true, }
58 }
59
60 pub fn with_selection(start: usize, end: usize) -> Self {
62 Self {
63 position: end,
64 anchor: Some(start),
65 sticky_column: 0,
66 selection_mode: SelectionMode::Normal,
67 block_anchor: None,
68 deselect_on_move: true, }
70 }
71
72 pub fn collapsed(&self) -> bool {
74 self.anchor.is_none() && self.block_anchor.is_none()
75 }
76
77 pub fn selection_range(&self) -> Option<Range<usize>> {
79 self.anchor.map(|anchor| {
80 if anchor < self.position {
81 anchor..self.position
82 } else {
83 self.position..anchor
84 }
85 })
86 }
87
88 pub fn has_block_selection(&self) -> bool {
90 self.selection_mode == SelectionMode::Block && self.block_anchor.is_some()
91 }
92
93 pub fn block_selection_bounds(&self) -> Option<(usize, usize, usize, usize)> {
96 if self.selection_mode != SelectionMode::Block {
97 return None;
98 }
99 self.block_anchor.map(|anchor| {
100 (anchor.line, anchor.column, anchor.line, anchor.column)
104 })
105 }
106
107 pub fn selection_start(&self) -> usize {
109 self.anchor.map_or(self.position, |a| a.min(self.position))
110 }
111
112 pub fn selection_end(&self) -> usize {
114 self.anchor.map_or(self.position, |a| a.max(self.position))
115 }
116
117 pub fn clear_selection(&mut self) {
119 self.anchor = None;
120 self.block_anchor = None;
121 self.selection_mode = SelectionMode::Normal;
122 }
123
124 pub fn set_anchor(&mut self, anchor: usize) {
126 self.anchor = Some(anchor);
127 }
128
129 pub fn start_block_selection(&mut self, line: usize, column: usize) {
131 self.selection_mode = SelectionMode::Block;
132 self.block_anchor = Some(Position2D { line, column });
133 }
136
137 pub fn clear_block_selection(&mut self) {
139 self.selection_mode = SelectionMode::Normal;
140 self.block_anchor = None;
141 }
142
143 pub fn move_to(&mut self, position: usize, extend_selection: bool) {
145 if extend_selection {
146 if self.anchor.is_none() {
147 self.anchor = Some(self.position);
148 }
149 } else {
150 self.anchor = None;
151 if !extend_selection && self.selection_mode == SelectionMode::Block {
153 self.selection_mode = SelectionMode::Normal;
154 self.block_anchor = None;
155 }
156 }
157 self.position = position;
158 }
159
160 pub fn adjust_for_edit(&mut self, edit_pos: usize, old_len: usize, new_len: usize) {
163 let delta = new_len as isize - old_len as isize;
164
165 if edit_pos <= self.position {
166 if edit_pos + old_len <= self.position {
167 self.position = (self.position as isize + delta).max(0) as usize;
169 } else {
170 self.position = edit_pos + new_len;
172 }
173 }
174
175 if let Some(anchor) = self.anchor {
177 if edit_pos <= anchor {
178 if edit_pos + old_len <= anchor {
179 self.anchor = Some((anchor as isize + delta).max(0) as usize);
180 } else {
181 self.anchor = Some(edit_pos + new_len);
182 }
183 }
184 }
185 }
186}
187
188#[derive(Debug, Clone)]
190pub struct Cursors {
191 cursors: HashMap<CursorId, Cursor>,
193
194 next_id: usize,
196
197 primary_id: CursorId,
199}
200
201impl Cursors {
202 pub fn new() -> Self {
204 let primary_id = CursorId(0);
205 let mut cursors = HashMap::new();
206 cursors.insert(primary_id, Cursor::new(0));
207
208 Self {
209 cursors,
210 next_id: 1,
211 primary_id,
212 }
213 }
214
215 pub fn primary(&self) -> &Cursor {
217 self.cursors
218 .get(&self.primary_id)
219 .expect("Primary cursor should always exist")
220 }
221
222 pub fn primary_mut(&mut self) -> &mut Cursor {
224 self.cursors
225 .get_mut(&self.primary_id)
226 .expect("Primary cursor should always exist")
227 }
228
229 pub fn primary_id(&self) -> CursorId {
231 self.primary_id
232 }
233
234 pub fn get(&self, id: CursorId) -> Option<&Cursor> {
236 self.cursors.get(&id)
237 }
238
239 pub fn get_mut(&mut self, id: CursorId) -> Option<&mut Cursor> {
241 self.cursors.get_mut(&id)
242 }
243
244 pub fn add(&mut self, cursor: Cursor) -> CursorId {
246 let id = CursorId(self.next_id);
247 self.next_id += 1;
248 self.cursors.insert(id, cursor);
249 self.primary_id = id; id
251 }
252
253 pub fn insert_with_id(&mut self, id: CursorId, cursor: Cursor) {
255 self.cursors.insert(id, cursor);
256 self.primary_id = id; if id.0 >= self.next_id {
259 self.next_id = id.0 + 1;
260 }
261 }
262
263 pub fn remove(&mut self, id: CursorId) -> Option<Cursor> {
265 if self.cursors.len() <= 1 {
267 return None;
268 }
269
270 let cursor = self.cursors.remove(&id);
271
272 if id == self.primary_id {
274 self.primary_id = *self
275 .cursors
276 .keys()
277 .next()
278 .expect("Should have at least one cursor remaining");
279 }
280
281 cursor
282 }
283
284 pub fn remove_secondary(&mut self) {
287 let first_id = *self
289 .cursors
290 .keys()
291 .min_by_key(|id| id.0)
292 .expect("Should have at least one cursor");
293 let first_cursor = *self
294 .cursors
295 .get(&first_id)
296 .expect("First cursor should exist");
297
298 self.cursors.clear();
299 self.cursors.insert(first_id, first_cursor);
300 self.primary_id = first_id; }
302
303 pub fn ids(&self) -> Vec<CursorId> {
305 self.cursors.keys().copied().collect()
306 }
307
308 pub fn iter(&self) -> impl Iterator<Item = (CursorId, &Cursor)> {
310 self.cursors.iter().map(|(id, c)| (*id, c))
311 }
312
313 pub fn count(&self) -> usize {
315 self.cursors.len()
316 }
317
318 pub fn map<F>(&mut self, mut f: F)
320 where
321 F: FnMut(&mut Cursor),
322 {
323 for cursor in self.cursors.values_mut() {
324 f(cursor);
325 }
326 }
327
328 pub fn adjust_for_edit(&mut self, edit_pos: usize, old_len: usize, new_len: usize) {
330 for cursor in self.cursors.values_mut() {
331 cursor.adjust_for_edit(edit_pos, old_len, new_len);
332 }
333 }
334
335 pub fn normalize(&mut self) {
337 let mut cursor_list: Vec<(CursorId, Cursor)> =
339 self.cursors.iter().map(|(id, c)| (*id, *c)).collect();
340
341 cursor_list.sort_by_key(|(_, c)| c.selection_start());
342
343 cursor_list.dedup_by(|(_, a), (_, b)| a.position == b.position && a.anchor == b.anchor);
345
346 self.cursors.clear();
348 for (id, cursor) in cursor_list {
349 self.cursors.insert(id, cursor);
350 }
351
352 if !self.cursors.contains_key(&self.primary_id) {
354 if let Some(id) = self.cursors.keys().next() {
355 self.primary_id = *id;
356 }
357 }
358 }
359
360 pub fn positions(&self) -> Vec<usize> {
362 self.cursors.values().map(|c| c.position).collect()
363 }
364
365 pub fn selections(&self) -> Vec<Range<usize>> {
367 self.cursors
368 .values()
369 .filter_map(|c| c.selection_range())
370 .collect()
371 }
372}
373
374impl Default for Cursors {
375 fn default() -> Self {
376 Self::new()
377 }
378}
379
380#[cfg(test)]
381mod tests {
382 use super::*;
383
384 #[test]
385 fn test_cursor_new() {
386 let cursor = Cursor::new(5);
387 assert_eq!(cursor.position, 5);
388 assert!(cursor.collapsed());
389 assert_eq!(cursor.selection_range(), None);
390 }
391
392 #[test]
393 fn test_cursor_with_selection() {
394 let cursor = Cursor::with_selection(5, 10);
395 assert_eq!(cursor.position, 10);
396 assert!(!cursor.collapsed());
397 assert_eq!(cursor.selection_range(), Some(5..10));
398 }
399
400 #[test]
401 fn test_cursor_move_to() {
402 let mut cursor = Cursor::new(5);
403 cursor.move_to(10, false);
404 assert_eq!(cursor.position, 10);
405 assert!(cursor.collapsed());
406
407 cursor.move_to(15, true);
408 assert_eq!(cursor.position, 15);
409 assert_eq!(cursor.selection_range(), Some(10..15));
410 }
411
412 #[test]
413 fn test_cursor_adjust_for_edit() {
414 let mut cursor = Cursor::new(10);
415
416 cursor.adjust_for_edit(5, 0, 3);
418 assert_eq!(cursor.position, 13);
419
420 cursor.adjust_for_edit(20, 5, 2);
422 assert_eq!(cursor.position, 13);
423 }
424
425 #[test]
426 fn test_cursors_new() {
427 let cursors = Cursors::new();
428 assert_eq!(cursors.count(), 1);
429 assert_eq!(cursors.primary().position, 0);
430 }
431
432 #[test]
433 fn test_cursors_add_remove() {
434 let mut cursors = Cursors::new();
435 let id = cursors.add(Cursor::new(10));
436 assert_eq!(cursors.count(), 2);
437 assert_eq!(cursors.get(id).unwrap().position, 10);
438
439 cursors.remove(id);
440 assert_eq!(cursors.count(), 1);
441 }
442
443 #[test]
444 fn test_cursors_remove_secondary() {
445 let mut cursors = Cursors::new();
446 cursors.add(Cursor::new(10));
447 cursors.add(Cursor::new(20));
448 assert_eq!(cursors.count(), 3);
449
450 cursors.remove_secondary();
451 assert_eq!(cursors.count(), 1);
452 }
453
454 #[test]
455 fn test_cursors_normalize() {
456 let mut cursors = Cursors::new();
457 cursors.add(Cursor::new(10));
458 cursors.add(Cursor::new(10)); cursors.normalize();
461 assert_eq!(cursors.count(), 2); }
463}